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, NULL, "Libalias sysctl API");
165 #if BYTE_ORDER == LITTLE_ENDIAN
166 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
167 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
169 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
170 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
175 /* TCP Handling Routines
177 TcpMonitorIn() -- These routines monitor TCP connections, and
178 TcpMonitorOut() delete a link when a connection is closed.
180 These routines look for SYN, FIN and RST flags to determine when TCP
181 connections open and close. When a TCP connection closes, the data
182 structure containing packet aliasing information is deleted after
186 /* Local prototypes */
187 static void TcpMonitorIn(u_char, struct alias_link *);
189 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);
232 /* Protocol Specific Packet Aliasing Routines
234 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
235 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
236 ProtoAliasIn(), ProtoAliasOut()
237 UdpAliasIn(), UdpAliasOut()
238 TcpAliasIn(), TcpAliasOut()
240 These routines handle protocol specific details of packet aliasing.
241 One may observe a certain amount of repetitive arithmetic in these
242 functions, the purpose of which is to compute a revised checksum
243 without actually summing over the entire data packet, which could be
244 unnecessarily time consuming.
246 The purpose of the packet aliasing routines is to replace the source
247 address of the outgoing packet and then correctly put it back for
248 any incoming packets. For TCP and UDP, ports are also re-mapped.
250 For ICMP echo/timestamp requests and replies, the following scheme
251 is used: the ID number is replaced by an alias for the outgoing
254 ICMP error messages are handled by looking at the IP fragment
255 in the data section of the message.
257 For TCP and UDP protocols, a port number is chosen for an outgoing
258 packet, and then incoming packets are identified by IP address and
259 port numbers. For TCP packets, there is additional logic in the event
260 that sequence and ACK numbers have been altered (as in the case for
261 FTP data port commands).
263 The port numbers used by the packet aliasing module are not true
264 ports in the Unix sense. No sockets are actually bound to ports.
265 They are more correctly thought of as placeholders.
267 All packets go through the aliasing mechanism, whether they come from
268 the gateway machine or other machines on a local area network.
272 /* Local prototypes */
273 static int IcmpAliasIn1(struct libalias *, struct ip *);
274 static int IcmpAliasIn2(struct libalias *, struct ip *);
275 static int IcmpAliasIn(struct libalias *, struct ip *);
277 static int IcmpAliasOut1(struct libalias *, struct ip *, int create);
278 static int IcmpAliasOut2(struct libalias *, struct ip *);
279 static int IcmpAliasOut(struct libalias *, struct ip *, int create);
281 static int ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
282 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum);
283 static int ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
284 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum,
287 static int UdpAliasIn(struct libalias *, struct ip *);
288 static int UdpAliasOut(struct libalias *, struct ip *, int, int create);
290 static int TcpAliasIn(struct libalias *, struct ip *);
291 static int TcpAliasOut(struct libalias *, struct ip *, int, int create);
295 IcmpAliasIn1(struct libalias *la, struct ip *pip)
298 LIBALIAS_LOCK_ASSERT(la);
300 De-alias incoming echo and timestamp replies.
301 Alias incoming echo and timestamp requests.
303 struct alias_link *lnk;
306 ic = (struct icmp *)ip_next(pip);
308 /* Get source address from ICMP data field and restore original data */
309 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
314 original_id = GetOriginalPort(lnk);
316 /* Adjust ICMP checksum */
317 accumulate = ic->icmp_id;
318 accumulate -= original_id;
319 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
321 /* Put original sequence number back in */
322 ic->icmp_id = original_id;
324 /* Put original address back into IP header */
326 struct in_addr original_address;
328 original_address = GetOriginalAddress(lnk);
329 DifferentialChecksum(&pip->ip_sum,
330 &original_address, &pip->ip_dst, 2);
331 pip->ip_dst = original_address;
334 return (PKT_ALIAS_OK);
336 return (PKT_ALIAS_IGNORED);
340 IcmpAliasIn2(struct libalias *la, struct ip *pip)
343 LIBALIAS_LOCK_ASSERT(la);
345 Alias incoming ICMP error messages containing
346 IP header and first 64 bits of datagram.
349 struct icmp *ic, *ic2;
352 struct alias_link *lnk;
354 ic = (struct icmp *)ip_next(pip);
357 ud = (struct udphdr *)ip_next(ip);
358 tc = (struct tcphdr *)ip_next(ip);
359 ic2 = (struct icmp *)ip_next(ip);
361 if (ip->ip_p == IPPROTO_UDP)
362 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
363 ud->uh_dport, ud->uh_sport,
365 else if (ip->ip_p == IPPROTO_TCP)
366 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
367 tc->th_dport, tc->th_sport,
369 else if (ip->ip_p == IPPROTO_ICMP) {
370 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
371 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
378 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
379 int accumulate, accumulate2;
380 struct in_addr original_address;
381 u_short original_port;
383 original_address = GetOriginalAddress(lnk);
384 original_port = GetOriginalPort(lnk);
386 /* Adjust ICMP checksum */
387 accumulate = twowords(&ip->ip_src);
388 accumulate -= twowords(&original_address);
389 accumulate += ud->uh_sport;
390 accumulate -= original_port;
391 accumulate2 = accumulate;
392 accumulate2 += ip->ip_sum;
393 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
394 accumulate2 -= ip->ip_sum;
395 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
397 /* Un-alias address in IP header */
398 DifferentialChecksum(&pip->ip_sum,
399 &original_address, &pip->ip_dst, 2);
400 pip->ip_dst = original_address;
402 /* Un-alias address and port number of original IP packet
403 fragment contained in ICMP data section */
404 ip->ip_src = original_address;
405 ud->uh_sport = original_port;
406 } else if (ip->ip_p == IPPROTO_ICMP) {
407 int accumulate, accumulate2;
408 struct in_addr original_address;
411 original_address = GetOriginalAddress(lnk);
412 original_id = GetOriginalPort(lnk);
414 /* Adjust ICMP checksum */
415 accumulate = twowords(&ip->ip_src);
416 accumulate -= twowords(&original_address);
417 accumulate += ic2->icmp_id;
418 accumulate -= original_id;
419 accumulate2 = accumulate;
420 accumulate2 += ip->ip_sum;
421 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
422 accumulate2 -= ip->ip_sum;
423 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
425 /* Un-alias address in IP header */
426 DifferentialChecksum(&pip->ip_sum,
427 &original_address, &pip->ip_dst, 2);
428 pip->ip_dst = original_address;
430 /* Un-alias address of original IP packet and sequence number of
431 embedded ICMP datagram */
432 ip->ip_src = original_address;
433 ic2->icmp_id = original_id;
435 return (PKT_ALIAS_OK);
437 return (PKT_ALIAS_IGNORED);
442 IcmpAliasIn(struct libalias *la, struct ip *pip)
447 LIBALIAS_LOCK_ASSERT(la);
449 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
450 if (dlen < ICMP_MINLEN)
451 return (PKT_ALIAS_IGNORED);
453 /* Return if proxy-only mode is enabled */
454 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
455 return (PKT_ALIAS_OK);
457 ic = (struct icmp *)ip_next(pip);
459 iresult = PKT_ALIAS_IGNORED;
460 switch (ic->icmp_type) {
462 case ICMP_TSTAMPREPLY:
463 if (ic->icmp_code == 0) {
464 iresult = IcmpAliasIn1(la, pip);
468 case ICMP_SOURCEQUENCH:
471 if (dlen < ICMP_ADVLENMIN ||
472 dlen < ICMP_ADVLEN(ic))
473 return (PKT_ALIAS_IGNORED);
474 iresult = IcmpAliasIn2(la, pip);
478 iresult = IcmpAliasIn1(la, pip);
486 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
489 Alias outgoing echo and timestamp requests.
490 De-alias outgoing echo and timestamp replies.
492 struct alias_link *lnk;
495 LIBALIAS_LOCK_ASSERT(la);
496 ic = (struct icmp *)ip_next(pip);
498 /* Save overwritten data for when echo packet returns */
499 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create);
504 alias_id = GetAliasPort(lnk);
506 /* Since data field is being modified, adjust ICMP checksum */
507 accumulate = ic->icmp_id;
508 accumulate -= alias_id;
509 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
511 /* Alias sequence number */
512 ic->icmp_id = alias_id;
514 /* Change source address */
516 struct in_addr alias_address;
518 alias_address = GetAliasAddress(lnk);
519 DifferentialChecksum(&pip->ip_sum,
520 &alias_address, &pip->ip_src, 2);
521 pip->ip_src = alias_address;
524 return (PKT_ALIAS_OK);
526 return (PKT_ALIAS_IGNORED);
531 IcmpAliasOut2(struct libalias *la, struct ip *pip)
534 Alias outgoing ICMP error messages containing
535 IP header and first 64 bits of datagram.
538 struct icmp *ic, *ic2;
541 struct alias_link *lnk;
543 LIBALIAS_LOCK_ASSERT(la);
544 ic = (struct icmp *)ip_next(pip);
547 ud = (struct udphdr *)ip_next(ip);
548 tc = (struct tcphdr *)ip_next(ip);
549 ic2 = (struct icmp *)ip_next(ip);
551 if (ip->ip_p == IPPROTO_UDP)
552 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
553 ud->uh_dport, ud->uh_sport,
555 else if (ip->ip_p == IPPROTO_TCP)
556 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
557 tc->th_dport, tc->th_sport,
559 else if (ip->ip_p == IPPROTO_ICMP) {
560 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
561 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
568 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
570 struct in_addr alias_address;
573 alias_address = GetAliasAddress(lnk);
574 alias_port = GetAliasPort(lnk);
576 /* Adjust ICMP checksum */
577 accumulate = twowords(&ip->ip_dst);
578 accumulate -= twowords(&alias_address);
579 accumulate += ud->uh_dport;
580 accumulate -= alias_port;
581 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
584 * Alias address in IP header if it comes from the host
585 * the original TCP/UDP packet was destined for.
587 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
588 DifferentialChecksum(&pip->ip_sum,
589 &alias_address, &pip->ip_src, 2);
590 pip->ip_src = alias_address;
592 /* Alias address and port number of original IP packet
593 fragment contained in ICMP data section */
594 ip->ip_dst = alias_address;
595 ud->uh_dport = alias_port;
596 } else if (ip->ip_p == IPPROTO_ICMP) {
598 struct in_addr alias_address;
601 alias_address = GetAliasAddress(lnk);
602 alias_id = GetAliasPort(lnk);
604 /* Adjust ICMP checksum */
605 accumulate = twowords(&ip->ip_dst);
606 accumulate -= twowords(&alias_address);
607 accumulate += ic2->icmp_id;
608 accumulate -= alias_id;
609 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
612 * Alias address in IP header if it comes from the host
613 * the original ICMP message was destined for.
615 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
616 DifferentialChecksum(&pip->ip_sum,
617 &alias_address, &pip->ip_src, 2);
618 pip->ip_src = alias_address;
620 /* Alias address of original IP packet and sequence number of
621 embedded ICMP datagram */
622 ip->ip_dst = alias_address;
623 ic2->icmp_id = alias_id;
625 return (PKT_ALIAS_OK);
627 return (PKT_ALIAS_IGNORED);
632 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
637 LIBALIAS_LOCK_ASSERT(la);
640 /* Return if proxy-only mode is enabled */
641 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
642 return (PKT_ALIAS_OK);
644 ic = (struct icmp *)ip_next(pip);
646 iresult = PKT_ALIAS_IGNORED;
647 switch (ic->icmp_type) {
650 if (ic->icmp_code == 0) {
651 iresult = IcmpAliasOut1(la, pip, create);
655 case ICMP_SOURCEQUENCH:
658 iresult = IcmpAliasOut2(la, pip);
661 case ICMP_TSTAMPREPLY:
662 iresult = IcmpAliasOut1(la, pip, create);
668 ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
669 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum)
672 Handle incoming IP packets. The
673 only thing which is done in this case is to alias
674 the dest IP address of the packet to our inside
677 struct alias_link *lnk;
679 LIBALIAS_LOCK_ASSERT(la);
680 /* Return if proxy-only mode is enabled */
681 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
682 return (PKT_ALIAS_OK);
684 lnk = FindProtoIn(la, ip_src, *ip_dst, ip_p);
686 struct in_addr original_address;
688 original_address = GetOriginalAddress(lnk);
690 /* Restore original IP address */
691 DifferentialChecksum(ip_sum,
692 &original_address, ip_dst, 2);
693 *ip_dst = original_address;
695 return (PKT_ALIAS_OK);
697 return (PKT_ALIAS_IGNORED);
701 ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
702 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
705 Handle outgoing IP packets. The
706 only thing which is done in this case is to alias
707 the source IP address of the packet.
709 struct alias_link *lnk;
711 LIBALIAS_LOCK_ASSERT(la);
713 /* Return if proxy-only mode is enabled */
714 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
715 return (PKT_ALIAS_OK);
718 return (PKT_ALIAS_IGNORED);
720 lnk = FindProtoOut(la, *ip_src, ip_dst, ip_p);
722 struct in_addr alias_address;
724 alias_address = GetAliasAddress(lnk);
726 /* Change source address */
727 DifferentialChecksum(ip_sum,
728 &alias_address, ip_src, 2);
729 *ip_src = alias_address;
731 return (PKT_ALIAS_OK);
733 return (PKT_ALIAS_IGNORED);
738 UdpAliasIn(struct libalias *la, struct ip *pip)
741 struct alias_link *lnk;
744 LIBALIAS_LOCK_ASSERT(la);
746 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
747 if (dlen < sizeof(struct udphdr))
748 return (PKT_ALIAS_IGNORED);
750 ud = (struct udphdr *)ip_next(pip);
751 if (dlen < ntohs(ud->uh_ulen))
752 return (PKT_ALIAS_IGNORED);
754 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
755 ud->uh_sport, ud->uh_dport,
756 IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
758 struct in_addr alias_address;
759 struct in_addr original_address;
760 struct in_addr proxy_address;
765 struct alias_data ad = {
767 .oaddr = &original_address,
768 .aaddr = &alias_address,
769 .aport = &alias_port,
770 .sport = &ud->uh_sport,
771 .dport = &ud->uh_dport,
775 alias_address = GetAliasAddress(lnk);
776 original_address = GetOriginalAddress(lnk);
777 proxy_address = GetProxyAddress(lnk);
778 alias_port = ud->uh_dport;
779 ud->uh_dport = GetOriginalPort(lnk);
780 proxy_port = GetProxyPort(lnk);
782 /* Walk out chain. */
783 error = find_handler(IN, UDP, la, pip, &ad);
784 /* If we cannot figure out the packet, ignore it. */
786 return (PKT_ALIAS_IGNORED);
788 /* If UDP checksum is not zero, then adjust since destination port */
789 /* is being unaliased and destination address is being altered. */
790 if (ud->uh_sum != 0) {
791 accumulate = alias_port;
792 accumulate -= ud->uh_dport;
793 accumulate += twowords(&alias_address);
794 accumulate -= twowords(&original_address);
796 /* If this is a proxy packet, modify checksum because of source change.*/
797 if (proxy_port != 0) {
798 accumulate += ud->uh_sport;
799 accumulate -= proxy_port;
802 if (proxy_address.s_addr != 0) {
803 accumulate += twowords(&pip->ip_src);
804 accumulate -= twowords(&proxy_address);
807 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
809 /* XXX: Could the two if's below be concatenated to one ? */
810 /* Restore source port and/or address in case of proxying*/
813 ud->uh_sport = proxy_port;
815 if (proxy_address.s_addr != 0) {
816 DifferentialChecksum(&pip->ip_sum,
817 &proxy_address, &pip->ip_src, 2);
818 pip->ip_src = proxy_address;
821 /* Restore original IP address */
822 DifferentialChecksum(&pip->ip_sum,
823 &original_address, &pip->ip_dst, 2);
824 pip->ip_dst = original_address;
826 return (PKT_ALIAS_OK);
828 return (PKT_ALIAS_IGNORED);
832 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
835 struct alias_link *lnk;
836 struct in_addr dest_address;
837 struct in_addr proxy_server_address;
839 u_short proxy_server_port;
843 LIBALIAS_LOCK_ASSERT(la);
845 /* Return if proxy-only mode is enabled and not proxyrule found.*/
846 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
847 if (dlen < sizeof(struct udphdr))
848 return (PKT_ALIAS_IGNORED);
850 ud = (struct udphdr *)ip_next(pip);
851 if (dlen < ntohs(ud->uh_ulen))
852 return (PKT_ALIAS_IGNORED);
854 proxy_type = ProxyCheck(la, &proxy_server_address,
855 &proxy_server_port, pip->ip_src, pip->ip_dst,
856 ud->uh_dport, pip->ip_p);
857 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
858 return (PKT_ALIAS_OK);
860 /* If this is a transparent proxy, save original destination,
861 * then alter the destination and adjust checksums */
862 dest_port = ud->uh_dport;
863 dest_address = pip->ip_dst;
865 if (proxy_type != 0) {
868 accumulate = twowords(&pip->ip_dst);
869 accumulate -= twowords(&proxy_server_address);
871 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
873 if (ud->uh_sum != 0) {
874 accumulate = twowords(&pip->ip_dst);
875 accumulate -= twowords(&proxy_server_address);
876 accumulate += ud->uh_dport;
877 accumulate -= proxy_server_port;
878 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
880 pip->ip_dst = proxy_server_address;
881 ud->uh_dport = proxy_server_port;
883 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
884 ud->uh_sport, ud->uh_dport,
885 IPPROTO_UDP, create);
888 struct in_addr alias_address;
889 struct alias_data ad = {
892 .aaddr = &alias_address,
893 .aport = &alias_port,
894 .sport = &ud->uh_sport,
895 .dport = &ud->uh_dport,
899 /* Save original destination address, if this is a proxy packet.
900 * Also modify packet to include destination encoding. This may
901 * change the size of IP header. */
902 if (proxy_type != 0) {
903 SetProxyPort(lnk, dest_port);
904 SetProxyAddress(lnk, dest_address);
905 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
906 ud = (struct udphdr *)ip_next(pip);
909 alias_address = GetAliasAddress(lnk);
910 alias_port = GetAliasPort(lnk);
912 /* Walk out chain. */
913 error = find_handler(OUT, UDP, la, pip, &ad);
915 /* If UDP checksum is not zero, adjust since source port is */
916 /* being aliased and source address is being altered */
917 if (ud->uh_sum != 0) {
920 accumulate = ud->uh_sport;
921 accumulate -= alias_port;
922 accumulate += twowords(&pip->ip_src);
923 accumulate -= twowords(&alias_address);
924 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
926 /* Put alias port in UDP header */
927 ud->uh_sport = alias_port;
929 /* Change source address */
930 DifferentialChecksum(&pip->ip_sum,
931 &alias_address, &pip->ip_src, 2);
932 pip->ip_src = alias_address;
934 return (PKT_ALIAS_OK);
936 return (PKT_ALIAS_IGNORED);
942 TcpAliasIn(struct libalias *la, struct ip *pip)
945 struct alias_link *lnk;
948 LIBALIAS_LOCK_ASSERT(la);
950 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
951 if (dlen < sizeof(struct tcphdr))
952 return (PKT_ALIAS_IGNORED);
953 tc = (struct tcphdr *)ip_next(pip);
955 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
956 tc->th_sport, tc->th_dport,
958 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
960 struct in_addr alias_address;
961 struct in_addr original_address;
962 struct in_addr proxy_address;
965 int accumulate, error;
968 * The init of MANY vars is a bit below, but aliashandlepptpin
969 * seems to need the destination port that came within the
970 * packet and not the original one looks below [*].
973 struct alias_data ad = {
978 .sport = &tc->th_sport,
979 .dport = &tc->th_dport,
983 /* Walk out chain. */
984 error = find_handler(IN, TCP, la, pip, &ad);
986 alias_address = GetAliasAddress(lnk);
987 original_address = GetOriginalAddress(lnk);
988 proxy_address = GetProxyAddress(lnk);
989 alias_port = tc->th_dport;
990 tc->th_dport = GetOriginalPort(lnk);
991 proxy_port = GetProxyPort(lnk);
994 * Look above, if anyone is going to add find_handler AFTER
995 * this aliashandlepptpin/point, please redo alias_data too.
996 * Uncommenting the piece here below should be enough.
999 struct alias_data ad = {
1001 .oaddr = &original_address,
1002 .aaddr = &alias_address,
1003 .aport = &alias_port,
1004 .sport = &ud->uh_sport,
1005 .dport = &ud->uh_dport,
1009 /* Walk out chain. */
1010 error = find_handler(la, pip, &ad);
1011 if (error == EHDNOF)
1012 printf("Protocol handler not found\n");
1015 /* Adjust TCP checksum since destination port is being unaliased */
1016 /* and destination port is being altered. */
1017 accumulate = alias_port;
1018 accumulate -= tc->th_dport;
1019 accumulate += twowords(&alias_address);
1020 accumulate -= twowords(&original_address);
1022 /* If this is a proxy, then modify the TCP source port and
1023 checksum accumulation */
1024 if (proxy_port != 0) {
1025 accumulate += tc->th_sport;
1026 tc->th_sport = proxy_port;
1027 accumulate -= tc->th_sport;
1028 accumulate += twowords(&pip->ip_src);
1029 accumulate -= twowords(&proxy_address);
1031 /* See if ACK number needs to be modified */
1032 if (GetAckModified(lnk) == 1) {
1035 tc = (struct tcphdr *)ip_next(pip);
1036 delta = GetDeltaAckIn(tc->th_ack, lnk);
1038 accumulate += twowords(&tc->th_ack);
1039 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
1040 accumulate -= twowords(&tc->th_ack);
1043 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1045 /* Restore original IP address */
1046 accumulate = twowords(&pip->ip_dst);
1047 pip->ip_dst = original_address;
1048 accumulate -= twowords(&pip->ip_dst);
1050 /* If this is a transparent proxy packet, then modify the source
1052 if (proxy_address.s_addr != 0) {
1053 accumulate += twowords(&pip->ip_src);
1054 pip->ip_src = proxy_address;
1055 accumulate -= twowords(&pip->ip_src);
1057 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1059 /* Monitor TCP connection state */
1060 tc = (struct tcphdr *)ip_next(pip);
1061 TcpMonitorIn(tc->th_flags, lnk);
1063 return (PKT_ALIAS_OK);
1065 return (PKT_ALIAS_IGNORED);
1069 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
1071 int dlen, proxy_type, error;
1073 u_short proxy_server_port;
1074 struct in_addr dest_address;
1075 struct in_addr proxy_server_address;
1077 struct alias_link *lnk;
1079 LIBALIAS_LOCK_ASSERT(la);
1081 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
1082 if (dlen < sizeof(struct tcphdr))
1083 return (PKT_ALIAS_IGNORED);
1084 tc = (struct tcphdr *)ip_next(pip);
1087 proxy_type = ProxyCheck(la, &proxy_server_address,
1088 &proxy_server_port, pip->ip_src, pip->ip_dst,
1089 tc->th_dport, pip->ip_p);
1093 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1094 return (PKT_ALIAS_OK);
1096 /* If this is a transparent proxy, save original destination,
1097 then alter the destination and adjust checksums */
1098 dest_port = tc->th_dport;
1099 dest_address = pip->ip_dst;
1100 if (proxy_type != 0) {
1103 accumulate = tc->th_dport;
1104 tc->th_dport = proxy_server_port;
1105 accumulate -= tc->th_dport;
1106 accumulate += twowords(&pip->ip_dst);
1107 accumulate -= twowords(&proxy_server_address);
1108 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1110 accumulate = twowords(&pip->ip_dst);
1111 pip->ip_dst = proxy_server_address;
1112 accumulate -= twowords(&pip->ip_dst);
1113 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1115 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
1116 tc->th_sport, tc->th_dport,
1117 IPPROTO_TCP, create);
1119 return (PKT_ALIAS_IGNORED);
1122 struct in_addr alias_address;
1124 struct alias_data ad = {
1127 .aaddr = &alias_address,
1128 .aport = &alias_port,
1129 .sport = &tc->th_sport,
1130 .dport = &tc->th_dport,
1131 .maxpktsize = maxpacketsize
1134 /* Save original destination address, if this is a proxy packet.
1135 Also modify packet to include destination encoding. This may
1136 change the size of IP header. */
1137 if (proxy_type != 0) {
1138 SetProxyPort(lnk, dest_port);
1139 SetProxyAddress(lnk, dest_address);
1140 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
1141 tc = (struct tcphdr *)ip_next(pip);
1143 /* Get alias address and port */
1144 alias_port = GetAliasPort(lnk);
1145 alias_address = GetAliasAddress(lnk);
1147 /* Monitor TCP connection state */
1148 tc = (struct tcphdr *)ip_next(pip);
1149 TcpMonitorOut(tc->th_flags, lnk);
1151 /* Walk out chain. */
1152 error = find_handler(OUT, TCP, la, pip, &ad);
1154 /* Adjust TCP checksum since source port is being aliased */
1155 /* and source address is being altered */
1156 accumulate = tc->th_sport;
1157 tc->th_sport = alias_port;
1158 accumulate -= tc->th_sport;
1159 accumulate += twowords(&pip->ip_src);
1160 accumulate -= twowords(&alias_address);
1162 /* Modify sequence number if necessary */
1163 if (GetAckModified(lnk) == 1) {
1166 tc = (struct tcphdr *)ip_next(pip);
1167 delta = GetDeltaSeqOut(tc->th_seq, lnk);
1169 accumulate += twowords(&tc->th_seq);
1170 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1171 accumulate -= twowords(&tc->th_seq);
1174 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1176 /* Change source address */
1177 accumulate = twowords(&pip->ip_src);
1178 pip->ip_src = alias_address;
1179 accumulate -= twowords(&pip->ip_src);
1180 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1182 return (PKT_ALIAS_OK);
1184 return (PKT_ALIAS_IGNORED);
1190 /* Fragment Handling
1195 The packet aliasing module has a limited ability for handling IP
1196 fragments. If the ICMP, TCP or UDP header is in the first fragment
1197 received, then the ID number of the IP packet is saved, and other
1198 fragments are identified according to their ID number and IP address
1199 they were sent from. Pointers to unresolved fragments can also be
1200 saved and recalled when a header fragment is seen.
1203 /* Local prototypes */
1204 static int FragmentIn(struct libalias *la, struct in_addr ip_src,
1205 struct in_addr *ip_dst, u_short ip_id, u_short *ip_sum);
1206 static int FragmentOut(struct libalias *, struct in_addr *ip_src,
1210 FragmentIn(struct libalias *la, struct in_addr ip_src, struct in_addr *ip_dst,
1211 u_short ip_id, u_short *ip_sum)
1213 struct alias_link *lnk;
1215 LIBALIAS_LOCK_ASSERT(la);
1216 lnk = FindFragmentIn2(la, ip_src, *ip_dst, ip_id);
1218 struct in_addr original_address;
1220 GetFragmentAddr(lnk, &original_address);
1221 DifferentialChecksum(ip_sum,
1222 &original_address, ip_dst, 2);
1223 *ip_dst = original_address;
1225 return (PKT_ALIAS_OK);
1227 return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1231 FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum)
1233 struct in_addr alias_address;
1235 LIBALIAS_LOCK_ASSERT(la);
1236 alias_address = FindAliasAddress(la, *ip_src);
1237 DifferentialChecksum(ip_sum,
1238 &alias_address, ip_src, 2);
1239 *ip_src = alias_address;
1241 return (PKT_ALIAS_OK);
1249 /* Outside World Access
1251 PacketAliasSaveFragment()
1252 PacketAliasGetFragment()
1253 PacketAliasFragmentIn()
1258 (prototypes in alias.h)
1262 LibAliasSaveFragment(struct libalias *la, char *ptr)
1265 struct alias_link *lnk;
1269 pip = (struct ip *)ptr;
1270 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1271 iresult = PKT_ALIAS_ERROR;
1273 SetFragmentPtr(lnk, ptr);
1274 iresult = PKT_ALIAS_OK;
1276 LIBALIAS_UNLOCK(la);
1281 LibAliasGetFragment(struct libalias *la, char *ptr)
1283 struct alias_link *lnk;
1288 pip = (struct ip *)ptr;
1289 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1291 GetFragmentPtr(lnk, &fptr);
1292 SetFragmentPtr(lnk, NULL);
1293 SetExpire(lnk, 0); /* Deletes link */
1297 LIBALIAS_UNLOCK(la);
1302 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
1305 char *ptr_fragment /* Points to fragment which must be
1314 pip = (struct ip *)ptr;
1315 fpip = (struct ip *)ptr_fragment;
1317 DifferentialChecksum(&fpip->ip_sum,
1318 &pip->ip_dst, &fpip->ip_dst, 2);
1319 fpip->ip_dst = pip->ip_dst;
1320 LIBALIAS_UNLOCK(la);
1323 /* Local prototypes */
1325 LibAliasOutLocked(struct libalias *la, char *ptr,
1326 int maxpacketsize, int create);
1328 LibAliasInLocked(struct libalias *la, char *ptr,
1332 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1337 res = LibAliasInLocked(la, ptr, maxpacketsize);
1338 LIBALIAS_UNLOCK(la);
1343 LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize)
1345 struct in_addr alias_addr;
1349 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1350 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1351 iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1352 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1356 ClearCheckNewLink(la);
1357 pip = (struct ip *)ptr;
1358 alias_addr = pip->ip_dst;
1360 /* Defense against mangled packets */
1361 if (ntohs(pip->ip_len) > maxpacketsize
1362 || (pip->ip_hl << 2) > maxpacketsize) {
1363 iresult = PKT_ALIAS_IGNORED;
1367 iresult = PKT_ALIAS_IGNORED;
1368 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1369 switch (pip->ip_p) {
1371 iresult = IcmpAliasIn(la, pip);
1374 iresult = UdpAliasIn(la, pip);
1377 iresult = TcpAliasIn(la, pip);
1381 iresult = SctpAlias(la, pip, SN_TO_LOCAL);
1386 struct alias_data ad = {
1396 /* Walk out chain. */
1397 error = find_handler(IN, IP, la, pip, &ad);
1399 iresult = PKT_ALIAS_OK;
1401 iresult = ProtoAliasIn(la, pip->ip_src,
1402 &pip->ip_dst, pip->ip_p, &pip->ip_sum);
1406 iresult = ProtoAliasIn(la, pip->ip_src, &pip->ip_dst,
1407 pip->ip_p, &pip->ip_sum);
1411 if (ntohs(pip->ip_off) & IP_MF) {
1412 struct alias_link *lnk;
1414 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1416 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1417 SetFragmentAddr(lnk, pip->ip_dst);
1419 iresult = PKT_ALIAS_ERROR;
1423 iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id,
1433 /* Unregistered address ranges */
1435 /* 10.0.0.0 -> 10.255.255.255 */
1436 #define UNREG_ADDR_A_LOWER 0x0a000000
1437 #define UNREG_ADDR_A_UPPER 0x0affffff
1439 /* 172.16.0.0 -> 172.31.255.255 */
1440 #define UNREG_ADDR_B_LOWER 0xac100000
1441 #define UNREG_ADDR_B_UPPER 0xac1fffff
1443 /* 192.168.0.0 -> 192.168.255.255 */
1444 #define UNREG_ADDR_C_LOWER 0xc0a80000
1445 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1448 LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize)
1453 res = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1454 LIBALIAS_UNLOCK(la);
1459 LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create)
1464 res = LibAliasOutLocked(la, ptr, maxpacketsize, create);
1465 LIBALIAS_UNLOCK(la);
1470 LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */
1471 int maxpacketsize, /* How much the packet data may grow (FTP
1472 * and IRC inline changes) */
1473 int create /* Create new entries ? */
1477 struct in_addr addr_save;
1480 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1481 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1482 iresult = LibAliasInLocked(la, ptr, maxpacketsize);
1483 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1487 ClearCheckNewLink(la);
1488 pip = (struct ip *)ptr;
1490 /* Defense against mangled packets */
1491 if (ntohs(pip->ip_len) > maxpacketsize
1492 || (pip->ip_hl << 2) > maxpacketsize) {
1493 iresult = PKT_ALIAS_IGNORED;
1497 addr_save = GetDefaultAliasAddress(la);
1498 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) {
1503 addr = ntohl(pip->ip_src.s_addr);
1504 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1506 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1508 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1512 SetDefaultAliasAddress(la, pip->ip_src);
1514 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1515 SetDefaultAliasAddress(la, pip->ip_src);
1517 iresult = PKT_ALIAS_IGNORED;
1518 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1519 switch (pip->ip_p) {
1521 iresult = IcmpAliasOut(la, pip, create);
1524 iresult = UdpAliasOut(la, pip, maxpacketsize, create);
1527 iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1531 iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
1536 struct alias_data ad = {
1545 /* Walk out chain. */
1546 error = find_handler(OUT, IP, la, pip, &ad);
1548 iresult = PKT_ALIAS_OK;
1550 iresult = ProtoAliasOut(la, &pip->ip_src,
1551 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1555 iresult = ProtoAliasOut(la, &pip->ip_src,
1556 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1560 iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum);
1563 SetDefaultAliasAddress(la, addr_save);
1569 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1570 int maxpacketsize /* for error checking */
1577 struct alias_link *lnk;
1578 int iresult = PKT_ALIAS_IGNORED;
1581 pip = (struct ip *)ptr;
1583 /* Defense against mangled packets */
1584 if (ntohs(pip->ip_len) > maxpacketsize
1585 || (pip->ip_hl << 2) > maxpacketsize)
1588 ud = (struct udphdr *)ip_next(pip);
1589 tc = (struct tcphdr *)ip_next(pip);
1590 ic = (struct icmp *)ip_next(pip);
1593 if (pip->ip_p == IPPROTO_UDP)
1594 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1595 ud->uh_dport, ud->uh_sport,
1597 else if (pip->ip_p == IPPROTO_TCP)
1598 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1599 tc->th_dport, tc->th_sport,
1601 else if (pip->ip_p == IPPROTO_ICMP)
1602 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1606 /* Change it from an aliased packet to an unaliased packet */
1608 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1610 struct in_addr original_address;
1611 u_short original_port;
1613 original_address = GetOriginalAddress(lnk);
1614 original_port = GetOriginalPort(lnk);
1616 /* Adjust TCP/UDP checksum */
1617 accumulate = twowords(&pip->ip_src);
1618 accumulate -= twowords(&original_address);
1620 if (pip->ip_p == IPPROTO_UDP) {
1621 accumulate += ud->uh_sport;
1622 accumulate -= original_port;
1623 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1625 accumulate += tc->th_sport;
1626 accumulate -= original_port;
1627 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1630 /* Adjust IP checksum */
1631 DifferentialChecksum(&pip->ip_sum,
1632 &original_address, &pip->ip_src, 2);
1634 /* Un-alias source address and port number */
1635 pip->ip_src = original_address;
1636 if (pip->ip_p == IPPROTO_UDP)
1637 ud->uh_sport = original_port;
1639 tc->th_sport = original_port;
1641 iresult = PKT_ALIAS_OK;
1643 } else if (pip->ip_p == IPPROTO_ICMP) {
1646 struct in_addr original_address;
1647 u_short original_id;
1649 original_address = GetOriginalAddress(lnk);
1650 original_id = GetOriginalPort(lnk);
1652 /* Adjust ICMP checksum */
1653 accumulate = twowords(&pip->ip_src);
1654 accumulate -= twowords(&original_address);
1655 accumulate += ic->icmp_id;
1656 accumulate -= original_id;
1657 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1659 /* Adjust IP checksum */
1660 DifferentialChecksum(&pip->ip_sum,
1661 &original_address, &pip->ip_src, 2);
1663 /* Un-alias source address and port number */
1664 pip->ip_src = original_address;
1665 ic->icmp_id = original_id;
1667 iresult = PKT_ALIAS_OK;
1671 LIBALIAS_UNLOCK(la);
1679 LibAliasRefreshModules(void)
1681 char buf[256], conf[] = "/etc/libalias.conf";
1685 fd = fopen(conf, "r");
1687 err(1, "fopen(%s)", conf);
1689 LibAliasUnLoadAllModule();
1692 fgets(buf, 256, fd);
1697 for (i = 0; i < len; i++)
1698 if (!isspace(buf[i]))
1702 buf[len - 1] = '\0';
1703 LibAliasLoadModule(buf);
1711 LibAliasLoadModule(char *path)
1715 struct proto_handler *m;
1719 handle = dlopen (path, RTLD_LAZY);
1721 fprintf(stderr, "%s\n", dlerror());
1725 p = dlsym(handle, "alias_mod");
1726 if ((error = dlerror()) != NULL) {
1727 fprintf(stderr, "%s\n", dlerror());
1731 t = malloc(sizeof(struct dll));
1734 strncpy(t->name, p->name, DLL_LEN);
1736 if (attach_dll(t) == EEXIST) {
1738 fprintf(stderr, "dll conflict\n");
1742 m = dlsym(t->handle, "handlers");
1743 if ((error = dlerror()) != NULL) {
1744 fprintf(stderr, "%s\n", error);
1748 LibAliasAttachHandlers(m);
1753 LibAliasUnLoadAllModule(void)
1756 struct proto_handler *p;
1758 /* Unload all modules then reload everything. */
1759 while ((p = first_handler()) != NULL) {
1760 LibAliasDetachHandlers(p);
1762 while ((t = walk_dll_chain()) != NULL) {
1773 * m_megapullup() - this function is a big hack.
1774 * Thankfully, it's only used in ng_nat and ipfw+nat.
1776 * It allocates an mbuf with cluster and copies the specified part of the chain
1777 * into cluster, so that it is all contiguous and can be accessed via a plain
1778 * (char *) pointer. This is required, because libalias doesn't know how to
1779 * handle mbuf chains.
1781 * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1782 * the input packet, on failure NULL. The input packet is always consumed.
1785 m_megapullup(struct mbuf *m, int len)
1789 if (len > m->m_pkthdr.len)
1792 if (m->m_next == NULL && M_WRITABLE(m))
1795 if (len <= MJUMPAGESIZE)
1796 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
1797 else if (len <= MJUM9BYTES)
1798 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1799 else if (len <= MJUM16BYTES)
1800 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
1806 m_move_pkthdr(mcl, m);
1807 m_copydata(m, 0, len, mtod(mcl, caddr_t));
1808 mcl->m_len = mcl->m_pkthdr.len = len;