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);
448 /* Return if proxy-only mode is enabled */
449 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
450 return (PKT_ALIAS_OK);
452 ic = (struct icmp *)ip_next(pip);
454 iresult = PKT_ALIAS_IGNORED;
455 switch (ic->icmp_type) {
457 case ICMP_TSTAMPREPLY:
458 if (ic->icmp_code == 0) {
459 iresult = IcmpAliasIn1(la, pip);
463 case ICMP_SOURCEQUENCH:
466 iresult = IcmpAliasIn2(la, pip);
470 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);
523 IcmpAliasOut2(struct libalias *la, struct ip *pip)
526 Alias outgoing ICMP error messages containing
527 IP header and first 64 bits of datagram.
530 struct icmp *ic, *ic2;
533 struct alias_link *lnk;
535 LIBALIAS_LOCK_ASSERT(la);
536 ic = (struct icmp *)ip_next(pip);
539 ud = (struct udphdr *)ip_next(ip);
540 tc = (struct tcphdr *)ip_next(ip);
541 ic2 = (struct icmp *)ip_next(ip);
543 if (ip->ip_p == IPPROTO_UDP)
544 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
545 ud->uh_dport, ud->uh_sport,
547 else if (ip->ip_p == IPPROTO_TCP)
548 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
549 tc->th_dport, tc->th_sport,
551 else if (ip->ip_p == IPPROTO_ICMP) {
552 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
553 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
560 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
562 struct in_addr alias_address;
565 alias_address = GetAliasAddress(lnk);
566 alias_port = GetAliasPort(lnk);
568 /* Adjust ICMP checksum */
569 accumulate = twowords(&ip->ip_dst);
570 accumulate -= twowords(&alias_address);
571 accumulate += ud->uh_dport;
572 accumulate -= alias_port;
573 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
576 * Alias address in IP header if it comes from the host
577 * the original TCP/UDP packet was destined for.
579 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
580 DifferentialChecksum(&pip->ip_sum,
581 &alias_address, &pip->ip_src, 2);
582 pip->ip_src = alias_address;
584 /* Alias address and port number of original IP packet
585 fragment contained in ICMP data section */
586 ip->ip_dst = alias_address;
587 ud->uh_dport = alias_port;
588 } else if (ip->ip_p == IPPROTO_ICMP) {
590 struct in_addr alias_address;
593 alias_address = GetAliasAddress(lnk);
594 alias_id = GetAliasPort(lnk);
596 /* Adjust ICMP checksum */
597 accumulate = twowords(&ip->ip_dst);
598 accumulate -= twowords(&alias_address);
599 accumulate += ic2->icmp_id;
600 accumulate -= alias_id;
601 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
604 * Alias address in IP header if it comes from the host
605 * the original ICMP message was destined for.
607 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
608 DifferentialChecksum(&pip->ip_sum,
609 &alias_address, &pip->ip_src, 2);
610 pip->ip_src = alias_address;
612 /* Alias address of original IP packet and sequence number of
613 embedded ICMP datagram */
614 ip->ip_dst = alias_address;
615 ic2->icmp_id = alias_id;
617 return (PKT_ALIAS_OK);
619 return (PKT_ALIAS_IGNORED);
624 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
629 LIBALIAS_LOCK_ASSERT(la);
632 /* Return if proxy-only mode is enabled */
633 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
634 return (PKT_ALIAS_OK);
636 ic = (struct icmp *)ip_next(pip);
638 iresult = PKT_ALIAS_IGNORED;
639 switch (ic->icmp_type) {
642 if (ic->icmp_code == 0) {
643 iresult = IcmpAliasOut1(la, pip, create);
647 case ICMP_SOURCEQUENCH:
650 iresult = IcmpAliasOut2(la, pip);
653 case ICMP_TSTAMPREPLY:
654 iresult = IcmpAliasOut1(la, pip, create);
660 ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
661 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum)
664 Handle incoming IP packets. The
665 only thing which is done in this case is to alias
666 the dest IP address of the packet to our inside
669 struct alias_link *lnk;
671 LIBALIAS_LOCK_ASSERT(la);
672 /* Return if proxy-only mode is enabled */
673 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
674 return (PKT_ALIAS_OK);
676 lnk = FindProtoIn(la, ip_src, *ip_dst, ip_p);
678 struct in_addr original_address;
680 original_address = GetOriginalAddress(lnk);
682 /* Restore original IP address */
683 DifferentialChecksum(ip_sum,
684 &original_address, ip_dst, 2);
685 *ip_dst = original_address;
687 return (PKT_ALIAS_OK);
689 return (PKT_ALIAS_IGNORED);
693 ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
694 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
697 Handle outgoing IP packets. The
698 only thing which is done in this case is to alias
699 the source IP address of the packet.
701 struct alias_link *lnk;
703 LIBALIAS_LOCK_ASSERT(la);
705 /* Return if proxy-only mode is enabled */
706 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
707 return (PKT_ALIAS_OK);
710 return (PKT_ALIAS_IGNORED);
712 lnk = FindProtoOut(la, *ip_src, ip_dst, ip_p);
714 struct in_addr alias_address;
716 alias_address = GetAliasAddress(lnk);
718 /* Change source address */
719 DifferentialChecksum(ip_sum,
720 &alias_address, ip_src, 2);
721 *ip_src = alias_address;
723 return (PKT_ALIAS_OK);
725 return (PKT_ALIAS_IGNORED);
730 UdpAliasIn(struct libalias *la, struct ip *pip)
733 struct alias_link *lnk;
735 LIBALIAS_LOCK_ASSERT(la);
737 ud = (struct udphdr *)ip_next(pip);
739 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
740 ud->uh_sport, ud->uh_dport,
741 IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
743 struct in_addr alias_address;
744 struct in_addr original_address;
745 struct in_addr proxy_address;
750 struct alias_data ad = {
752 .oaddr = &original_address,
753 .aaddr = &alias_address,
754 .aport = &alias_port,
755 .sport = &ud->uh_sport,
756 .dport = &ud->uh_dport,
760 alias_address = GetAliasAddress(lnk);
761 original_address = GetOriginalAddress(lnk);
762 proxy_address = GetProxyAddress(lnk);
763 alias_port = ud->uh_dport;
764 ud->uh_dport = GetOriginalPort(lnk);
765 proxy_port = GetProxyPort(lnk);
767 /* Walk out chain. */
768 error = find_handler(IN, UDP, la, pip, &ad);
769 /* If we cannot figure out the packet, ignore it. */
771 return (PKT_ALIAS_IGNORED);
773 /* If UDP checksum is not zero, then adjust since destination port */
774 /* is being unaliased and destination address is being altered. */
775 if (ud->uh_sum != 0) {
776 accumulate = alias_port;
777 accumulate -= ud->uh_dport;
778 accumulate += twowords(&alias_address);
779 accumulate -= twowords(&original_address);
781 /* If this is a proxy packet, modify checksum because of source change.*/
782 if (proxy_port != 0) {
783 accumulate += ud->uh_sport;
784 accumulate -= proxy_port;
787 if (proxy_address.s_addr != 0) {
788 accumulate += twowords(&pip->ip_src);
789 accumulate -= twowords(&proxy_address);
792 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
794 /* XXX: Could the two if's below be concatenated to one ? */
795 /* Restore source port and/or address in case of proxying*/
798 ud->uh_sport = proxy_port;
800 if (proxy_address.s_addr != 0) {
801 DifferentialChecksum(&pip->ip_sum,
802 &proxy_address, &pip->ip_src, 2);
803 pip->ip_src = proxy_address;
806 /* Restore original IP address */
807 DifferentialChecksum(&pip->ip_sum,
808 &original_address, &pip->ip_dst, 2);
809 pip->ip_dst = original_address;
811 return (PKT_ALIAS_OK);
813 return (PKT_ALIAS_IGNORED);
817 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
820 struct alias_link *lnk;
821 struct in_addr dest_address;
822 struct in_addr proxy_server_address;
824 u_short proxy_server_port;
828 LIBALIAS_LOCK_ASSERT(la);
830 /* Return if proxy-only mode is enabled and not proxyrule found.*/
831 ud = (struct udphdr *)ip_next(pip);
832 proxy_type = ProxyCheck(la, &proxy_server_address,
833 &proxy_server_port, pip->ip_src, pip->ip_dst,
834 ud->uh_dport, pip->ip_p);
835 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
836 return (PKT_ALIAS_OK);
838 /* If this is a transparent proxy, save original destination,
839 * then alter the destination and adjust checksums */
840 dest_port = ud->uh_dport;
841 dest_address = pip->ip_dst;
843 if (proxy_type != 0) {
846 accumulate = twowords(&pip->ip_dst);
847 accumulate -= twowords(&proxy_server_address);
849 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
851 if (ud->uh_sum != 0) {
852 accumulate = twowords(&pip->ip_dst);
853 accumulate -= twowords(&proxy_server_address);
854 accumulate += ud->uh_dport;
855 accumulate -= proxy_server_port;
856 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
858 pip->ip_dst = proxy_server_address;
859 ud->uh_dport = proxy_server_port;
861 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
862 ud->uh_sport, ud->uh_dport,
863 IPPROTO_UDP, create);
866 struct in_addr alias_address;
867 struct alias_data ad = {
870 .aaddr = &alias_address,
871 .aport = &alias_port,
872 .sport = &ud->uh_sport,
873 .dport = &ud->uh_dport,
877 /* Save original destination address, if this is a proxy packet.
878 * Also modify packet to include destination encoding. This may
879 * change the size of IP header. */
880 if (proxy_type != 0) {
881 SetProxyPort(lnk, dest_port);
882 SetProxyAddress(lnk, dest_address);
883 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
884 ud = (struct udphdr *)ip_next(pip);
887 alias_address = GetAliasAddress(lnk);
888 alias_port = GetAliasPort(lnk);
890 /* Walk out chain. */
891 error = find_handler(OUT, UDP, la, pip, &ad);
893 /* If UDP checksum is not zero, adjust since source port is */
894 /* being aliased and source address is being altered */
895 if (ud->uh_sum != 0) {
898 accumulate = ud->uh_sport;
899 accumulate -= alias_port;
900 accumulate += twowords(&pip->ip_src);
901 accumulate -= twowords(&alias_address);
902 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
904 /* Put alias port in UDP header */
905 ud->uh_sport = alias_port;
907 /* Change source address */
908 DifferentialChecksum(&pip->ip_sum,
909 &alias_address, &pip->ip_src, 2);
910 pip->ip_src = alias_address;
912 return (PKT_ALIAS_OK);
914 return (PKT_ALIAS_IGNORED);
920 TcpAliasIn(struct libalias *la, struct ip *pip)
923 struct alias_link *lnk;
925 LIBALIAS_LOCK_ASSERT(la);
926 tc = (struct tcphdr *)ip_next(pip);
928 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
929 tc->th_sport, tc->th_dport,
931 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
933 struct in_addr alias_address;
934 struct in_addr original_address;
935 struct in_addr proxy_address;
938 int accumulate, error;
941 * The init of MANY vars is a bit below, but aliashandlepptpin
942 * seems to need the destination port that came within the
943 * packet and not the original one looks below [*].
946 struct alias_data ad = {
951 .sport = &tc->th_sport,
952 .dport = &tc->th_dport,
956 /* Walk out chain. */
957 error = find_handler(IN, TCP, la, pip, &ad);
959 alias_address = GetAliasAddress(lnk);
960 original_address = GetOriginalAddress(lnk);
961 proxy_address = GetProxyAddress(lnk);
962 alias_port = tc->th_dport;
963 tc->th_dport = GetOriginalPort(lnk);
964 proxy_port = GetProxyPort(lnk);
967 * Look above, if anyone is going to add find_handler AFTER
968 * this aliashandlepptpin/point, please redo alias_data too.
969 * Uncommenting the piece here below should be enough.
972 struct alias_data ad = {
974 .oaddr = &original_address,
975 .aaddr = &alias_address,
976 .aport = &alias_port,
977 .sport = &ud->uh_sport,
978 .dport = &ud->uh_dport,
982 /* Walk out chain. */
983 error = find_handler(la, pip, &ad);
985 printf("Protocol handler not found\n");
988 /* Adjust TCP checksum since destination port is being unaliased */
989 /* and destination port is being altered. */
990 accumulate = alias_port;
991 accumulate -= tc->th_dport;
992 accumulate += twowords(&alias_address);
993 accumulate -= twowords(&original_address);
995 /* If this is a proxy, then modify the TCP source port and
996 checksum accumulation */
997 if (proxy_port != 0) {
998 accumulate += tc->th_sport;
999 tc->th_sport = proxy_port;
1000 accumulate -= tc->th_sport;
1001 accumulate += twowords(&pip->ip_src);
1002 accumulate -= twowords(&proxy_address);
1004 /* See if ACK number needs to be modified */
1005 if (GetAckModified(lnk) == 1) {
1008 tc = (struct tcphdr *)ip_next(pip);
1009 delta = GetDeltaAckIn(tc->th_ack, lnk);
1011 accumulate += twowords(&tc->th_ack);
1012 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
1013 accumulate -= twowords(&tc->th_ack);
1016 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1018 /* Restore original IP address */
1019 accumulate = twowords(&pip->ip_dst);
1020 pip->ip_dst = original_address;
1021 accumulate -= twowords(&pip->ip_dst);
1023 /* If this is a transparent proxy packet, then modify the source
1025 if (proxy_address.s_addr != 0) {
1026 accumulate += twowords(&pip->ip_src);
1027 pip->ip_src = proxy_address;
1028 accumulate -= twowords(&pip->ip_src);
1030 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1032 /* Monitor TCP connection state */
1033 tc = (struct tcphdr *)ip_next(pip);
1034 TcpMonitorIn(tc->th_flags, lnk);
1036 return (PKT_ALIAS_OK);
1038 return (PKT_ALIAS_IGNORED);
1042 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
1044 int proxy_type, error;
1046 u_short proxy_server_port;
1047 struct in_addr dest_address;
1048 struct in_addr proxy_server_address;
1050 struct alias_link *lnk;
1052 LIBALIAS_LOCK_ASSERT(la);
1053 tc = (struct tcphdr *)ip_next(pip);
1056 proxy_type = ProxyCheck(la, &proxy_server_address,
1057 &proxy_server_port, pip->ip_src, pip->ip_dst,
1058 tc->th_dport, pip->ip_p);
1062 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1063 return (PKT_ALIAS_OK);
1065 /* If this is a transparent proxy, save original destination,
1066 then alter the destination and adjust checksums */
1067 dest_port = tc->th_dport;
1068 dest_address = pip->ip_dst;
1069 if (proxy_type != 0) {
1072 accumulate = tc->th_dport;
1073 tc->th_dport = proxy_server_port;
1074 accumulate -= tc->th_dport;
1075 accumulate += twowords(&pip->ip_dst);
1076 accumulate -= twowords(&proxy_server_address);
1077 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1079 accumulate = twowords(&pip->ip_dst);
1080 pip->ip_dst = proxy_server_address;
1081 accumulate -= twowords(&pip->ip_dst);
1082 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1084 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
1085 tc->th_sport, tc->th_dport,
1086 IPPROTO_TCP, create);
1088 return (PKT_ALIAS_IGNORED);
1091 struct in_addr alias_address;
1093 struct alias_data ad = {
1096 .aaddr = &alias_address,
1097 .aport = &alias_port,
1098 .sport = &tc->th_sport,
1099 .dport = &tc->th_dport,
1100 .maxpktsize = maxpacketsize
1103 /* Save original destination address, if this is a proxy packet.
1104 Also modify packet to include destination encoding. This may
1105 change the size of IP header. */
1106 if (proxy_type != 0) {
1107 SetProxyPort(lnk, dest_port);
1108 SetProxyAddress(lnk, dest_address);
1109 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
1110 tc = (struct tcphdr *)ip_next(pip);
1112 /* Get alias address and port */
1113 alias_port = GetAliasPort(lnk);
1114 alias_address = GetAliasAddress(lnk);
1116 /* Monitor TCP connection state */
1117 tc = (struct tcphdr *)ip_next(pip);
1118 TcpMonitorOut(tc->th_flags, lnk);
1120 /* Walk out chain. */
1121 error = find_handler(OUT, TCP, la, pip, &ad);
1123 /* Adjust TCP checksum since source port is being aliased */
1124 /* and source address is being altered */
1125 accumulate = tc->th_sport;
1126 tc->th_sport = alias_port;
1127 accumulate -= tc->th_sport;
1128 accumulate += twowords(&pip->ip_src);
1129 accumulate -= twowords(&alias_address);
1131 /* Modify sequence number if necessary */
1132 if (GetAckModified(lnk) == 1) {
1135 tc = (struct tcphdr *)ip_next(pip);
1136 delta = GetDeltaSeqOut(tc->th_seq, lnk);
1138 accumulate += twowords(&tc->th_seq);
1139 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1140 accumulate -= twowords(&tc->th_seq);
1143 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1145 /* Change source address */
1146 accumulate = twowords(&pip->ip_src);
1147 pip->ip_src = alias_address;
1148 accumulate -= twowords(&pip->ip_src);
1149 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1151 return (PKT_ALIAS_OK);
1153 return (PKT_ALIAS_IGNORED);
1159 /* Fragment Handling
1164 The packet aliasing module has a limited ability for handling IP
1165 fragments. If the ICMP, TCP or UDP header is in the first fragment
1166 received, then the ID number of the IP packet is saved, and other
1167 fragments are identified according to their ID number and IP address
1168 they were sent from. Pointers to unresolved fragments can also be
1169 saved and recalled when a header fragment is seen.
1172 /* Local prototypes */
1173 static int FragmentIn(struct libalias *la, struct in_addr ip_src,
1174 struct in_addr *ip_dst, u_short ip_id, u_short *ip_sum);
1175 static int FragmentOut(struct libalias *, struct in_addr *ip_src,
1179 FragmentIn(struct libalias *la, struct in_addr ip_src, struct in_addr *ip_dst,
1180 u_short ip_id, u_short *ip_sum)
1182 struct alias_link *lnk;
1184 LIBALIAS_LOCK_ASSERT(la);
1185 lnk = FindFragmentIn2(la, ip_src, *ip_dst, ip_id);
1187 struct in_addr original_address;
1189 GetFragmentAddr(lnk, &original_address);
1190 DifferentialChecksum(ip_sum,
1191 &original_address, ip_dst, 2);
1192 *ip_dst = original_address;
1194 return (PKT_ALIAS_OK);
1196 return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1200 FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum)
1202 struct in_addr alias_address;
1204 LIBALIAS_LOCK_ASSERT(la);
1205 alias_address = FindAliasAddress(la, *ip_src);
1206 DifferentialChecksum(ip_sum,
1207 &alias_address, ip_src, 2);
1208 *ip_src = alias_address;
1210 return (PKT_ALIAS_OK);
1218 /* Outside World Access
1220 PacketAliasSaveFragment()
1221 PacketAliasGetFragment()
1222 PacketAliasFragmentIn()
1227 (prototypes in alias.h)
1231 LibAliasSaveFragment(struct libalias *la, char *ptr)
1234 struct alias_link *lnk;
1238 pip = (struct ip *)ptr;
1239 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1240 iresult = PKT_ALIAS_ERROR;
1242 SetFragmentPtr(lnk, ptr);
1243 iresult = PKT_ALIAS_OK;
1245 LIBALIAS_UNLOCK(la);
1250 LibAliasGetFragment(struct libalias *la, char *ptr)
1252 struct alias_link *lnk;
1257 pip = (struct ip *)ptr;
1258 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1260 GetFragmentPtr(lnk, &fptr);
1261 SetFragmentPtr(lnk, NULL);
1262 SetExpire(lnk, 0); /* Deletes link */
1266 LIBALIAS_UNLOCK(la);
1271 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
1274 char *ptr_fragment /* Points to fragment which must be
1283 pip = (struct ip *)ptr;
1284 fpip = (struct ip *)ptr_fragment;
1286 DifferentialChecksum(&fpip->ip_sum,
1287 &pip->ip_dst, &fpip->ip_dst, 2);
1288 fpip->ip_dst = pip->ip_dst;
1289 LIBALIAS_UNLOCK(la);
1292 /* Local prototypes */
1294 LibAliasOutLocked(struct libalias *la, char *ptr,
1295 int maxpacketsize, int create);
1297 LibAliasInLocked(struct libalias *la, char *ptr,
1301 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1306 res = LibAliasInLocked(la, ptr, maxpacketsize);
1307 LIBALIAS_UNLOCK(la);
1312 LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize)
1314 struct in_addr alias_addr;
1318 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1319 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1320 iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1321 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1325 ClearCheckNewLink(la);
1326 pip = (struct ip *)ptr;
1327 alias_addr = pip->ip_dst;
1329 /* Defense against mangled packets */
1330 if (ntohs(pip->ip_len) > maxpacketsize
1331 || (pip->ip_hl << 2) > maxpacketsize) {
1332 iresult = PKT_ALIAS_IGNORED;
1336 iresult = PKT_ALIAS_IGNORED;
1337 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1338 switch (pip->ip_p) {
1340 iresult = IcmpAliasIn(la, pip);
1343 iresult = UdpAliasIn(la, pip);
1346 iresult = TcpAliasIn(la, pip);
1350 iresult = SctpAlias(la, pip, SN_TO_LOCAL);
1355 struct alias_data ad = {
1365 /* Walk out chain. */
1366 error = find_handler(IN, IP, la, pip, &ad);
1368 iresult = PKT_ALIAS_OK;
1370 iresult = ProtoAliasIn(la, pip->ip_src,
1371 &pip->ip_dst, pip->ip_p, &pip->ip_sum);
1375 iresult = ProtoAliasIn(la, pip->ip_src, &pip->ip_dst,
1376 pip->ip_p, &pip->ip_sum);
1380 if (ntohs(pip->ip_off) & IP_MF) {
1381 struct alias_link *lnk;
1383 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1385 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1386 SetFragmentAddr(lnk, pip->ip_dst);
1388 iresult = PKT_ALIAS_ERROR;
1392 iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id,
1402 /* Unregistered address ranges */
1404 /* 10.0.0.0 -> 10.255.255.255 */
1405 #define UNREG_ADDR_A_LOWER 0x0a000000
1406 #define UNREG_ADDR_A_UPPER 0x0affffff
1408 /* 172.16.0.0 -> 172.31.255.255 */
1409 #define UNREG_ADDR_B_LOWER 0xac100000
1410 #define UNREG_ADDR_B_UPPER 0xac1fffff
1412 /* 192.168.0.0 -> 192.168.255.255 */
1413 #define UNREG_ADDR_C_LOWER 0xc0a80000
1414 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1417 LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize)
1422 res = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1423 LIBALIAS_UNLOCK(la);
1428 LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create)
1433 res = LibAliasOutLocked(la, ptr, maxpacketsize, create);
1434 LIBALIAS_UNLOCK(la);
1439 LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */
1440 int maxpacketsize, /* How much the packet data may grow (FTP
1441 * and IRC inline changes) */
1442 int create /* Create new entries ? */
1446 struct in_addr addr_save;
1449 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1450 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1451 iresult = LibAliasInLocked(la, ptr, maxpacketsize);
1452 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1456 ClearCheckNewLink(la);
1457 pip = (struct ip *)ptr;
1459 /* Defense against mangled packets */
1460 if (ntohs(pip->ip_len) > maxpacketsize
1461 || (pip->ip_hl << 2) > maxpacketsize) {
1462 iresult = PKT_ALIAS_IGNORED;
1466 addr_save = GetDefaultAliasAddress(la);
1467 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) {
1472 addr = ntohl(pip->ip_src.s_addr);
1473 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1475 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1477 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1481 SetDefaultAliasAddress(la, pip->ip_src);
1483 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1484 SetDefaultAliasAddress(la, pip->ip_src);
1486 iresult = PKT_ALIAS_IGNORED;
1487 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1488 switch (pip->ip_p) {
1490 iresult = IcmpAliasOut(la, pip, create);
1493 iresult = UdpAliasOut(la, pip, maxpacketsize, create);
1496 iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1500 iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
1505 struct alias_data ad = {
1514 /* Walk out chain. */
1515 error = find_handler(OUT, IP, la, pip, &ad);
1517 iresult = PKT_ALIAS_OK;
1519 iresult = ProtoAliasOut(la, &pip->ip_src,
1520 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1524 iresult = ProtoAliasOut(la, &pip->ip_src,
1525 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1529 iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum);
1532 SetDefaultAliasAddress(la, addr_save);
1538 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1539 int maxpacketsize /* for error checking */
1546 struct alias_link *lnk;
1547 int iresult = PKT_ALIAS_IGNORED;
1550 pip = (struct ip *)ptr;
1552 /* Defense against mangled packets */
1553 if (ntohs(pip->ip_len) > maxpacketsize
1554 || (pip->ip_hl << 2) > maxpacketsize)
1557 ud = (struct udphdr *)ip_next(pip);
1558 tc = (struct tcphdr *)ip_next(pip);
1559 ic = (struct icmp *)ip_next(pip);
1562 if (pip->ip_p == IPPROTO_UDP)
1563 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1564 ud->uh_dport, ud->uh_sport,
1566 else if (pip->ip_p == IPPROTO_TCP)
1567 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1568 tc->th_dport, tc->th_sport,
1570 else if (pip->ip_p == IPPROTO_ICMP)
1571 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1575 /* Change it from an aliased packet to an unaliased packet */
1577 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1579 struct in_addr original_address;
1580 u_short original_port;
1582 original_address = GetOriginalAddress(lnk);
1583 original_port = GetOriginalPort(lnk);
1585 /* Adjust TCP/UDP checksum */
1586 accumulate = twowords(&pip->ip_src);
1587 accumulate -= twowords(&original_address);
1589 if (pip->ip_p == IPPROTO_UDP) {
1590 accumulate += ud->uh_sport;
1591 accumulate -= original_port;
1592 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1594 accumulate += tc->th_sport;
1595 accumulate -= original_port;
1596 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1599 /* Adjust IP checksum */
1600 DifferentialChecksum(&pip->ip_sum,
1601 &original_address, &pip->ip_src, 2);
1603 /* Un-alias source address and port number */
1604 pip->ip_src = original_address;
1605 if (pip->ip_p == IPPROTO_UDP)
1606 ud->uh_sport = original_port;
1608 tc->th_sport = original_port;
1610 iresult = PKT_ALIAS_OK;
1612 } else if (pip->ip_p == IPPROTO_ICMP) {
1615 struct in_addr original_address;
1616 u_short original_id;
1618 original_address = GetOriginalAddress(lnk);
1619 original_id = GetOriginalPort(lnk);
1621 /* Adjust ICMP checksum */
1622 accumulate = twowords(&pip->ip_src);
1623 accumulate -= twowords(&original_address);
1624 accumulate += ic->icmp_id;
1625 accumulate -= original_id;
1626 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1628 /* Adjust IP checksum */
1629 DifferentialChecksum(&pip->ip_sum,
1630 &original_address, &pip->ip_src, 2);
1632 /* Un-alias source address and port number */
1633 pip->ip_src = original_address;
1634 ic->icmp_id = original_id;
1636 iresult = PKT_ALIAS_OK;
1640 LIBALIAS_UNLOCK(la);
1648 LibAliasRefreshModules(void)
1650 char buf[256], conf[] = "/etc/libalias.conf";
1654 fd = fopen(conf, "r");
1656 err(1, "fopen(%s)", conf);
1658 LibAliasUnLoadAllModule();
1661 fgets(buf, 256, fd);
1666 for (i = 0; i < len; i++)
1667 if (!isspace(buf[i]))
1671 buf[len - 1] = '\0';
1672 LibAliasLoadModule(buf);
1680 LibAliasLoadModule(char *path)
1684 struct proto_handler *m;
1688 handle = dlopen (path, RTLD_LAZY);
1690 fprintf(stderr, "%s\n", dlerror());
1694 p = dlsym(handle, "alias_mod");
1695 if ((error = dlerror()) != NULL) {
1696 fprintf(stderr, "%s\n", dlerror());
1700 t = malloc(sizeof(struct dll));
1703 strncpy(t->name, p->name, DLL_LEN);
1705 if (attach_dll(t) == EEXIST) {
1707 fprintf(stderr, "dll conflict\n");
1711 m = dlsym(t->handle, "handlers");
1712 if ((error = dlerror()) != NULL) {
1713 fprintf(stderr, "%s\n", error);
1717 LibAliasAttachHandlers(m);
1722 LibAliasUnLoadAllModule(void)
1725 struct proto_handler *p;
1727 /* Unload all modules then reload everything. */
1728 while ((p = first_handler()) != NULL) {
1729 LibAliasDetachHandlers(p);
1731 while ((t = walk_dll_chain()) != NULL) {
1742 * m_megapullup() - this function is a big hack.
1743 * Thankfully, it's only used in ng_nat and ipfw+nat.
1745 * It allocates an mbuf with cluster and copies the specified part of the chain
1746 * into cluster, so that it is all contiguous and can be accessed via a plain
1747 * (char *) pointer. This is required, because libalias doesn't know how to
1748 * handle mbuf chains.
1750 * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1751 * the input packet, on failure NULL. The input packet is always consumed.
1754 m_megapullup(struct mbuf *m, int len)
1758 if (len > m->m_pkthdr.len)
1761 if (m->m_next == NULL && M_WRITABLE(m))
1764 if (len <= MJUMPAGESIZE)
1765 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
1766 else if (len <= MJUM9BYTES)
1767 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1768 else if (len <= MJUM16BYTES)
1769 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
1775 m_move_pkthdr(mcl, m);
1776 m_copydata(m, 0, len, mtod(mcl, caddr_t));
1777 mcl->m_len = mcl->m_pkthdr.len = len;