2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
33 Alias.c provides supervisory control for the functions of the
34 packet aliasing software. It consists of routines to monitor
35 TCP connection state, protocol-specific aliasing routines,
36 fragment handling and the following outside world functional
37 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
38 PacketAliasIn and PacketAliasOut.
40 The other C program files are briefly described. The data
41 structure framework which holds information needed to translate
42 packets is encapsulated in alias_db.c. Data is accessed by
43 function calls, so other segments of the program need not know
44 about the underlying data structures. Alias_ftp.c contains
45 special code for modifying the ftp PORT command used to establish
46 data connections, while alias_irc.c does the same for IRC
47 DCC. Alias_util.c contains a few utility routines.
49 Version 1.0 August, 1996 (cjm)
51 Version 1.1 August 20, 1996 (cjm)
52 PPP host accepts incoming connections for ports 0 to 1023.
53 (Gary Roberts pointed out the need to handle incoming
56 Version 1.2 September 7, 1996 (cjm)
57 Fragment handling error in alias_db.c corrected.
58 (Tom Torrance helped fix this problem.)
60 Version 1.4 September 16, 1996 (cjm)
61 - A more generalized method for handling incoming
62 connections, without the 0-1023 restriction, is
63 implemented in alias_db.c
64 - Improved ICMP support in alias.c. Traceroute
65 packet streams can now be correctly aliased.
66 - TCP connection closing logic simplified in
67 alias.c and now allows for additional 1 minute
68 "grace period" after FIN or RST is observed.
70 Version 1.5 September 17, 1996 (cjm)
71 Corrected error in handling incoming UDP packets with 0 checksum.
72 (Tom Torrance helped fix this problem.)
74 Version 1.6 September 18, 1996 (cjm)
75 Simplified ICMP aliasing scheme. Should now support
76 traceroute from Win95 as well as FreeBSD.
78 Version 1.7 January 9, 1997 (cjm)
79 - Out-of-order fragment handling.
80 - IP checksum error fixed for ftp transfers
82 - Integer return codes added to all
83 aliasing/de-aliasing functions.
84 - Some obsolete comments cleaned up.
85 - Differential checksum computations for
86 IP header (TCP, UDP and ICMP were already
89 Version 2.1 May 1997 (cjm)
90 - Added support for outgoing ICMP error
92 - Added two functions PacketAliasIn2()
93 and PacketAliasOut2() for dynamic address
94 control (e.g. round-robin allocation of
97 Version 2.2 July 1997 (cjm)
98 - Rationalized API function names to begin
100 - Eliminated PacketAliasIn2() and
101 PacketAliasOut2() as poorly conceived.
103 Version 2.3 Dec 1998 (dillon)
104 - Major bounds checking additions, see FreeBSD/CVS
106 Version 3.1 May, 2000 (salander)
107 - Added hooks to handle PPTP.
109 Version 3.2 July, 2000 (salander and satoh)
110 - Added PacketUnaliasOut routine.
111 - Added hooks to handle RTSP/RTP.
113 See HISTORY file for additional revisions.
117 #include <sys/param.h>
118 #include <sys/systm.h>
119 #include <sys/mbuf.h>
120 #include <sys/sysctl.h>
122 #include <sys/types.h>
131 #include <netinet/in_systm.h>
132 #include <netinet/in.h>
133 #include <netinet/ip.h>
134 #include <netinet/ip_icmp.h>
135 #include <netinet/tcp.h>
136 #include <netinet/udp.h>
139 #include <netinet/libalias/alias.h>
140 #include <netinet/libalias/alias_local.h>
141 #include <netinet/libalias/alias_mod.h>
145 #include "alias_local.h"
146 #include "alias_mod.h"
150 * Define libalias SYSCTL Node
154 SYSCTL_DECL(_net_inet);
155 SYSCTL_DECL(_net_inet_ip);
156 SYSCTL_NODE(_net_inet_ip, OID_AUTO, alias, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
157 "Libalias sysctl API");
166 #if BYTE_ORDER == LITTLE_ENDIAN
167 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
168 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
170 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
171 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
176 /* TCP Handling Routines
178 TcpMonitorIn() -- These routines monitor TCP connections, and
179 TcpMonitorOut() delete a link when a connection is closed.
181 These routines look for SYN, FIN and RST flags to determine when TCP
182 connections open and close. When a TCP connection closes, the data
183 structure containing packet aliasing information is deleted after
187 /* Local prototypes */
188 static void TcpMonitorIn(u_char, struct alias_link *);
190 static void TcpMonitorOut(u_char, struct alias_link *);
193 TcpMonitorIn(u_char th_flags, struct alias_link *lnk)
196 switch (GetStateIn(lnk)) {
197 case ALIAS_TCP_STATE_NOT_CONNECTED:
198 if (th_flags & TH_RST)
199 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
200 else if (th_flags & TH_SYN)
201 SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED);
203 case ALIAS_TCP_STATE_CONNECTED:
204 if (th_flags & (TH_FIN | TH_RST))
205 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
211 TcpMonitorOut(u_char th_flags, struct alias_link *lnk)
214 switch (GetStateOut(lnk)) {
215 case ALIAS_TCP_STATE_NOT_CONNECTED:
216 if (th_flags & TH_RST)
217 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
218 else if (th_flags & TH_SYN)
219 SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED);
221 case ALIAS_TCP_STATE_CONNECTED:
222 if (th_flags & (TH_FIN | TH_RST))
223 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
228 /* Protocol Specific Packet Aliasing Routines
230 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
231 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
232 ProtoAliasIn(), ProtoAliasOut()
233 UdpAliasIn(), UdpAliasOut()
234 TcpAliasIn(), TcpAliasOut()
236 These routines handle protocol specific details of packet aliasing.
237 One may observe a certain amount of repetitive arithmetic in these
238 functions, the purpose of which is to compute a revised checksum
239 without actually summing over the entire data packet, which could be
240 unnecessarily time consuming.
242 The purpose of the packet aliasing routines is to replace the source
243 address of the outgoing packet and then correctly put it back for
244 any incoming packets. For TCP and UDP, ports are also re-mapped.
246 For ICMP echo/timestamp requests and replies, the following scheme
247 is used: the ID number is replaced by an alias for the outgoing
250 ICMP error messages are handled by looking at the IP fragment
251 in the data section of the message.
253 For TCP and UDP protocols, a port number is chosen for an outgoing
254 packet, and then incoming packets are identified by IP address and
255 port numbers. For TCP packets, there is additional logic in the event
256 that sequence and ACK numbers have been altered (as in the case for
257 FTP data port commands).
259 The port numbers used by the packet aliasing module are not true
260 ports in the Unix sense. No sockets are actually bound to ports.
261 They are more correctly thought of as placeholders.
263 All packets go through the aliasing mechanism, whether they come from
264 the gateway machine or other machines on a local area network.
267 /* Local prototypes */
268 static int IcmpAliasIn1(struct libalias *, struct ip *);
269 static int IcmpAliasIn2(struct libalias *, struct ip *);
270 static int IcmpAliasIn(struct libalias *, struct ip *);
272 static int IcmpAliasOut1(struct libalias *, struct ip *, int create);
273 static int IcmpAliasOut2(struct libalias *, struct ip *);
274 static int IcmpAliasOut(struct libalias *, struct ip *, int create);
276 static int ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
277 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum);
278 static int ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
279 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum,
282 static int UdpAliasIn(struct libalias *, struct ip *);
283 static int UdpAliasOut(struct libalias *, struct ip *, int, int create);
285 static int TcpAliasIn(struct libalias *, struct ip *);
286 static int TcpAliasOut(struct libalias *, struct ip *, int, int create);
289 IcmpAliasIn1(struct libalias *la, struct ip *pip)
292 LIBALIAS_LOCK_ASSERT(la);
294 De-alias incoming echo and timestamp replies.
295 Alias incoming echo and timestamp requests.
297 struct alias_link *lnk;
300 ic = (struct icmp *)ip_next(pip);
302 /* Get source address from ICMP data field and restore original data */
303 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
308 original_id = GetOriginalPort(lnk);
310 /* Adjust ICMP checksum */
311 accumulate = ic->icmp_id;
312 accumulate -= original_id;
313 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
315 /* Put original sequence number back in */
316 ic->icmp_id = original_id;
318 /* Put original address back into IP header */
320 struct in_addr original_address;
322 original_address = GetOriginalAddress(lnk);
323 DifferentialChecksum(&pip->ip_sum,
324 &original_address, &pip->ip_dst, 2);
325 pip->ip_dst = original_address;
328 return (PKT_ALIAS_OK);
330 return (PKT_ALIAS_IGNORED);
334 IcmpAliasIn2(struct libalias *la, struct ip *pip)
337 LIBALIAS_LOCK_ASSERT(la);
339 Alias incoming ICMP error messages containing
340 IP header and first 64 bits of datagram.
343 struct icmp *ic, *ic2;
346 struct alias_link *lnk;
348 ic = (struct icmp *)ip_next(pip);
351 ud = (struct udphdr *)ip_next(ip);
352 tc = (struct tcphdr *)ip_next(ip);
353 ic2 = (struct icmp *)ip_next(ip);
355 if (ip->ip_p == IPPROTO_UDP)
356 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
357 ud->uh_dport, ud->uh_sport,
359 else if (ip->ip_p == IPPROTO_TCP)
360 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
361 tc->th_dport, tc->th_sport,
363 else if (ip->ip_p == IPPROTO_ICMP) {
364 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
365 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
372 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
373 int accumulate, accumulate2;
374 struct in_addr original_address;
375 u_short original_port;
377 original_address = GetOriginalAddress(lnk);
378 original_port = GetOriginalPort(lnk);
380 /* Adjust ICMP checksum */
381 accumulate = twowords(&ip->ip_src);
382 accumulate -= twowords(&original_address);
383 accumulate += ud->uh_sport;
384 accumulate -= original_port;
385 accumulate2 = accumulate;
386 accumulate2 += ip->ip_sum;
387 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
388 accumulate2 -= ip->ip_sum;
389 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
391 /* Un-alias address in IP header */
392 DifferentialChecksum(&pip->ip_sum,
393 &original_address, &pip->ip_dst, 2);
394 pip->ip_dst = original_address;
396 /* Un-alias address and port number of original IP packet
397 fragment contained in ICMP data section */
398 ip->ip_src = original_address;
399 ud->uh_sport = original_port;
400 } else if (ip->ip_p == IPPROTO_ICMP) {
401 int accumulate, accumulate2;
402 struct in_addr original_address;
405 original_address = GetOriginalAddress(lnk);
406 original_id = GetOriginalPort(lnk);
408 /* Adjust ICMP checksum */
409 accumulate = twowords(&ip->ip_src);
410 accumulate -= twowords(&original_address);
411 accumulate += ic2->icmp_id;
412 accumulate -= original_id;
413 accumulate2 = accumulate;
414 accumulate2 += ip->ip_sum;
415 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
416 accumulate2 -= ip->ip_sum;
417 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
419 /* Un-alias address in IP header */
420 DifferentialChecksum(&pip->ip_sum,
421 &original_address, &pip->ip_dst, 2);
422 pip->ip_dst = original_address;
424 /* Un-alias address of original IP packet and sequence number of
425 embedded ICMP datagram */
426 ip->ip_src = original_address;
427 ic2->icmp_id = original_id;
429 return (PKT_ALIAS_OK);
431 return (PKT_ALIAS_IGNORED);
435 IcmpAliasIn(struct libalias *la, struct ip *pip)
440 LIBALIAS_LOCK_ASSERT(la);
442 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
443 if (dlen < ICMP_MINLEN)
444 return (PKT_ALIAS_IGNORED);
446 /* Return if proxy-only mode is enabled */
447 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
448 return (PKT_ALIAS_OK);
450 ic = (struct icmp *)ip_next(pip);
452 iresult = PKT_ALIAS_IGNORED;
453 switch (ic->icmp_type) {
455 case ICMP_TSTAMPREPLY:
456 if (ic->icmp_code == 0) {
457 iresult = IcmpAliasIn1(la, pip);
461 case ICMP_SOURCEQUENCH:
464 if (dlen < ICMP_ADVLENMIN ||
465 dlen < ICMP_ADVLEN(ic))
466 return (PKT_ALIAS_IGNORED);
467 iresult = IcmpAliasIn2(la, pip);
471 iresult = IcmpAliasIn1(la, pip);
478 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
481 Alias outgoing echo and timestamp requests.
482 De-alias outgoing echo and timestamp replies.
484 struct alias_link *lnk;
487 LIBALIAS_LOCK_ASSERT(la);
488 ic = (struct icmp *)ip_next(pip);
490 /* Save overwritten data for when echo packet returns */
491 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create);
496 alias_id = GetAliasPort(lnk);
498 /* Since data field is being modified, adjust ICMP checksum */
499 accumulate = ic->icmp_id;
500 accumulate -= alias_id;
501 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
503 /* Alias sequence number */
504 ic->icmp_id = alias_id;
506 /* Change source address */
508 struct in_addr alias_address;
510 alias_address = GetAliasAddress(lnk);
511 DifferentialChecksum(&pip->ip_sum,
512 &alias_address, &pip->ip_src, 2);
513 pip->ip_src = alias_address;
516 return (PKT_ALIAS_OK);
518 return (PKT_ALIAS_IGNORED);
522 IcmpAliasOut2(struct libalias *la, struct ip *pip)
525 Alias outgoing ICMP error messages containing
526 IP header and first 64 bits of datagram.
529 struct icmp *ic, *ic2;
532 struct alias_link *lnk;
534 LIBALIAS_LOCK_ASSERT(la);
535 ic = (struct icmp *)ip_next(pip);
538 ud = (struct udphdr *)ip_next(ip);
539 tc = (struct tcphdr *)ip_next(ip);
540 ic2 = (struct icmp *)ip_next(ip);
542 if (ip->ip_p == IPPROTO_UDP)
543 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
544 ud->uh_dport, ud->uh_sport,
546 else if (ip->ip_p == IPPROTO_TCP)
547 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
548 tc->th_dport, tc->th_sport,
550 else if (ip->ip_p == IPPROTO_ICMP) {
551 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
552 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
559 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
561 struct in_addr alias_address;
564 alias_address = GetAliasAddress(lnk);
565 alias_port = GetAliasPort(lnk);
567 /* Adjust ICMP checksum */
568 accumulate = twowords(&ip->ip_dst);
569 accumulate -= twowords(&alias_address);
570 accumulate += ud->uh_dport;
571 accumulate -= alias_port;
572 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
575 * Alias address in IP header if it comes from the host
576 * the original TCP/UDP packet was destined for.
578 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
579 DifferentialChecksum(&pip->ip_sum,
580 &alias_address, &pip->ip_src, 2);
581 pip->ip_src = alias_address;
583 /* Alias address and port number of original IP packet
584 fragment contained in ICMP data section */
585 ip->ip_dst = alias_address;
586 ud->uh_dport = alias_port;
587 } else if (ip->ip_p == IPPROTO_ICMP) {
589 struct in_addr alias_address;
592 alias_address = GetAliasAddress(lnk);
593 alias_id = GetAliasPort(lnk);
595 /* Adjust ICMP checksum */
596 accumulate = twowords(&ip->ip_dst);
597 accumulate -= twowords(&alias_address);
598 accumulate += ic2->icmp_id;
599 accumulate -= alias_id;
600 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
603 * Alias address in IP header if it comes from the host
604 * the original ICMP message was destined for.
606 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
607 DifferentialChecksum(&pip->ip_sum,
608 &alias_address, &pip->ip_src, 2);
609 pip->ip_src = alias_address;
611 /* Alias address of original IP packet and sequence number of
612 embedded ICMP datagram */
613 ip->ip_dst = alias_address;
614 ic2->icmp_id = alias_id;
616 return (PKT_ALIAS_OK);
618 return (PKT_ALIAS_IGNORED);
622 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
627 LIBALIAS_LOCK_ASSERT(la);
630 /* Return if proxy-only mode is enabled */
631 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
632 return (PKT_ALIAS_OK);
634 ic = (struct icmp *)ip_next(pip);
636 iresult = PKT_ALIAS_IGNORED;
637 switch (ic->icmp_type) {
640 if (ic->icmp_code == 0) {
641 iresult = IcmpAliasOut1(la, pip, create);
645 case ICMP_SOURCEQUENCH:
648 iresult = IcmpAliasOut2(la, pip);
651 case ICMP_TSTAMPREPLY:
652 iresult = IcmpAliasOut1(la, pip, create);
658 ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
659 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum)
662 Handle incoming IP packets. The
663 only thing which is done in this case is to alias
664 the dest IP address of the packet to our inside
667 struct alias_link *lnk;
669 LIBALIAS_LOCK_ASSERT(la);
670 /* Return if proxy-only mode is enabled */
671 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
672 return (PKT_ALIAS_OK);
674 lnk = FindProtoIn(la, ip_src, *ip_dst, ip_p);
676 struct in_addr original_address;
678 original_address = GetOriginalAddress(lnk);
680 /* Restore original IP address */
681 DifferentialChecksum(ip_sum,
682 &original_address, ip_dst, 2);
683 *ip_dst = original_address;
685 return (PKT_ALIAS_OK);
687 return (PKT_ALIAS_IGNORED);
691 ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
692 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
695 Handle outgoing IP packets. The
696 only thing which is done in this case is to alias
697 the source IP address of the packet.
699 struct alias_link *lnk;
701 LIBALIAS_LOCK_ASSERT(la);
703 /* Return if proxy-only mode is enabled */
704 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
705 return (PKT_ALIAS_OK);
708 return (PKT_ALIAS_IGNORED);
710 lnk = FindProtoOut(la, *ip_src, ip_dst, ip_p);
712 struct in_addr alias_address;
714 alias_address = GetAliasAddress(lnk);
716 /* Change source address */
717 DifferentialChecksum(ip_sum,
718 &alias_address, ip_src, 2);
719 *ip_src = alias_address;
721 return (PKT_ALIAS_OK);
723 return (PKT_ALIAS_IGNORED);
727 UdpAliasIn(struct libalias *la, struct ip *pip)
730 struct alias_link *lnk;
733 LIBALIAS_LOCK_ASSERT(la);
735 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
736 if (dlen < sizeof(struct udphdr))
737 return (PKT_ALIAS_IGNORED);
739 ud = (struct udphdr *)ip_next(pip);
740 if (dlen < ntohs(ud->uh_ulen))
741 return (PKT_ALIAS_IGNORED);
743 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
744 ud->uh_sport, ud->uh_dport,
745 IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
747 struct in_addr alias_address;
748 struct in_addr original_address;
749 struct in_addr proxy_address;
754 struct alias_data ad = {
756 .oaddr = &original_address,
757 .aaddr = &alias_address,
758 .aport = &alias_port,
759 .sport = &ud->uh_sport,
760 .dport = &ud->uh_dport,
764 alias_address = GetAliasAddress(lnk);
765 original_address = GetOriginalAddress(lnk);
766 proxy_address = GetProxyAddress(lnk);
767 alias_port = ud->uh_dport;
768 ud->uh_dport = GetOriginalPort(lnk);
769 proxy_port = GetProxyPort(lnk);
771 /* Walk out chain. */
772 error = find_handler(IN, UDP, la, pip, &ad);
773 /* If we cannot figure out the packet, ignore it. */
775 return (PKT_ALIAS_IGNORED);
777 /* If UDP checksum is not zero, then adjust since destination port */
778 /* is being unaliased and destination address is being altered. */
779 if (ud->uh_sum != 0) {
780 accumulate = alias_port;
781 accumulate -= ud->uh_dport;
782 accumulate += twowords(&alias_address);
783 accumulate -= twowords(&original_address);
785 /* If this is a proxy packet, modify checksum because of source change.*/
786 if (proxy_port != 0) {
787 accumulate += ud->uh_sport;
788 accumulate -= proxy_port;
791 if (proxy_address.s_addr != 0) {
792 accumulate += twowords(&pip->ip_src);
793 accumulate -= twowords(&proxy_address);
796 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
798 /* XXX: Could the two if's below be concatenated to one ? */
799 /* Restore source port and/or address in case of proxying*/
802 ud->uh_sport = proxy_port;
804 if (proxy_address.s_addr != 0) {
805 DifferentialChecksum(&pip->ip_sum,
806 &proxy_address, &pip->ip_src, 2);
807 pip->ip_src = proxy_address;
810 /* Restore original IP address */
811 DifferentialChecksum(&pip->ip_sum,
812 &original_address, &pip->ip_dst, 2);
813 pip->ip_dst = original_address;
815 return (PKT_ALIAS_OK);
817 return (PKT_ALIAS_IGNORED);
821 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
824 struct alias_link *lnk;
825 struct in_addr dest_address;
826 struct in_addr proxy_server_address;
828 u_short proxy_server_port;
832 LIBALIAS_LOCK_ASSERT(la);
834 /* Return if proxy-only mode is enabled and not proxyrule found.*/
835 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
836 if (dlen < sizeof(struct udphdr))
837 return (PKT_ALIAS_IGNORED);
839 ud = (struct udphdr *)ip_next(pip);
840 if (dlen < ntohs(ud->uh_ulen))
841 return (PKT_ALIAS_IGNORED);
843 proxy_type = ProxyCheck(la, &proxy_server_address,
844 &proxy_server_port, pip->ip_src, pip->ip_dst,
845 ud->uh_dport, pip->ip_p);
846 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
847 return (PKT_ALIAS_OK);
849 /* If this is a transparent proxy, save original destination,
850 * then alter the destination and adjust checksums */
851 dest_port = ud->uh_dport;
852 dest_address = pip->ip_dst;
854 if (proxy_type != 0) {
857 accumulate = twowords(&pip->ip_dst);
858 accumulate -= twowords(&proxy_server_address);
860 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
862 if (ud->uh_sum != 0) {
863 accumulate = twowords(&pip->ip_dst);
864 accumulate -= twowords(&proxy_server_address);
865 accumulate += ud->uh_dport;
866 accumulate -= proxy_server_port;
867 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
869 pip->ip_dst = proxy_server_address;
870 ud->uh_dport = proxy_server_port;
872 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
873 ud->uh_sport, ud->uh_dport,
874 IPPROTO_UDP, create);
877 struct in_addr alias_address;
878 struct alias_data ad = {
881 .aaddr = &alias_address,
882 .aport = &alias_port,
883 .sport = &ud->uh_sport,
884 .dport = &ud->uh_dport,
888 /* Save original destination address, if this is a proxy packet.
889 * Also modify packet to include destination encoding. This may
890 * change the size of IP header. */
891 if (proxy_type != 0) {
892 SetProxyPort(lnk, dest_port);
893 SetProxyAddress(lnk, dest_address);
894 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
895 ud = (struct udphdr *)ip_next(pip);
898 alias_address = GetAliasAddress(lnk);
899 alias_port = GetAliasPort(lnk);
901 /* Walk out chain. */
902 error = find_handler(OUT, UDP, la, pip, &ad);
904 /* If UDP checksum is not zero, adjust since source port is */
905 /* being aliased and source address is being altered */
906 if (ud->uh_sum != 0) {
909 accumulate = ud->uh_sport;
910 accumulate -= alias_port;
911 accumulate += twowords(&pip->ip_src);
912 accumulate -= twowords(&alias_address);
913 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
915 /* Put alias port in UDP header */
916 ud->uh_sport = alias_port;
918 /* Change source address */
919 DifferentialChecksum(&pip->ip_sum,
920 &alias_address, &pip->ip_src, 2);
921 pip->ip_src = alias_address;
923 return (PKT_ALIAS_OK);
925 return (PKT_ALIAS_IGNORED);
929 TcpAliasIn(struct libalias *la, struct ip *pip)
932 struct alias_link *lnk;
935 LIBALIAS_LOCK_ASSERT(la);
937 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
938 if (dlen < sizeof(struct tcphdr))
939 return (PKT_ALIAS_IGNORED);
940 tc = (struct tcphdr *)ip_next(pip);
942 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
943 tc->th_sport, tc->th_dport,
945 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
947 struct in_addr alias_address;
948 struct in_addr original_address;
949 struct in_addr proxy_address;
952 int accumulate, error;
955 * The init of MANY vars is a bit below, but aliashandlepptpin
956 * seems to need the destination port that came within the
957 * packet and not the original one looks below [*].
960 struct alias_data ad = {
965 .sport = &tc->th_sport,
966 .dport = &tc->th_dport,
970 /* Walk out chain. */
971 error = find_handler(IN, TCP, la, pip, &ad);
973 alias_address = GetAliasAddress(lnk);
974 original_address = GetOriginalAddress(lnk);
975 proxy_address = GetProxyAddress(lnk);
976 alias_port = tc->th_dport;
977 tc->th_dport = GetOriginalPort(lnk);
978 proxy_port = GetProxyPort(lnk);
981 * Look above, if anyone is going to add find_handler AFTER
982 * this aliashandlepptpin/point, please redo alias_data too.
983 * Uncommenting the piece here below should be enough.
986 struct alias_data ad = {
988 .oaddr = &original_address,
989 .aaddr = &alias_address,
990 .aport = &alias_port,
991 .sport = &ud->uh_sport,
992 .dport = &ud->uh_dport,
996 /* Walk out chain. */
997 error = find_handler(la, pip, &ad);
999 printf("Protocol handler not found\n");
1002 /* Adjust TCP checksum since destination port is being unaliased */
1003 /* and destination port is being altered. */
1004 accumulate = alias_port;
1005 accumulate -= tc->th_dport;
1006 accumulate += twowords(&alias_address);
1007 accumulate -= twowords(&original_address);
1009 /* If this is a proxy, then modify the TCP source port and
1010 checksum accumulation */
1011 if (proxy_port != 0) {
1012 accumulate += tc->th_sport;
1013 tc->th_sport = proxy_port;
1014 accumulate -= tc->th_sport;
1015 accumulate += twowords(&pip->ip_src);
1016 accumulate -= twowords(&proxy_address);
1018 /* See if ACK number needs to be modified */
1019 if (GetAckModified(lnk) == 1) {
1022 tc = (struct tcphdr *)ip_next(pip);
1023 delta = GetDeltaAckIn(tc->th_ack, lnk);
1025 accumulate += twowords(&tc->th_ack);
1026 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
1027 accumulate -= twowords(&tc->th_ack);
1030 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1032 /* Restore original IP address */
1033 accumulate = twowords(&pip->ip_dst);
1034 pip->ip_dst = original_address;
1035 accumulate -= twowords(&pip->ip_dst);
1037 /* If this is a transparent proxy packet, then modify the source
1039 if (proxy_address.s_addr != 0) {
1040 accumulate += twowords(&pip->ip_src);
1041 pip->ip_src = proxy_address;
1042 accumulate -= twowords(&pip->ip_src);
1044 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1046 /* Monitor TCP connection state */
1047 tc = (struct tcphdr *)ip_next(pip);
1048 TcpMonitorIn(tc->th_flags, lnk);
1050 return (PKT_ALIAS_OK);
1052 return (PKT_ALIAS_IGNORED);
1056 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
1058 int dlen, proxy_type, error;
1060 u_short proxy_server_port;
1061 struct in_addr dest_address;
1062 struct in_addr proxy_server_address;
1064 struct alias_link *lnk;
1066 LIBALIAS_LOCK_ASSERT(la);
1068 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
1069 if (dlen < sizeof(struct tcphdr))
1070 return (PKT_ALIAS_IGNORED);
1071 tc = (struct tcphdr *)ip_next(pip);
1074 proxy_type = ProxyCheck(la, &proxy_server_address,
1075 &proxy_server_port, pip->ip_src, pip->ip_dst,
1076 tc->th_dport, pip->ip_p);
1080 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1081 return (PKT_ALIAS_OK);
1083 /* If this is a transparent proxy, save original destination,
1084 then alter the destination and adjust checksums */
1085 dest_port = tc->th_dport;
1086 dest_address = pip->ip_dst;
1087 if (proxy_type != 0) {
1090 accumulate = tc->th_dport;
1091 tc->th_dport = proxy_server_port;
1092 accumulate -= tc->th_dport;
1093 accumulate += twowords(&pip->ip_dst);
1094 accumulate -= twowords(&proxy_server_address);
1095 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1097 accumulate = twowords(&pip->ip_dst);
1098 pip->ip_dst = proxy_server_address;
1099 accumulate -= twowords(&pip->ip_dst);
1100 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1102 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
1103 tc->th_sport, tc->th_dport,
1104 IPPROTO_TCP, create);
1106 return (PKT_ALIAS_IGNORED);
1109 struct in_addr alias_address;
1111 struct alias_data ad = {
1114 .aaddr = &alias_address,
1115 .aport = &alias_port,
1116 .sport = &tc->th_sport,
1117 .dport = &tc->th_dport,
1118 .maxpktsize = maxpacketsize
1121 /* Save original destination address, if this is a proxy packet.
1122 Also modify packet to include destination encoding. This may
1123 change the size of IP header. */
1124 if (proxy_type != 0) {
1125 SetProxyPort(lnk, dest_port);
1126 SetProxyAddress(lnk, dest_address);
1127 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
1128 tc = (struct tcphdr *)ip_next(pip);
1130 /* Get alias address and port */
1131 alias_port = GetAliasPort(lnk);
1132 alias_address = GetAliasAddress(lnk);
1134 /* Monitor TCP connection state */
1135 tc = (struct tcphdr *)ip_next(pip);
1136 TcpMonitorOut(tc->th_flags, lnk);
1138 /* Walk out chain. */
1139 error = find_handler(OUT, TCP, la, pip, &ad);
1141 /* Adjust TCP checksum since source port is being aliased */
1142 /* and source address is being altered */
1143 accumulate = tc->th_sport;
1144 tc->th_sport = alias_port;
1145 accumulate -= tc->th_sport;
1146 accumulate += twowords(&pip->ip_src);
1147 accumulate -= twowords(&alias_address);
1149 /* Modify sequence number if necessary */
1150 if (GetAckModified(lnk) == 1) {
1153 tc = (struct tcphdr *)ip_next(pip);
1154 delta = GetDeltaSeqOut(tc->th_seq, lnk);
1156 accumulate += twowords(&tc->th_seq);
1157 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1158 accumulate -= twowords(&tc->th_seq);
1161 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1163 /* Change source address */
1164 accumulate = twowords(&pip->ip_src);
1165 pip->ip_src = alias_address;
1166 accumulate -= twowords(&pip->ip_src);
1167 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1169 return (PKT_ALIAS_OK);
1171 return (PKT_ALIAS_IGNORED);
1174 /* Fragment Handling
1179 The packet aliasing module has a limited ability for handling IP
1180 fragments. If the ICMP, TCP or UDP header is in the first fragment
1181 received, then the ID number of the IP packet is saved, and other
1182 fragments are identified according to their ID number and IP address
1183 they were sent from. Pointers to unresolved fragments can also be
1184 saved and recalled when a header fragment is seen.
1187 /* Local prototypes */
1188 static int FragmentIn(struct libalias *la, struct in_addr ip_src,
1189 struct in_addr *ip_dst, u_short ip_id, u_short *ip_sum);
1190 static int FragmentOut(struct libalias *, struct in_addr *ip_src,
1194 FragmentIn(struct libalias *la, struct in_addr ip_src, struct in_addr *ip_dst,
1195 u_short ip_id, u_short *ip_sum)
1197 struct alias_link *lnk;
1199 LIBALIAS_LOCK_ASSERT(la);
1200 lnk = FindFragmentIn2(la, ip_src, *ip_dst, ip_id);
1202 struct in_addr original_address;
1204 GetFragmentAddr(lnk, &original_address);
1205 DifferentialChecksum(ip_sum,
1206 &original_address, ip_dst, 2);
1207 *ip_dst = original_address;
1209 return (PKT_ALIAS_OK);
1211 return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1215 FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum)
1217 struct in_addr alias_address;
1219 LIBALIAS_LOCK_ASSERT(la);
1220 alias_address = FindAliasAddress(la, *ip_src);
1221 DifferentialChecksum(ip_sum,
1222 &alias_address, ip_src, 2);
1223 *ip_src = alias_address;
1225 return (PKT_ALIAS_OK);
1228 /* Outside World Access
1230 PacketAliasSaveFragment()
1231 PacketAliasGetFragment()
1232 PacketAliasFragmentIn()
1237 (prototypes in alias.h)
1241 LibAliasSaveFragment(struct libalias *la, char *ptr)
1244 struct alias_link *lnk;
1248 pip = (struct ip *)ptr;
1249 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1250 iresult = PKT_ALIAS_ERROR;
1252 SetFragmentPtr(lnk, ptr);
1253 iresult = PKT_ALIAS_OK;
1255 LIBALIAS_UNLOCK(la);
1260 LibAliasGetFragment(struct libalias *la, char *ptr)
1262 struct alias_link *lnk;
1267 pip = (struct ip *)ptr;
1268 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1270 GetFragmentPtr(lnk, &fptr);
1271 SetFragmentPtr(lnk, NULL);
1272 SetExpire(lnk, 0); /* Deletes link */
1276 LIBALIAS_UNLOCK(la);
1281 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
1284 char *ptr_fragment /* Points to fragment which must be
1293 pip = (struct ip *)ptr;
1294 fpip = (struct ip *)ptr_fragment;
1296 DifferentialChecksum(&fpip->ip_sum,
1297 &pip->ip_dst, &fpip->ip_dst, 2);
1298 fpip->ip_dst = pip->ip_dst;
1299 LIBALIAS_UNLOCK(la);
1302 /* Local prototypes */
1304 LibAliasOutLocked(struct libalias *la, char *ptr,
1305 int maxpacketsize, int create);
1307 LibAliasInLocked(struct libalias *la, char *ptr,
1311 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1316 res = LibAliasInLocked(la, ptr, maxpacketsize);
1317 LIBALIAS_UNLOCK(la);
1322 LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize)
1324 struct in_addr alias_addr;
1328 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1329 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1330 iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1331 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1335 ClearCheckNewLink(la);
1336 pip = (struct ip *)ptr;
1337 alias_addr = pip->ip_dst;
1339 /* Defense against mangled packets */
1340 if (ntohs(pip->ip_len) > maxpacketsize
1341 || (pip->ip_hl << 2) > maxpacketsize) {
1342 iresult = PKT_ALIAS_IGNORED;
1346 iresult = PKT_ALIAS_IGNORED;
1347 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1348 switch (pip->ip_p) {
1350 iresult = IcmpAliasIn(la, pip);
1353 iresult = UdpAliasIn(la, pip);
1356 iresult = TcpAliasIn(la, pip);
1360 iresult = SctpAlias(la, pip, SN_TO_LOCAL);
1365 struct alias_data ad = {
1375 /* Walk out chain. */
1376 error = find_handler(IN, IP, la, pip, &ad);
1378 iresult = PKT_ALIAS_OK;
1380 iresult = ProtoAliasIn(la, pip->ip_src,
1381 &pip->ip_dst, pip->ip_p, &pip->ip_sum);
1385 iresult = ProtoAliasIn(la, pip->ip_src, &pip->ip_dst,
1386 pip->ip_p, &pip->ip_sum);
1390 if (ntohs(pip->ip_off) & IP_MF) {
1391 struct alias_link *lnk;
1393 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1395 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1396 SetFragmentAddr(lnk, pip->ip_dst);
1398 iresult = PKT_ALIAS_ERROR;
1402 iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id,
1410 /* Unregistered address ranges */
1412 /* 10.0.0.0 -> 10.255.255.255 */
1413 #define UNREG_ADDR_A_LOWER 0x0a000000
1414 #define UNREG_ADDR_A_UPPER 0x0affffff
1416 /* 172.16.0.0 -> 172.31.255.255 */
1417 #define UNREG_ADDR_B_LOWER 0xac100000
1418 #define UNREG_ADDR_B_UPPER 0xac1fffff
1420 /* 192.168.0.0 -> 192.168.255.255 */
1421 #define UNREG_ADDR_C_LOWER 0xc0a80000
1422 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1424 /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */
1425 #define UNREG_ADDR_CGN_LOWER 0x64400000
1426 #define UNREG_ADDR_CGN_UPPER 0x647fffff
1429 LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize)
1434 res = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1435 LIBALIAS_UNLOCK(la);
1440 LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create)
1445 res = LibAliasOutLocked(la, ptr, maxpacketsize, create);
1446 LIBALIAS_UNLOCK(la);
1451 LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */
1452 int maxpacketsize, /* How much the packet data may grow (FTP
1453 * and IRC inline changes) */
1454 int create /* Create new entries ? */
1458 struct in_addr addr_save;
1461 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1462 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1463 iresult = LibAliasInLocked(la, ptr, maxpacketsize);
1464 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1468 ClearCheckNewLink(la);
1469 pip = (struct ip *)ptr;
1471 /* Defense against mangled packets */
1472 if (ntohs(pip->ip_len) > maxpacketsize
1473 || (pip->ip_hl << 2) > maxpacketsize) {
1474 iresult = PKT_ALIAS_IGNORED;
1478 addr_save = GetDefaultAliasAddress(la);
1479 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY ||
1480 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) {
1485 addr = ntohl(pip->ip_src.s_addr);
1486 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1488 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1490 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1492 else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER &&
1493 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN)
1497 SetDefaultAliasAddress(la, pip->ip_src);
1499 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1500 SetDefaultAliasAddress(la, pip->ip_src);
1502 iresult = PKT_ALIAS_IGNORED;
1503 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1504 switch (pip->ip_p) {
1506 iresult = IcmpAliasOut(la, pip, create);
1509 iresult = UdpAliasOut(la, pip, maxpacketsize, create);
1512 iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1516 iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
1521 struct alias_data ad = {
1530 /* Walk out chain. */
1531 error = find_handler(OUT, IP, la, pip, &ad);
1533 iresult = PKT_ALIAS_OK;
1535 iresult = ProtoAliasOut(la, &pip->ip_src,
1536 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1540 iresult = ProtoAliasOut(la, &pip->ip_src,
1541 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1545 iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum);
1548 SetDefaultAliasAddress(la, addr_save);
1554 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1555 int maxpacketsize /* for error checking */
1562 struct alias_link *lnk;
1563 int iresult = PKT_ALIAS_IGNORED;
1566 pip = (struct ip *)ptr;
1568 /* Defense against mangled packets */
1569 if (ntohs(pip->ip_len) > maxpacketsize
1570 || (pip->ip_hl << 2) > maxpacketsize)
1573 ud = (struct udphdr *)ip_next(pip);
1574 tc = (struct tcphdr *)ip_next(pip);
1575 ic = (struct icmp *)ip_next(pip);
1578 if (pip->ip_p == IPPROTO_UDP)
1579 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1580 ud->uh_dport, ud->uh_sport,
1582 else if (pip->ip_p == IPPROTO_TCP)
1583 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1584 tc->th_dport, tc->th_sport,
1586 else if (pip->ip_p == IPPROTO_ICMP)
1587 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1591 /* Change it from an aliased packet to an unaliased packet */
1593 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1595 struct in_addr original_address;
1596 u_short original_port;
1598 original_address = GetOriginalAddress(lnk);
1599 original_port = GetOriginalPort(lnk);
1601 /* Adjust TCP/UDP checksum */
1602 accumulate = twowords(&pip->ip_src);
1603 accumulate -= twowords(&original_address);
1605 if (pip->ip_p == IPPROTO_UDP) {
1606 accumulate += ud->uh_sport;
1607 accumulate -= original_port;
1608 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1610 accumulate += tc->th_sport;
1611 accumulate -= original_port;
1612 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1615 /* Adjust IP checksum */
1616 DifferentialChecksum(&pip->ip_sum,
1617 &original_address, &pip->ip_src, 2);
1619 /* Un-alias source address and port number */
1620 pip->ip_src = original_address;
1621 if (pip->ip_p == IPPROTO_UDP)
1622 ud->uh_sport = original_port;
1624 tc->th_sport = original_port;
1626 iresult = PKT_ALIAS_OK;
1628 } else if (pip->ip_p == IPPROTO_ICMP) {
1630 struct in_addr original_address;
1631 u_short original_id;
1633 original_address = GetOriginalAddress(lnk);
1634 original_id = GetOriginalPort(lnk);
1636 /* Adjust ICMP checksum */
1637 accumulate = twowords(&pip->ip_src);
1638 accumulate -= twowords(&original_address);
1639 accumulate += ic->icmp_id;
1640 accumulate -= original_id;
1641 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1643 /* Adjust IP checksum */
1644 DifferentialChecksum(&pip->ip_sum,
1645 &original_address, &pip->ip_src, 2);
1647 /* Un-alias source address and port number */
1648 pip->ip_src = original_address;
1649 ic->icmp_id = original_id;
1651 iresult = PKT_ALIAS_OK;
1655 LIBALIAS_UNLOCK(la);
1663 LibAliasRefreshModules(void)
1665 char buf[256], conf[] = "/etc/libalias.conf";
1669 fd = fopen(conf, "r");
1671 err(1, "fopen(%s)", conf);
1673 LibAliasUnLoadAllModule();
1676 fgets(buf, 256, fd);
1681 for (i = 0; i < len; i++)
1682 if (!isspace(buf[i]))
1686 buf[len - 1] = '\0';
1687 LibAliasLoadModule(buf);
1695 LibAliasLoadModule(char *path)
1699 struct proto_handler *m;
1703 handle = dlopen (path, RTLD_LAZY);
1705 fprintf(stderr, "%s\n", dlerror());
1709 p = dlsym(handle, "alias_mod");
1710 if ((error = dlerror()) != NULL) {
1711 fprintf(stderr, "%s\n", dlerror());
1715 t = malloc(sizeof(struct dll));
1718 strncpy(t->name, p->name, DLL_LEN);
1720 if (attach_dll(t) == EEXIST) {
1722 fprintf(stderr, "dll conflict\n");
1726 m = dlsym(t->handle, "handlers");
1727 if ((error = dlerror()) != NULL) {
1728 fprintf(stderr, "%s\n", error);
1732 LibAliasAttachHandlers(m);
1737 LibAliasUnLoadAllModule(void)
1740 struct proto_handler *p;
1742 /* Unload all modules then reload everything. */
1743 while ((p = first_handler()) != NULL) {
1744 LibAliasDetachHandlers(p);
1746 while ((t = walk_dll_chain()) != NULL) {
1757 * m_megapullup() - this function is a big hack.
1758 * Thankfully, it's only used in ng_nat and ipfw+nat.
1760 * It allocates an mbuf with cluster and copies the specified part of the chain
1761 * into cluster, so that it is all contiguous and can be accessed via a plain
1762 * (char *) pointer. This is required, because libalias doesn't know how to
1763 * handle mbuf chains.
1765 * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1766 * the input packet, on failure NULL. The input packet is always consumed.
1769 m_megapullup(struct mbuf *m, int len)
1773 if (len > m->m_pkthdr.len)
1776 if (m->m_next == NULL && M_WRITABLE(m))
1779 if (len <= MJUMPAGESIZE)
1780 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
1781 else if (len <= MJUM9BYTES)
1782 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1783 else if (len <= MJUM16BYTES)
1784 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
1790 m_move_pkthdr(mcl, m);
1791 m_copydata(m, 0, len, mtod(mcl, caddr_t));
1792 mcl->m_len = mcl->m_pkthdr.len = len;