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 *);
194 TcpMonitorIn(u_char th_flags, struct alias_link *lnk)
197 switch (GetStateIn(lnk)) {
198 case ALIAS_TCP_STATE_NOT_CONNECTED:
199 if (th_flags & TH_RST)
200 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
201 else if (th_flags & TH_SYN)
202 SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED);
204 case ALIAS_TCP_STATE_CONNECTED:
205 if (th_flags & (TH_FIN | TH_RST))
206 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
212 TcpMonitorOut(u_char th_flags, struct alias_link *lnk)
215 switch (GetStateOut(lnk)) {
216 case ALIAS_TCP_STATE_NOT_CONNECTED:
217 if (th_flags & TH_RST)
218 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
219 else if (th_flags & TH_SYN)
220 SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED);
222 case ALIAS_TCP_STATE_CONNECTED:
223 if (th_flags & (TH_FIN | TH_RST))
224 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
233 /* Protocol Specific Packet Aliasing Routines
235 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
236 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
237 ProtoAliasIn(), ProtoAliasOut()
238 UdpAliasIn(), UdpAliasOut()
239 TcpAliasIn(), TcpAliasOut()
241 These routines handle protocol specific details of packet aliasing.
242 One may observe a certain amount of repetitive arithmetic in these
243 functions, the purpose of which is to compute a revised checksum
244 without actually summing over the entire data packet, which could be
245 unnecessarily time consuming.
247 The purpose of the packet aliasing routines is to replace the source
248 address of the outgoing packet and then correctly put it back for
249 any incoming packets. For TCP and UDP, ports are also re-mapped.
251 For ICMP echo/timestamp requests and replies, the following scheme
252 is used: the ID number is replaced by an alias for the outgoing
255 ICMP error messages are handled by looking at the IP fragment
256 in the data section of the message.
258 For TCP and UDP protocols, a port number is chosen for an outgoing
259 packet, and then incoming packets are identified by IP address and
260 port numbers. For TCP packets, there is additional logic in the event
261 that sequence and ACK numbers have been altered (as in the case for
262 FTP data port commands).
264 The port numbers used by the packet aliasing module are not true
265 ports in the Unix sense. No sockets are actually bound to ports.
266 They are more correctly thought of as placeholders.
268 All packets go through the aliasing mechanism, whether they come from
269 the gateway machine or other machines on a local area network.
273 /* Local prototypes */
274 static int IcmpAliasIn1(struct libalias *, struct ip *);
275 static int IcmpAliasIn2(struct libalias *, struct ip *);
276 static int IcmpAliasIn(struct libalias *, struct ip *);
278 static int IcmpAliasOut1(struct libalias *, struct ip *, int create);
279 static int IcmpAliasOut2(struct libalias *, struct ip *);
280 static int IcmpAliasOut(struct libalias *, struct ip *, int create);
282 static int ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
283 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum);
284 static int ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
285 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum,
288 static int UdpAliasIn(struct libalias *, struct ip *);
289 static int UdpAliasOut(struct libalias *, struct ip *, int, int create);
291 static int TcpAliasIn(struct libalias *, struct ip *);
292 static int TcpAliasOut(struct libalias *, struct ip *, int, int create);
296 IcmpAliasIn1(struct libalias *la, struct ip *pip)
299 LIBALIAS_LOCK_ASSERT(la);
301 De-alias incoming echo and timestamp replies.
302 Alias incoming echo and timestamp requests.
304 struct alias_link *lnk;
307 ic = (struct icmp *)ip_next(pip);
309 /* Get source address from ICMP data field and restore original data */
310 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
315 original_id = GetOriginalPort(lnk);
317 /* Adjust ICMP checksum */
318 accumulate = ic->icmp_id;
319 accumulate -= original_id;
320 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
322 /* Put original sequence number back in */
323 ic->icmp_id = original_id;
325 /* Put original address back into IP header */
327 struct in_addr original_address;
329 original_address = GetOriginalAddress(lnk);
330 DifferentialChecksum(&pip->ip_sum,
331 &original_address, &pip->ip_dst, 2);
332 pip->ip_dst = original_address;
335 return (PKT_ALIAS_OK);
337 return (PKT_ALIAS_IGNORED);
341 IcmpAliasIn2(struct libalias *la, struct ip *pip)
344 LIBALIAS_LOCK_ASSERT(la);
346 Alias incoming ICMP error messages containing
347 IP header and first 64 bits of datagram.
350 struct icmp *ic, *ic2;
353 struct alias_link *lnk;
355 ic = (struct icmp *)ip_next(pip);
358 ud = (struct udphdr *)ip_next(ip);
359 tc = (struct tcphdr *)ip_next(ip);
360 ic2 = (struct icmp *)ip_next(ip);
362 if (ip->ip_p == IPPROTO_UDP)
363 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
364 ud->uh_dport, ud->uh_sport,
366 else if (ip->ip_p == IPPROTO_TCP)
367 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
368 tc->th_dport, tc->th_sport,
370 else if (ip->ip_p == IPPROTO_ICMP) {
371 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
372 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
379 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
380 int accumulate, accumulate2;
381 struct in_addr original_address;
382 u_short original_port;
384 original_address = GetOriginalAddress(lnk);
385 original_port = GetOriginalPort(lnk);
387 /* Adjust ICMP checksum */
388 accumulate = twowords(&ip->ip_src);
389 accumulate -= twowords(&original_address);
390 accumulate += ud->uh_sport;
391 accumulate -= original_port;
392 accumulate2 = accumulate;
393 accumulate2 += ip->ip_sum;
394 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
395 accumulate2 -= ip->ip_sum;
396 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
398 /* Un-alias address in IP header */
399 DifferentialChecksum(&pip->ip_sum,
400 &original_address, &pip->ip_dst, 2);
401 pip->ip_dst = original_address;
403 /* Un-alias address and port number of original IP packet
404 fragment contained in ICMP data section */
405 ip->ip_src = original_address;
406 ud->uh_sport = original_port;
407 } else if (ip->ip_p == IPPROTO_ICMP) {
408 int accumulate, accumulate2;
409 struct in_addr original_address;
412 original_address = GetOriginalAddress(lnk);
413 original_id = GetOriginalPort(lnk);
415 /* Adjust ICMP checksum */
416 accumulate = twowords(&ip->ip_src);
417 accumulate -= twowords(&original_address);
418 accumulate += ic2->icmp_id;
419 accumulate -= original_id;
420 accumulate2 = accumulate;
421 accumulate2 += ip->ip_sum;
422 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
423 accumulate2 -= ip->ip_sum;
424 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
426 /* Un-alias address in IP header */
427 DifferentialChecksum(&pip->ip_sum,
428 &original_address, &pip->ip_dst, 2);
429 pip->ip_dst = original_address;
431 /* Un-alias address of original IP packet and sequence number of
432 embedded ICMP datagram */
433 ip->ip_src = original_address;
434 ic2->icmp_id = original_id;
436 return (PKT_ALIAS_OK);
438 return (PKT_ALIAS_IGNORED);
443 IcmpAliasIn(struct libalias *la, struct ip *pip)
448 LIBALIAS_LOCK_ASSERT(la);
450 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
451 if (dlen < ICMP_MINLEN)
452 return (PKT_ALIAS_IGNORED);
454 /* Return if proxy-only mode is enabled */
455 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
456 return (PKT_ALIAS_OK);
458 ic = (struct icmp *)ip_next(pip);
460 iresult = PKT_ALIAS_IGNORED;
461 switch (ic->icmp_type) {
463 case ICMP_TSTAMPREPLY:
464 if (ic->icmp_code == 0) {
465 iresult = IcmpAliasIn1(la, pip);
469 case ICMP_SOURCEQUENCH:
472 if (dlen < ICMP_ADVLENMIN ||
473 dlen < ICMP_ADVLEN(ic))
474 return (PKT_ALIAS_IGNORED);
475 iresult = IcmpAliasIn2(la, pip);
479 iresult = IcmpAliasIn1(la, pip);
487 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
490 Alias outgoing echo and timestamp requests.
491 De-alias outgoing echo and timestamp replies.
493 struct alias_link *lnk;
496 LIBALIAS_LOCK_ASSERT(la);
497 ic = (struct icmp *)ip_next(pip);
499 /* Save overwritten data for when echo packet returns */
500 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create);
505 alias_id = GetAliasPort(lnk);
507 /* Since data field is being modified, adjust ICMP checksum */
508 accumulate = ic->icmp_id;
509 accumulate -= alias_id;
510 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
512 /* Alias sequence number */
513 ic->icmp_id = alias_id;
515 /* Change source address */
517 struct in_addr alias_address;
519 alias_address = GetAliasAddress(lnk);
520 DifferentialChecksum(&pip->ip_sum,
521 &alias_address, &pip->ip_src, 2);
522 pip->ip_src = alias_address;
525 return (PKT_ALIAS_OK);
527 return (PKT_ALIAS_IGNORED);
532 IcmpAliasOut2(struct libalias *la, struct ip *pip)
535 Alias outgoing ICMP error messages containing
536 IP header and first 64 bits of datagram.
539 struct icmp *ic, *ic2;
542 struct alias_link *lnk;
544 LIBALIAS_LOCK_ASSERT(la);
545 ic = (struct icmp *)ip_next(pip);
548 ud = (struct udphdr *)ip_next(ip);
549 tc = (struct tcphdr *)ip_next(ip);
550 ic2 = (struct icmp *)ip_next(ip);
552 if (ip->ip_p == IPPROTO_UDP)
553 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
554 ud->uh_dport, ud->uh_sport,
556 else if (ip->ip_p == IPPROTO_TCP)
557 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
558 tc->th_dport, tc->th_sport,
560 else if (ip->ip_p == IPPROTO_ICMP) {
561 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
562 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
569 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
571 struct in_addr alias_address;
574 alias_address = GetAliasAddress(lnk);
575 alias_port = GetAliasPort(lnk);
577 /* Adjust ICMP checksum */
578 accumulate = twowords(&ip->ip_dst);
579 accumulate -= twowords(&alias_address);
580 accumulate += ud->uh_dport;
581 accumulate -= alias_port;
582 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
585 * Alias address in IP header if it comes from the host
586 * the original TCP/UDP packet was destined for.
588 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
589 DifferentialChecksum(&pip->ip_sum,
590 &alias_address, &pip->ip_src, 2);
591 pip->ip_src = alias_address;
593 /* Alias address and port number of original IP packet
594 fragment contained in ICMP data section */
595 ip->ip_dst = alias_address;
596 ud->uh_dport = alias_port;
597 } else if (ip->ip_p == IPPROTO_ICMP) {
599 struct in_addr alias_address;
602 alias_address = GetAliasAddress(lnk);
603 alias_id = GetAliasPort(lnk);
605 /* Adjust ICMP checksum */
606 accumulate = twowords(&ip->ip_dst);
607 accumulate -= twowords(&alias_address);
608 accumulate += ic2->icmp_id;
609 accumulate -= alias_id;
610 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
613 * Alias address in IP header if it comes from the host
614 * the original ICMP message was destined for.
616 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
617 DifferentialChecksum(&pip->ip_sum,
618 &alias_address, &pip->ip_src, 2);
619 pip->ip_src = alias_address;
621 /* Alias address of original IP packet and sequence number of
622 embedded ICMP datagram */
623 ip->ip_dst = alias_address;
624 ic2->icmp_id = alias_id;
626 return (PKT_ALIAS_OK);
628 return (PKT_ALIAS_IGNORED);
633 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
638 LIBALIAS_LOCK_ASSERT(la);
641 /* Return if proxy-only mode is enabled */
642 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
643 return (PKT_ALIAS_OK);
645 ic = (struct icmp *)ip_next(pip);
647 iresult = PKT_ALIAS_IGNORED;
648 switch (ic->icmp_type) {
651 if (ic->icmp_code == 0) {
652 iresult = IcmpAliasOut1(la, pip, create);
656 case ICMP_SOURCEQUENCH:
659 iresult = IcmpAliasOut2(la, pip);
662 case ICMP_TSTAMPREPLY:
663 iresult = IcmpAliasOut1(la, pip, create);
669 ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
670 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum)
673 Handle incoming IP packets. The
674 only thing which is done in this case is to alias
675 the dest IP address of the packet to our inside
678 struct alias_link *lnk;
680 LIBALIAS_LOCK_ASSERT(la);
681 /* Return if proxy-only mode is enabled */
682 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
683 return (PKT_ALIAS_OK);
685 lnk = FindProtoIn(la, ip_src, *ip_dst, ip_p);
687 struct in_addr original_address;
689 original_address = GetOriginalAddress(lnk);
691 /* Restore original IP address */
692 DifferentialChecksum(ip_sum,
693 &original_address, ip_dst, 2);
694 *ip_dst = original_address;
696 return (PKT_ALIAS_OK);
698 return (PKT_ALIAS_IGNORED);
702 ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
703 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
706 Handle outgoing IP packets. The
707 only thing which is done in this case is to alias
708 the source IP address of the packet.
710 struct alias_link *lnk;
712 LIBALIAS_LOCK_ASSERT(la);
714 /* Return if proxy-only mode is enabled */
715 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
716 return (PKT_ALIAS_OK);
719 return (PKT_ALIAS_IGNORED);
721 lnk = FindProtoOut(la, *ip_src, ip_dst, ip_p);
723 struct in_addr alias_address;
725 alias_address = GetAliasAddress(lnk);
727 /* Change source address */
728 DifferentialChecksum(ip_sum,
729 &alias_address, ip_src, 2);
730 *ip_src = alias_address;
732 return (PKT_ALIAS_OK);
734 return (PKT_ALIAS_IGNORED);
739 UdpAliasIn(struct libalias *la, struct ip *pip)
742 struct alias_link *lnk;
745 LIBALIAS_LOCK_ASSERT(la);
747 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
748 if (dlen < sizeof(struct udphdr))
749 return (PKT_ALIAS_IGNORED);
751 ud = (struct udphdr *)ip_next(pip);
752 if (dlen < ntohs(ud->uh_ulen))
753 return (PKT_ALIAS_IGNORED);
755 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
756 ud->uh_sport, ud->uh_dport,
757 IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
759 struct in_addr alias_address;
760 struct in_addr original_address;
761 struct in_addr proxy_address;
766 struct alias_data ad = {
768 .oaddr = &original_address,
769 .aaddr = &alias_address,
770 .aport = &alias_port,
771 .sport = &ud->uh_sport,
772 .dport = &ud->uh_dport,
776 alias_address = GetAliasAddress(lnk);
777 original_address = GetOriginalAddress(lnk);
778 proxy_address = GetProxyAddress(lnk);
779 alias_port = ud->uh_dport;
780 ud->uh_dport = GetOriginalPort(lnk);
781 proxy_port = GetProxyPort(lnk);
783 /* Walk out chain. */
784 error = find_handler(IN, UDP, la, pip, &ad);
785 /* If we cannot figure out the packet, ignore it. */
787 return (PKT_ALIAS_IGNORED);
789 /* If UDP checksum is not zero, then adjust since destination port */
790 /* is being unaliased and destination address is being altered. */
791 if (ud->uh_sum != 0) {
792 accumulate = alias_port;
793 accumulate -= ud->uh_dport;
794 accumulate += twowords(&alias_address);
795 accumulate -= twowords(&original_address);
797 /* If this is a proxy packet, modify checksum because of source change.*/
798 if (proxy_port != 0) {
799 accumulate += ud->uh_sport;
800 accumulate -= proxy_port;
803 if (proxy_address.s_addr != 0) {
804 accumulate += twowords(&pip->ip_src);
805 accumulate -= twowords(&proxy_address);
808 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
810 /* XXX: Could the two if's below be concatenated to one ? */
811 /* Restore source port and/or address in case of proxying*/
814 ud->uh_sport = proxy_port;
816 if (proxy_address.s_addr != 0) {
817 DifferentialChecksum(&pip->ip_sum,
818 &proxy_address, &pip->ip_src, 2);
819 pip->ip_src = proxy_address;
822 /* Restore original IP address */
823 DifferentialChecksum(&pip->ip_sum,
824 &original_address, &pip->ip_dst, 2);
825 pip->ip_dst = original_address;
827 return (PKT_ALIAS_OK);
829 return (PKT_ALIAS_IGNORED);
833 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
836 struct alias_link *lnk;
837 struct in_addr dest_address;
838 struct in_addr proxy_server_address;
840 u_short proxy_server_port;
844 LIBALIAS_LOCK_ASSERT(la);
846 /* Return if proxy-only mode is enabled and not proxyrule found.*/
847 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
848 if (dlen < sizeof(struct udphdr))
849 return (PKT_ALIAS_IGNORED);
851 ud = (struct udphdr *)ip_next(pip);
852 if (dlen < ntohs(ud->uh_ulen))
853 return (PKT_ALIAS_IGNORED);
855 proxy_type = ProxyCheck(la, &proxy_server_address,
856 &proxy_server_port, pip->ip_src, pip->ip_dst,
857 ud->uh_dport, pip->ip_p);
858 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
859 return (PKT_ALIAS_OK);
861 /* If this is a transparent proxy, save original destination,
862 * then alter the destination and adjust checksums */
863 dest_port = ud->uh_dport;
864 dest_address = pip->ip_dst;
866 if (proxy_type != 0) {
869 accumulate = twowords(&pip->ip_dst);
870 accumulate -= twowords(&proxy_server_address);
872 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
874 if (ud->uh_sum != 0) {
875 accumulate = twowords(&pip->ip_dst);
876 accumulate -= twowords(&proxy_server_address);
877 accumulate += ud->uh_dport;
878 accumulate -= proxy_server_port;
879 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
881 pip->ip_dst = proxy_server_address;
882 ud->uh_dport = proxy_server_port;
884 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
885 ud->uh_sport, ud->uh_dport,
886 IPPROTO_UDP, create);
889 struct in_addr alias_address;
890 struct alias_data ad = {
893 .aaddr = &alias_address,
894 .aport = &alias_port,
895 .sport = &ud->uh_sport,
896 .dport = &ud->uh_dport,
900 /* Save original destination address, if this is a proxy packet.
901 * Also modify packet to include destination encoding. This may
902 * change the size of IP header. */
903 if (proxy_type != 0) {
904 SetProxyPort(lnk, dest_port);
905 SetProxyAddress(lnk, dest_address);
906 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
907 ud = (struct udphdr *)ip_next(pip);
910 alias_address = GetAliasAddress(lnk);
911 alias_port = GetAliasPort(lnk);
913 /* Walk out chain. */
914 error = find_handler(OUT, UDP, la, pip, &ad);
916 /* If UDP checksum is not zero, adjust since source port is */
917 /* being aliased and source address is being altered */
918 if (ud->uh_sum != 0) {
921 accumulate = ud->uh_sport;
922 accumulate -= alias_port;
923 accumulate += twowords(&pip->ip_src);
924 accumulate -= twowords(&alias_address);
925 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
927 /* Put alias port in UDP header */
928 ud->uh_sport = alias_port;
930 /* Change source address */
931 DifferentialChecksum(&pip->ip_sum,
932 &alias_address, &pip->ip_src, 2);
933 pip->ip_src = alias_address;
935 return (PKT_ALIAS_OK);
937 return (PKT_ALIAS_IGNORED);
943 TcpAliasIn(struct libalias *la, struct ip *pip)
946 struct alias_link *lnk;
949 LIBALIAS_LOCK_ASSERT(la);
951 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
952 if (dlen < sizeof(struct tcphdr))
953 return (PKT_ALIAS_IGNORED);
954 tc = (struct tcphdr *)ip_next(pip);
956 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
957 tc->th_sport, tc->th_dport,
959 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
961 struct in_addr alias_address;
962 struct in_addr original_address;
963 struct in_addr proxy_address;
966 int accumulate, error;
969 * The init of MANY vars is a bit below, but aliashandlepptpin
970 * seems to need the destination port that came within the
971 * packet and not the original one looks below [*].
974 struct alias_data ad = {
979 .sport = &tc->th_sport,
980 .dport = &tc->th_dport,
984 /* Walk out chain. */
985 error = find_handler(IN, TCP, la, pip, &ad);
987 alias_address = GetAliasAddress(lnk);
988 original_address = GetOriginalAddress(lnk);
989 proxy_address = GetProxyAddress(lnk);
990 alias_port = tc->th_dport;
991 tc->th_dport = GetOriginalPort(lnk);
992 proxy_port = GetProxyPort(lnk);
995 * Look above, if anyone is going to add find_handler AFTER
996 * this aliashandlepptpin/point, please redo alias_data too.
997 * Uncommenting the piece here below should be enough.
1000 struct alias_data ad = {
1002 .oaddr = &original_address,
1003 .aaddr = &alias_address,
1004 .aport = &alias_port,
1005 .sport = &ud->uh_sport,
1006 .dport = &ud->uh_dport,
1010 /* Walk out chain. */
1011 error = find_handler(la, pip, &ad);
1012 if (error == EHDNOF)
1013 printf("Protocol handler not found\n");
1016 /* Adjust TCP checksum since destination port is being unaliased */
1017 /* and destination port is being altered. */
1018 accumulate = alias_port;
1019 accumulate -= tc->th_dport;
1020 accumulate += twowords(&alias_address);
1021 accumulate -= twowords(&original_address);
1023 /* If this is a proxy, then modify the TCP source port and
1024 checksum accumulation */
1025 if (proxy_port != 0) {
1026 accumulate += tc->th_sport;
1027 tc->th_sport = proxy_port;
1028 accumulate -= tc->th_sport;
1029 accumulate += twowords(&pip->ip_src);
1030 accumulate -= twowords(&proxy_address);
1032 /* See if ACK number needs to be modified */
1033 if (GetAckModified(lnk) == 1) {
1036 tc = (struct tcphdr *)ip_next(pip);
1037 delta = GetDeltaAckIn(tc->th_ack, lnk);
1039 accumulate += twowords(&tc->th_ack);
1040 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
1041 accumulate -= twowords(&tc->th_ack);
1044 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1046 /* Restore original IP address */
1047 accumulate = twowords(&pip->ip_dst);
1048 pip->ip_dst = original_address;
1049 accumulate -= twowords(&pip->ip_dst);
1051 /* If this is a transparent proxy packet, then modify the source
1053 if (proxy_address.s_addr != 0) {
1054 accumulate += twowords(&pip->ip_src);
1055 pip->ip_src = proxy_address;
1056 accumulate -= twowords(&pip->ip_src);
1058 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1060 /* Monitor TCP connection state */
1061 tc = (struct tcphdr *)ip_next(pip);
1062 TcpMonitorIn(tc->th_flags, lnk);
1064 return (PKT_ALIAS_OK);
1066 return (PKT_ALIAS_IGNORED);
1070 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
1072 int dlen, proxy_type, error;
1074 u_short proxy_server_port;
1075 struct in_addr dest_address;
1076 struct in_addr proxy_server_address;
1078 struct alias_link *lnk;
1080 LIBALIAS_LOCK_ASSERT(la);
1082 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
1083 if (dlen < sizeof(struct tcphdr))
1084 return (PKT_ALIAS_IGNORED);
1085 tc = (struct tcphdr *)ip_next(pip);
1088 proxy_type = ProxyCheck(la, &proxy_server_address,
1089 &proxy_server_port, pip->ip_src, pip->ip_dst,
1090 tc->th_dport, pip->ip_p);
1094 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1095 return (PKT_ALIAS_OK);
1097 /* If this is a transparent proxy, save original destination,
1098 then alter the destination and adjust checksums */
1099 dest_port = tc->th_dport;
1100 dest_address = pip->ip_dst;
1101 if (proxy_type != 0) {
1104 accumulate = tc->th_dport;
1105 tc->th_dport = proxy_server_port;
1106 accumulate -= tc->th_dport;
1107 accumulate += twowords(&pip->ip_dst);
1108 accumulate -= twowords(&proxy_server_address);
1109 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1111 accumulate = twowords(&pip->ip_dst);
1112 pip->ip_dst = proxy_server_address;
1113 accumulate -= twowords(&pip->ip_dst);
1114 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1116 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
1117 tc->th_sport, tc->th_dport,
1118 IPPROTO_TCP, create);
1120 return (PKT_ALIAS_IGNORED);
1123 struct in_addr alias_address;
1125 struct alias_data ad = {
1128 .aaddr = &alias_address,
1129 .aport = &alias_port,
1130 .sport = &tc->th_sport,
1131 .dport = &tc->th_dport,
1132 .maxpktsize = maxpacketsize
1135 /* Save original destination address, if this is a proxy packet.
1136 Also modify packet to include destination encoding. This may
1137 change the size of IP header. */
1138 if (proxy_type != 0) {
1139 SetProxyPort(lnk, dest_port);
1140 SetProxyAddress(lnk, dest_address);
1141 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
1142 tc = (struct tcphdr *)ip_next(pip);
1144 /* Get alias address and port */
1145 alias_port = GetAliasPort(lnk);
1146 alias_address = GetAliasAddress(lnk);
1148 /* Monitor TCP connection state */
1149 tc = (struct tcphdr *)ip_next(pip);
1150 TcpMonitorOut(tc->th_flags, lnk);
1152 /* Walk out chain. */
1153 error = find_handler(OUT, TCP, la, pip, &ad);
1155 /* Adjust TCP checksum since source port is being aliased */
1156 /* and source address is being altered */
1157 accumulate = tc->th_sport;
1158 tc->th_sport = alias_port;
1159 accumulate -= tc->th_sport;
1160 accumulate += twowords(&pip->ip_src);
1161 accumulate -= twowords(&alias_address);
1163 /* Modify sequence number if necessary */
1164 if (GetAckModified(lnk) == 1) {
1167 tc = (struct tcphdr *)ip_next(pip);
1168 delta = GetDeltaSeqOut(tc->th_seq, lnk);
1170 accumulate += twowords(&tc->th_seq);
1171 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1172 accumulate -= twowords(&tc->th_seq);
1175 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1177 /* Change source address */
1178 accumulate = twowords(&pip->ip_src);
1179 pip->ip_src = alias_address;
1180 accumulate -= twowords(&pip->ip_src);
1181 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1183 return (PKT_ALIAS_OK);
1185 return (PKT_ALIAS_IGNORED);
1191 /* Fragment Handling
1196 The packet aliasing module has a limited ability for handling IP
1197 fragments. If the ICMP, TCP or UDP header is in the first fragment
1198 received, then the ID number of the IP packet is saved, and other
1199 fragments are identified according to their ID number and IP address
1200 they were sent from. Pointers to unresolved fragments can also be
1201 saved and recalled when a header fragment is seen.
1204 /* Local prototypes */
1205 static int FragmentIn(struct libalias *la, struct in_addr ip_src,
1206 struct in_addr *ip_dst, u_short ip_id, u_short *ip_sum);
1207 static int FragmentOut(struct libalias *, struct in_addr *ip_src,
1211 FragmentIn(struct libalias *la, struct in_addr ip_src, struct in_addr *ip_dst,
1212 u_short ip_id, u_short *ip_sum)
1214 struct alias_link *lnk;
1216 LIBALIAS_LOCK_ASSERT(la);
1217 lnk = FindFragmentIn2(la, ip_src, *ip_dst, ip_id);
1219 struct in_addr original_address;
1221 GetFragmentAddr(lnk, &original_address);
1222 DifferentialChecksum(ip_sum,
1223 &original_address, ip_dst, 2);
1224 *ip_dst = original_address;
1226 return (PKT_ALIAS_OK);
1228 return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1232 FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum)
1234 struct in_addr alias_address;
1236 LIBALIAS_LOCK_ASSERT(la);
1237 alias_address = FindAliasAddress(la, *ip_src);
1238 DifferentialChecksum(ip_sum,
1239 &alias_address, ip_src, 2);
1240 *ip_src = alias_address;
1242 return (PKT_ALIAS_OK);
1250 /* Outside World Access
1252 PacketAliasSaveFragment()
1253 PacketAliasGetFragment()
1254 PacketAliasFragmentIn()
1259 (prototypes in alias.h)
1263 LibAliasSaveFragment(struct libalias *la, char *ptr)
1266 struct alias_link *lnk;
1270 pip = (struct ip *)ptr;
1271 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1272 iresult = PKT_ALIAS_ERROR;
1274 SetFragmentPtr(lnk, ptr);
1275 iresult = PKT_ALIAS_OK;
1277 LIBALIAS_UNLOCK(la);
1282 LibAliasGetFragment(struct libalias *la, char *ptr)
1284 struct alias_link *lnk;
1289 pip = (struct ip *)ptr;
1290 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1292 GetFragmentPtr(lnk, &fptr);
1293 SetFragmentPtr(lnk, NULL);
1294 SetExpire(lnk, 0); /* Deletes link */
1298 LIBALIAS_UNLOCK(la);
1303 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
1306 char *ptr_fragment /* Points to fragment which must be
1315 pip = (struct ip *)ptr;
1316 fpip = (struct ip *)ptr_fragment;
1318 DifferentialChecksum(&fpip->ip_sum,
1319 &pip->ip_dst, &fpip->ip_dst, 2);
1320 fpip->ip_dst = pip->ip_dst;
1321 LIBALIAS_UNLOCK(la);
1324 /* Local prototypes */
1326 LibAliasOutLocked(struct libalias *la, char *ptr,
1327 int maxpacketsize, int create);
1329 LibAliasInLocked(struct libalias *la, char *ptr,
1333 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1338 res = LibAliasInLocked(la, ptr, maxpacketsize);
1339 LIBALIAS_UNLOCK(la);
1344 LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize)
1346 struct in_addr alias_addr;
1350 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1351 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1352 iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1353 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1357 ClearCheckNewLink(la);
1358 pip = (struct ip *)ptr;
1359 alias_addr = pip->ip_dst;
1361 /* Defense against mangled packets */
1362 if (ntohs(pip->ip_len) > maxpacketsize
1363 || (pip->ip_hl << 2) > maxpacketsize) {
1364 iresult = PKT_ALIAS_IGNORED;
1368 iresult = PKT_ALIAS_IGNORED;
1369 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1370 switch (pip->ip_p) {
1372 iresult = IcmpAliasIn(la, pip);
1375 iresult = UdpAliasIn(la, pip);
1378 iresult = TcpAliasIn(la, pip);
1382 iresult = SctpAlias(la, pip, SN_TO_LOCAL);
1387 struct alias_data ad = {
1397 /* Walk out chain. */
1398 error = find_handler(IN, IP, la, pip, &ad);
1400 iresult = PKT_ALIAS_OK;
1402 iresult = ProtoAliasIn(la, pip->ip_src,
1403 &pip->ip_dst, pip->ip_p, &pip->ip_sum);
1407 iresult = ProtoAliasIn(la, pip->ip_src, &pip->ip_dst,
1408 pip->ip_p, &pip->ip_sum);
1412 if (ntohs(pip->ip_off) & IP_MF) {
1413 struct alias_link *lnk;
1415 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1417 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1418 SetFragmentAddr(lnk, pip->ip_dst);
1420 iresult = PKT_ALIAS_ERROR;
1424 iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id,
1434 /* Unregistered address ranges */
1436 /* 10.0.0.0 -> 10.255.255.255 */
1437 #define UNREG_ADDR_A_LOWER 0x0a000000
1438 #define UNREG_ADDR_A_UPPER 0x0affffff
1440 /* 172.16.0.0 -> 172.31.255.255 */
1441 #define UNREG_ADDR_B_LOWER 0xac100000
1442 #define UNREG_ADDR_B_UPPER 0xac1fffff
1444 /* 192.168.0.0 -> 192.168.255.255 */
1445 #define UNREG_ADDR_C_LOWER 0xc0a80000
1446 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1448 /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */
1449 #define UNREG_ADDR_CGN_LOWER 0x64400000
1450 #define UNREG_ADDR_CGN_UPPER 0x647fffff
1453 LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize)
1458 res = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1459 LIBALIAS_UNLOCK(la);
1464 LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create)
1469 res = LibAliasOutLocked(la, ptr, maxpacketsize, create);
1470 LIBALIAS_UNLOCK(la);
1475 LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */
1476 int maxpacketsize, /* How much the packet data may grow (FTP
1477 * and IRC inline changes) */
1478 int create /* Create new entries ? */
1482 struct in_addr addr_save;
1485 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1486 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1487 iresult = LibAliasInLocked(la, ptr, maxpacketsize);
1488 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1492 ClearCheckNewLink(la);
1493 pip = (struct ip *)ptr;
1495 /* Defense against mangled packets */
1496 if (ntohs(pip->ip_len) > maxpacketsize
1497 || (pip->ip_hl << 2) > maxpacketsize) {
1498 iresult = PKT_ALIAS_IGNORED;
1502 addr_save = GetDefaultAliasAddress(la);
1503 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY ||
1504 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) {
1509 addr = ntohl(pip->ip_src.s_addr);
1510 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1512 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1514 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1516 else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER &&
1517 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN)
1521 SetDefaultAliasAddress(la, pip->ip_src);
1523 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1524 SetDefaultAliasAddress(la, pip->ip_src);
1526 iresult = PKT_ALIAS_IGNORED;
1527 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1528 switch (pip->ip_p) {
1530 iresult = IcmpAliasOut(la, pip, create);
1533 iresult = UdpAliasOut(la, pip, maxpacketsize, create);
1536 iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1540 iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
1545 struct alias_data ad = {
1554 /* Walk out chain. */
1555 error = find_handler(OUT, IP, la, pip, &ad);
1557 iresult = PKT_ALIAS_OK;
1559 iresult = ProtoAliasOut(la, &pip->ip_src,
1560 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1564 iresult = ProtoAliasOut(la, &pip->ip_src,
1565 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1569 iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum);
1572 SetDefaultAliasAddress(la, addr_save);
1578 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1579 int maxpacketsize /* for error checking */
1586 struct alias_link *lnk;
1587 int iresult = PKT_ALIAS_IGNORED;
1590 pip = (struct ip *)ptr;
1592 /* Defense against mangled packets */
1593 if (ntohs(pip->ip_len) > maxpacketsize
1594 || (pip->ip_hl << 2) > maxpacketsize)
1597 ud = (struct udphdr *)ip_next(pip);
1598 tc = (struct tcphdr *)ip_next(pip);
1599 ic = (struct icmp *)ip_next(pip);
1602 if (pip->ip_p == IPPROTO_UDP)
1603 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1604 ud->uh_dport, ud->uh_sport,
1606 else if (pip->ip_p == IPPROTO_TCP)
1607 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1608 tc->th_dport, tc->th_sport,
1610 else if (pip->ip_p == IPPROTO_ICMP)
1611 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1615 /* Change it from an aliased packet to an unaliased packet */
1617 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1619 struct in_addr original_address;
1620 u_short original_port;
1622 original_address = GetOriginalAddress(lnk);
1623 original_port = GetOriginalPort(lnk);
1625 /* Adjust TCP/UDP checksum */
1626 accumulate = twowords(&pip->ip_src);
1627 accumulate -= twowords(&original_address);
1629 if (pip->ip_p == IPPROTO_UDP) {
1630 accumulate += ud->uh_sport;
1631 accumulate -= original_port;
1632 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1634 accumulate += tc->th_sport;
1635 accumulate -= original_port;
1636 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1639 /* Adjust IP checksum */
1640 DifferentialChecksum(&pip->ip_sum,
1641 &original_address, &pip->ip_src, 2);
1643 /* Un-alias source address and port number */
1644 pip->ip_src = original_address;
1645 if (pip->ip_p == IPPROTO_UDP)
1646 ud->uh_sport = original_port;
1648 tc->th_sport = original_port;
1650 iresult = PKT_ALIAS_OK;
1652 } else if (pip->ip_p == IPPROTO_ICMP) {
1655 struct in_addr original_address;
1656 u_short original_id;
1658 original_address = GetOriginalAddress(lnk);
1659 original_id = GetOriginalPort(lnk);
1661 /* Adjust ICMP checksum */
1662 accumulate = twowords(&pip->ip_src);
1663 accumulate -= twowords(&original_address);
1664 accumulate += ic->icmp_id;
1665 accumulate -= original_id;
1666 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1668 /* Adjust IP checksum */
1669 DifferentialChecksum(&pip->ip_sum,
1670 &original_address, &pip->ip_src, 2);
1672 /* Un-alias source address and port number */
1673 pip->ip_src = original_address;
1674 ic->icmp_id = original_id;
1676 iresult = PKT_ALIAS_OK;
1680 LIBALIAS_UNLOCK(la);
1688 LibAliasRefreshModules(void)
1690 char buf[256], conf[] = "/etc/libalias.conf";
1694 fd = fopen(conf, "r");
1696 err(1, "fopen(%s)", conf);
1698 LibAliasUnLoadAllModule();
1701 fgets(buf, 256, fd);
1706 for (i = 0; i < len; i++)
1707 if (!isspace(buf[i]))
1711 buf[len - 1] = '\0';
1712 LibAliasLoadModule(buf);
1720 LibAliasLoadModule(char *path)
1724 struct proto_handler *m;
1728 handle = dlopen (path, RTLD_LAZY);
1730 fprintf(stderr, "%s\n", dlerror());
1734 p = dlsym(handle, "alias_mod");
1735 if ((error = dlerror()) != NULL) {
1736 fprintf(stderr, "%s\n", dlerror());
1740 t = malloc(sizeof(struct dll));
1743 strncpy(t->name, p->name, DLL_LEN);
1745 if (attach_dll(t) == EEXIST) {
1747 fprintf(stderr, "dll conflict\n");
1751 m = dlsym(t->handle, "handlers");
1752 if ((error = dlerror()) != NULL) {
1753 fprintf(stderr, "%s\n", error);
1757 LibAliasAttachHandlers(m);
1762 LibAliasUnLoadAllModule(void)
1765 struct proto_handler *p;
1767 /* Unload all modules then reload everything. */
1768 while ((p = first_handler()) != NULL) {
1769 LibAliasDetachHandlers(p);
1771 while ((t = walk_dll_chain()) != NULL) {
1782 * m_megapullup() - this function is a big hack.
1783 * Thankfully, it's only used in ng_nat and ipfw+nat.
1785 * It allocates an mbuf with cluster and copies the specified part of the chain
1786 * into cluster, so that it is all contiguous and can be accessed via a plain
1787 * (char *) pointer. This is required, because libalias doesn't know how to
1788 * handle mbuf chains.
1790 * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1791 * the input packet, on failure NULL. The input packet is always consumed.
1794 m_megapullup(struct mbuf *m, int len)
1798 if (len > m->m_pkthdr.len)
1801 if (m->m_next == NULL && M_WRITABLE(m))
1804 if (len <= MJUMPAGESIZE)
1805 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
1806 else if (len <= MJUM9BYTES)
1807 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1808 else if (len <= MJUM16BYTES)
1809 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
1815 m_move_pkthdr(mcl, m);
1816 m_copydata(m, 0, len, mtod(mcl, caddr_t));
1817 mcl->m_len = mcl->m_pkthdr.len = len;