2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
31 Alias.c provides supervisory control for the functions of the
32 packet aliasing software. It consists of routines to monitor
33 TCP connection state, protocol-specific aliasing routines,
34 fragment handling and the following outside world functional
35 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
36 PacketAliasIn and PacketAliasOut.
38 The other C program files are briefly described. The data
39 structure framework which holds information needed to translate
40 packets is encapsulated in alias_db.c. Data is accessed by
41 function calls, so other segments of the program need not know
42 about the underlying data structures. Alias_ftp.c contains
43 special code for modifying the ftp PORT command used to establish
44 data connections, while alias_irc.c does the same for IRC
45 DCC. Alias_util.c contains a few utility routines.
47 Version 1.0 August, 1996 (cjm)
49 Version 1.1 August 20, 1996 (cjm)
50 PPP host accepts incoming connections for ports 0 to 1023.
51 (Gary Roberts pointed out the need to handle incoming
54 Version 1.2 September 7, 1996 (cjm)
55 Fragment handling error in alias_db.c corrected.
56 (Tom Torrance helped fix this problem.)
58 Version 1.4 September 16, 1996 (cjm)
59 - A more generalized method for handling incoming
60 connections, without the 0-1023 restriction, is
61 implemented in alias_db.c
62 - Improved ICMP support in alias.c. Traceroute
63 packet streams can now be correctly aliased.
64 - TCP connection closing logic simplified in
65 alias.c and now allows for additional 1 minute
66 "grace period" after FIN or RST is observed.
68 Version 1.5 September 17, 1996 (cjm)
69 Corrected error in handling incoming UDP packets with 0 checksum.
70 (Tom Torrance helped fix this problem.)
72 Version 1.6 September 18, 1996 (cjm)
73 Simplified ICMP aliasing scheme. Should now support
74 traceroute from Win95 as well as FreeBSD.
76 Version 1.7 January 9, 1997 (cjm)
77 - Out-of-order fragment handling.
78 - IP checksum error fixed for ftp transfers
80 - Integer return codes added to all
81 aliasing/de-aliasing functions.
82 - Some obsolete comments cleaned up.
83 - Differential checksum computations for
84 IP header (TCP, UDP and ICMP were already
87 Version 2.1 May 1997 (cjm)
88 - Added support for outgoing ICMP error
90 - Added two functions PacketAliasIn2()
91 and PacketAliasOut2() for dynamic address
92 control (e.g. round-robin allocation of
95 Version 2.2 July 1997 (cjm)
96 - Rationalized API function names to begin
98 - Eliminated PacketAliasIn2() and
99 PacketAliasOut2() as poorly conceived.
101 Version 2.3 Dec 1998 (dillon)
102 - Major bounds checking additions, see FreeBSD/CVS
104 Version 3.1 May, 2000 (salander)
105 - Added hooks to handle PPTP.
107 Version 3.2 July, 2000 (salander and satoh)
108 - Added PacketUnaliasOut routine.
109 - Added hooks to handle RTSP/RTP.
111 See HISTORY file for additional revisions.
115 #include <sys/param.h>
116 #include <sys/systm.h>
117 #include <sys/mbuf.h>
118 #include <sys/sysctl.h>
120 #include <sys/types.h>
129 #include <netinet/in_systm.h>
130 #include <netinet/in.h>
131 #include <netinet/ip.h>
132 #include <netinet/ip_icmp.h>
133 #include <netinet/tcp.h>
134 #include <netinet/udp.h>
137 #include <netinet/libalias/alias.h>
138 #include <netinet/libalias/alias_local.h>
139 #include <netinet/libalias/alias_mod.h>
143 #include "alias_local.h"
144 #include "alias_mod.h"
148 * Define libalias SYSCTL Node
152 SYSCTL_DECL(_net_inet);
153 SYSCTL_DECL(_net_inet_ip);
154 SYSCTL_NODE(_net_inet_ip, OID_AUTO, alias, CTLFLAG_RW, NULL, "Libalias sysctl API");
163 #if BYTE_ORDER == LITTLE_ENDIAN
164 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
165 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
167 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
168 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
173 /* TCP Handling Routines
175 TcpMonitorIn() -- These routines monitor TCP connections, and
176 TcpMonitorOut() delete a link when a connection is closed.
178 These routines look for SYN, FIN and RST flags to determine when TCP
179 connections open and close. When a TCP connection closes, the data
180 structure containing packet aliasing information is deleted after
184 /* Local prototypes */
185 static void TcpMonitorIn(u_char, struct alias_link *);
187 static void TcpMonitorOut(u_char, struct alias_link *);
191 TcpMonitorIn(u_char th_flags, struct alias_link *lnk)
194 switch (GetStateIn(lnk)) {
195 case ALIAS_TCP_STATE_NOT_CONNECTED:
196 if (th_flags & TH_RST)
197 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
198 else if (th_flags & TH_SYN)
199 SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED);
201 case ALIAS_TCP_STATE_CONNECTED:
202 if (th_flags & (TH_FIN | TH_RST))
203 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
209 TcpMonitorOut(u_char th_flags, struct alias_link *lnk)
212 switch (GetStateOut(lnk)) {
213 case ALIAS_TCP_STATE_NOT_CONNECTED:
214 if (th_flags & TH_RST)
215 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
216 else if (th_flags & TH_SYN)
217 SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED);
219 case ALIAS_TCP_STATE_CONNECTED:
220 if (th_flags & (TH_FIN | TH_RST))
221 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
230 /* Protocol Specific Packet Aliasing Routines
232 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
233 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
234 ProtoAliasIn(), ProtoAliasOut()
235 UdpAliasIn(), UdpAliasOut()
236 TcpAliasIn(), TcpAliasOut()
238 These routines handle protocol specific details of packet aliasing.
239 One may observe a certain amount of repetitive arithmetic in these
240 functions, the purpose of which is to compute a revised checksum
241 without actually summing over the entire data packet, which could be
242 unnecessarily time consuming.
244 The purpose of the packet aliasing routines is to replace the source
245 address of the outgoing packet and then correctly put it back for
246 any incoming packets. For TCP and UDP, ports are also re-mapped.
248 For ICMP echo/timestamp requests and replies, the following scheme
249 is used: the ID number is replaced by an alias for the outgoing
252 ICMP error messages are handled by looking at the IP fragment
253 in the data section of the message.
255 For TCP and UDP protocols, a port number is chosen for an outgoing
256 packet, and then incoming packets are identified by IP address and
257 port numbers. For TCP packets, there is additional logic in the event
258 that sequence and ACK numbers have been altered (as in the case for
259 FTP data port commands).
261 The port numbers used by the packet aliasing module are not true
262 ports in the Unix sense. No sockets are actually bound to ports.
263 They are more correctly thought of as placeholders.
265 All packets go through the aliasing mechanism, whether they come from
266 the gateway machine or other machines on a local area network.
270 /* Local prototypes */
271 static int IcmpAliasIn1(struct libalias *, struct ip *);
272 static int IcmpAliasIn2(struct libalias *, struct ip *);
273 static int IcmpAliasIn(struct libalias *, struct ip *);
275 static int IcmpAliasOut1(struct libalias *, struct ip *, int create);
276 static int IcmpAliasOut2(struct libalias *, struct ip *);
277 static int IcmpAliasOut(struct libalias *, struct ip *, int create);
279 static int ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
280 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum);
281 static int ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
282 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum,
285 static int UdpAliasIn(struct libalias *, struct ip *);
286 static int UdpAliasOut(struct libalias *, struct ip *, int, int create);
288 static int TcpAliasIn(struct libalias *, struct ip *);
289 static int TcpAliasOut(struct libalias *, struct ip *, int, int create);
293 IcmpAliasIn1(struct libalias *la, struct ip *pip)
296 LIBALIAS_LOCK_ASSERT(la);
298 De-alias incoming echo and timestamp replies.
299 Alias incoming echo and timestamp requests.
301 struct alias_link *lnk;
304 ic = (struct icmp *)ip_next(pip);
306 /* Get source address from ICMP data field and restore original data */
307 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
312 original_id = GetOriginalPort(lnk);
314 /* Adjust ICMP checksum */
315 accumulate = ic->icmp_id;
316 accumulate -= original_id;
317 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
319 /* Put original sequence number back in */
320 ic->icmp_id = original_id;
322 /* Put original address back into IP header */
324 struct in_addr original_address;
326 original_address = GetOriginalAddress(lnk);
327 DifferentialChecksum(&pip->ip_sum,
328 &original_address, &pip->ip_dst, 2);
329 pip->ip_dst = original_address;
332 return (PKT_ALIAS_OK);
334 return (PKT_ALIAS_IGNORED);
338 IcmpAliasIn2(struct libalias *la, struct ip *pip)
341 LIBALIAS_LOCK_ASSERT(la);
343 Alias incoming ICMP error messages containing
344 IP header and first 64 bits of datagram.
347 struct icmp *ic, *ic2;
350 struct alias_link *lnk;
352 ic = (struct icmp *)ip_next(pip);
355 ud = (struct udphdr *)ip_next(ip);
356 tc = (struct tcphdr *)ip_next(ip);
357 ic2 = (struct icmp *)ip_next(ip);
359 if (ip->ip_p == IPPROTO_UDP)
360 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
361 ud->uh_dport, ud->uh_sport,
363 else if (ip->ip_p == IPPROTO_TCP)
364 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
365 tc->th_dport, tc->th_sport,
367 else if (ip->ip_p == IPPROTO_ICMP) {
368 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
369 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
376 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
377 int accumulate, accumulate2;
378 struct in_addr original_address;
379 u_short original_port;
381 original_address = GetOriginalAddress(lnk);
382 original_port = GetOriginalPort(lnk);
384 /* Adjust ICMP checksum */
385 accumulate = twowords(&ip->ip_src);
386 accumulate -= twowords(&original_address);
387 accumulate += ud->uh_sport;
388 accumulate -= original_port;
389 accumulate2 = accumulate;
390 accumulate2 += ip->ip_sum;
391 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
392 accumulate2 -= ip->ip_sum;
393 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
395 /* Un-alias address in IP header */
396 DifferentialChecksum(&pip->ip_sum,
397 &original_address, &pip->ip_dst, 2);
398 pip->ip_dst = original_address;
400 /* Un-alias address and port number of original IP packet
401 fragment contained in ICMP data section */
402 ip->ip_src = original_address;
403 ud->uh_sport = original_port;
404 } else if (ip->ip_p == IPPROTO_ICMP) {
405 int accumulate, accumulate2;
406 struct in_addr original_address;
409 original_address = GetOriginalAddress(lnk);
410 original_id = GetOriginalPort(lnk);
412 /* Adjust ICMP checksum */
413 accumulate = twowords(&ip->ip_src);
414 accumulate -= twowords(&original_address);
415 accumulate += ic2->icmp_id;
416 accumulate -= original_id;
417 accumulate2 = accumulate;
418 accumulate2 += ip->ip_sum;
419 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
420 accumulate2 -= ip->ip_sum;
421 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
423 /* Un-alias address in IP header */
424 DifferentialChecksum(&pip->ip_sum,
425 &original_address, &pip->ip_dst, 2);
426 pip->ip_dst = original_address;
428 /* Un-alias address of original IP packet and sequence number of
429 embedded ICMP datagram */
430 ip->ip_src = original_address;
431 ic2->icmp_id = original_id;
433 return (PKT_ALIAS_OK);
435 return (PKT_ALIAS_IGNORED);
440 IcmpAliasIn(struct libalias *la, struct ip *pip)
445 LIBALIAS_LOCK_ASSERT(la);
446 /* Return if proxy-only mode is enabled */
447 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
448 return (PKT_ALIAS_OK);
450 ic = (struct icmp *)ip_next(pip);
452 iresult = PKT_ALIAS_IGNORED;
453 switch (ic->icmp_type) {
455 case ICMP_TSTAMPREPLY:
456 if (ic->icmp_code == 0) {
457 iresult = IcmpAliasIn1(la, pip);
461 case ICMP_SOURCEQUENCH:
464 iresult = IcmpAliasIn2(la, pip);
468 iresult = IcmpAliasIn1(la, pip);
476 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
479 Alias outgoing echo and timestamp requests.
480 De-alias outgoing echo and timestamp replies.
482 struct alias_link *lnk;
485 LIBALIAS_LOCK_ASSERT(la);
486 ic = (struct icmp *)ip_next(pip);
488 /* Save overwritten data for when echo packet returns */
489 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create);
494 alias_id = GetAliasPort(lnk);
496 /* Since data field is being modified, adjust ICMP checksum */
497 accumulate = ic->icmp_id;
498 accumulate -= alias_id;
499 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
501 /* Alias sequence number */
502 ic->icmp_id = alias_id;
504 /* Change source address */
506 struct in_addr alias_address;
508 alias_address = GetAliasAddress(lnk);
509 DifferentialChecksum(&pip->ip_sum,
510 &alias_address, &pip->ip_src, 2);
511 pip->ip_src = alias_address;
514 return (PKT_ALIAS_OK);
516 return (PKT_ALIAS_IGNORED);
521 IcmpAliasOut2(struct libalias *la, struct ip *pip)
524 Alias outgoing ICMP error messages containing
525 IP header and first 64 bits of datagram.
528 struct icmp *ic, *ic2;
531 struct alias_link *lnk;
533 LIBALIAS_LOCK_ASSERT(la);
534 ic = (struct icmp *)ip_next(pip);
537 ud = (struct udphdr *)ip_next(ip);
538 tc = (struct tcphdr *)ip_next(ip);
539 ic2 = (struct icmp *)ip_next(ip);
541 if (ip->ip_p == IPPROTO_UDP)
542 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
543 ud->uh_dport, ud->uh_sport,
545 else if (ip->ip_p == IPPROTO_TCP)
546 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
547 tc->th_dport, tc->th_sport,
549 else if (ip->ip_p == IPPROTO_ICMP) {
550 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
551 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
558 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
560 struct in_addr alias_address;
563 alias_address = GetAliasAddress(lnk);
564 alias_port = GetAliasPort(lnk);
566 /* Adjust ICMP checksum */
567 accumulate = twowords(&ip->ip_dst);
568 accumulate -= twowords(&alias_address);
569 accumulate += ud->uh_dport;
570 accumulate -= alias_port;
571 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
574 * Alias address in IP header if it comes from the host
575 * the original TCP/UDP packet was destined for.
577 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
578 DifferentialChecksum(&pip->ip_sum,
579 &alias_address, &pip->ip_src, 2);
580 pip->ip_src = alias_address;
582 /* Alias address and port number of original IP packet
583 fragment contained in ICMP data section */
584 ip->ip_dst = alias_address;
585 ud->uh_dport = alias_port;
586 } else if (ip->ip_p == IPPROTO_ICMP) {
588 struct in_addr alias_address;
591 alias_address = GetAliasAddress(lnk);
592 alias_id = GetAliasPort(lnk);
594 /* Adjust ICMP checksum */
595 accumulate = twowords(&ip->ip_dst);
596 accumulate -= twowords(&alias_address);
597 accumulate += ic2->icmp_id;
598 accumulate -= alias_id;
599 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
602 * Alias address in IP header if it comes from the host
603 * the original ICMP message was destined for.
605 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
606 DifferentialChecksum(&pip->ip_sum,
607 &alias_address, &pip->ip_src, 2);
608 pip->ip_src = alias_address;
610 /* Alias address of original IP packet and sequence number of
611 embedded ICMP datagram */
612 ip->ip_dst = alias_address;
613 ic2->icmp_id = alias_id;
615 return (PKT_ALIAS_OK);
617 return (PKT_ALIAS_IGNORED);
622 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
627 LIBALIAS_LOCK_ASSERT(la);
630 /* Return if proxy-only mode is enabled */
631 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
632 return (PKT_ALIAS_OK);
634 ic = (struct icmp *)ip_next(pip);
636 iresult = PKT_ALIAS_IGNORED;
637 switch (ic->icmp_type) {
640 if (ic->icmp_code == 0) {
641 iresult = IcmpAliasOut1(la, pip, create);
645 case ICMP_SOURCEQUENCH:
648 iresult = IcmpAliasOut2(la, pip);
651 case ICMP_TSTAMPREPLY:
652 iresult = IcmpAliasOut1(la, pip, create);
658 ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
659 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum)
662 Handle incoming IP packets. The
663 only thing which is done in this case is to alias
664 the dest IP address of the packet to our inside
667 struct alias_link *lnk;
669 LIBALIAS_LOCK_ASSERT(la);
670 /* Return if proxy-only mode is enabled */
671 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
672 return (PKT_ALIAS_OK);
674 lnk = FindProtoIn(la, ip_src, *ip_dst, ip_p);
676 struct in_addr original_address;
678 original_address = GetOriginalAddress(lnk);
680 /* Restore original IP address */
681 DifferentialChecksum(ip_sum,
682 &original_address, ip_dst, 2);
683 *ip_dst = original_address;
685 return (PKT_ALIAS_OK);
687 return (PKT_ALIAS_IGNORED);
691 ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
692 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
695 Handle outgoing IP packets. The
696 only thing which is done in this case is to alias
697 the source IP address of the packet.
699 struct alias_link *lnk;
701 LIBALIAS_LOCK_ASSERT(la);
704 /* Return if proxy-only mode is enabled */
705 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
706 return (PKT_ALIAS_OK);
708 lnk = FindProtoOut(la, *ip_src, ip_dst, ip_p);
710 struct in_addr alias_address;
712 alias_address = GetAliasAddress(lnk);
714 /* Change source address */
715 DifferentialChecksum(ip_sum,
716 &alias_address, ip_src, 2);
717 *ip_src = alias_address;
719 return (PKT_ALIAS_OK);
721 return (PKT_ALIAS_IGNORED);
726 UdpAliasIn(struct libalias *la, struct ip *pip)
729 struct alias_link *lnk;
731 LIBALIAS_LOCK_ASSERT(la);
733 ud = (struct udphdr *)ip_next(pip);
735 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
736 ud->uh_sport, ud->uh_dport,
737 IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
739 struct in_addr alias_address;
740 struct in_addr original_address;
741 struct in_addr proxy_address;
746 struct alias_data ad = {
748 .oaddr = &original_address,
749 .aaddr = &alias_address,
750 .aport = &alias_port,
751 .sport = &ud->uh_sport,
752 .dport = &ud->uh_dport,
756 alias_address = GetAliasAddress(lnk);
757 original_address = GetOriginalAddress(lnk);
758 proxy_address = GetProxyAddress(lnk);
759 alias_port = ud->uh_dport;
760 ud->uh_dport = GetOriginalPort(lnk);
761 proxy_port = GetProxyPort(lnk);
763 /* Walk out chain. */
764 error = find_handler(IN, UDP, la, pip, &ad);
765 /* If we cannot figure out the packet, ignore it. */
767 return (PKT_ALIAS_IGNORED);
769 /* If UDP checksum is not zero, then adjust since destination port */
770 /* is being unaliased and destination address is being altered. */
771 if (ud->uh_sum != 0) {
772 accumulate = alias_port;
773 accumulate -= ud->uh_dport;
774 accumulate += twowords(&alias_address);
775 accumulate -= twowords(&original_address);
777 /* If this is a proxy packet, modify checksum because of source change.*/
778 if (proxy_port != 0) {
779 accumulate += ud->uh_sport;
780 accumulate -= proxy_port;
783 if (proxy_address.s_addr != 0) {
784 accumulate += twowords(&pip->ip_src);
785 accumulate -= twowords(&proxy_address);
788 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
790 /* XXX: Could the two if's below be concatenated to one ? */
791 /* Restore source port and/or address in case of proxying*/
794 ud->uh_sport = proxy_port;
796 if (proxy_address.s_addr != 0) {
797 DifferentialChecksum(&pip->ip_sum,
798 &proxy_address, &pip->ip_src, 2);
799 pip->ip_src = proxy_address;
802 /* Restore original IP address */
803 DifferentialChecksum(&pip->ip_sum,
804 &original_address, &pip->ip_dst, 2);
805 pip->ip_dst = original_address;
807 return (PKT_ALIAS_OK);
809 return (PKT_ALIAS_IGNORED);
813 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
816 struct alias_link *lnk;
817 struct in_addr dest_address;
818 struct in_addr proxy_server_address;
820 u_short proxy_server_port;
824 LIBALIAS_LOCK_ASSERT(la);
826 /* Return if proxy-only mode is enabled and not proxyrule found.*/
827 ud = (struct udphdr *)ip_next(pip);
828 proxy_type = ProxyCheck(la, &proxy_server_address,
829 &proxy_server_port, pip->ip_src, pip->ip_dst,
830 ud->uh_dport, pip->ip_p);
831 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
832 return (PKT_ALIAS_OK);
834 /* If this is a transparent proxy, save original destination,
835 * then alter the destination and adjust checksums */
836 dest_port = ud->uh_dport;
837 dest_address = pip->ip_dst;
839 if (proxy_type != 0) {
842 accumulate = twowords(&pip->ip_dst);
843 accumulate -= twowords(&proxy_server_address);
845 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
847 if (ud->uh_sum != 0) {
848 accumulate = twowords(&pip->ip_dst);
849 accumulate -= twowords(&proxy_server_address);
850 accumulate += ud->uh_dport;
851 accumulate -= proxy_server_port;
852 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
854 pip->ip_dst = proxy_server_address;
855 ud->uh_dport = proxy_server_port;
857 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
858 ud->uh_sport, ud->uh_dport,
859 IPPROTO_UDP, create);
862 struct in_addr alias_address;
863 struct alias_data ad = {
866 .aaddr = &alias_address,
867 .aport = &alias_port,
868 .sport = &ud->uh_sport,
869 .dport = &ud->uh_dport,
873 /* Save original destination address, if this is a proxy packet.
874 * Also modify packet to include destination encoding. This may
875 * change the size of IP header. */
876 if (proxy_type != 0) {
877 SetProxyPort(lnk, dest_port);
878 SetProxyAddress(lnk, dest_address);
879 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
880 ud = (struct udphdr *)ip_next(pip);
883 alias_address = GetAliasAddress(lnk);
884 alias_port = GetAliasPort(lnk);
886 /* Walk out chain. */
887 error = find_handler(OUT, UDP, la, pip, &ad);
889 /* If UDP checksum is not zero, adjust since source port is */
890 /* being aliased and source address is being altered */
891 if (ud->uh_sum != 0) {
894 accumulate = ud->uh_sport;
895 accumulate -= alias_port;
896 accumulate += twowords(&pip->ip_src);
897 accumulate -= twowords(&alias_address);
898 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
900 /* Put alias port in UDP header */
901 ud->uh_sport = alias_port;
903 /* Change source address */
904 DifferentialChecksum(&pip->ip_sum,
905 &alias_address, &pip->ip_src, 2);
906 pip->ip_src = alias_address;
908 return (PKT_ALIAS_OK);
910 return (PKT_ALIAS_IGNORED);
916 TcpAliasIn(struct libalias *la, struct ip *pip)
919 struct alias_link *lnk;
921 LIBALIAS_LOCK_ASSERT(la);
922 tc = (struct tcphdr *)ip_next(pip);
924 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
925 tc->th_sport, tc->th_dport,
927 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
929 struct in_addr alias_address;
930 struct in_addr original_address;
931 struct in_addr proxy_address;
934 int accumulate, error;
937 * The init of MANY vars is a bit below, but aliashandlepptpin
938 * seems to need the destination port that came within the
939 * packet and not the original one looks below [*].
942 struct alias_data ad = {
947 .sport = &tc->th_sport,
948 .dport = &tc->th_dport,
952 /* Walk out chain. */
953 error = find_handler(IN, TCP, la, pip, &ad);
955 alias_address = GetAliasAddress(lnk);
956 original_address = GetOriginalAddress(lnk);
957 proxy_address = GetProxyAddress(lnk);
958 alias_port = tc->th_dport;
959 tc->th_dport = GetOriginalPort(lnk);
960 proxy_port = GetProxyPort(lnk);
963 * Look above, if anyone is going to add find_handler AFTER
964 * this aliashandlepptpin/point, please redo alias_data too.
965 * Uncommenting the piece here below should be enough.
968 struct alias_data ad = {
970 .oaddr = &original_address,
971 .aaddr = &alias_address,
972 .aport = &alias_port,
973 .sport = &ud->uh_sport,
974 .dport = &ud->uh_dport,
978 /* Walk out chain. */
979 error = find_handler(la, pip, &ad);
981 printf("Protocol handler not found\n");
984 /* Adjust TCP checksum since destination port is being unaliased */
985 /* and destination port is being altered. */
986 accumulate = alias_port;
987 accumulate -= tc->th_dport;
988 accumulate += twowords(&alias_address);
989 accumulate -= twowords(&original_address);
991 /* If this is a proxy, then modify the TCP source port and
992 checksum accumulation */
993 if (proxy_port != 0) {
994 accumulate += tc->th_sport;
995 tc->th_sport = proxy_port;
996 accumulate -= tc->th_sport;
997 accumulate += twowords(&pip->ip_src);
998 accumulate -= twowords(&proxy_address);
1000 /* See if ACK number needs to be modified */
1001 if (GetAckModified(lnk) == 1) {
1004 tc = (struct tcphdr *)ip_next(pip);
1005 delta = GetDeltaAckIn(tc->th_ack, lnk);
1007 accumulate += twowords(&tc->th_ack);
1008 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
1009 accumulate -= twowords(&tc->th_ack);
1012 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1014 /* Restore original IP address */
1015 accumulate = twowords(&pip->ip_dst);
1016 pip->ip_dst = original_address;
1017 accumulate -= twowords(&pip->ip_dst);
1019 /* If this is a transparent proxy packet, then modify the source
1021 if (proxy_address.s_addr != 0) {
1022 accumulate += twowords(&pip->ip_src);
1023 pip->ip_src = proxy_address;
1024 accumulate -= twowords(&pip->ip_src);
1026 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1028 /* Monitor TCP connection state */
1029 tc = (struct tcphdr *)ip_next(pip);
1030 TcpMonitorIn(tc->th_flags, lnk);
1032 return (PKT_ALIAS_OK);
1034 return (PKT_ALIAS_IGNORED);
1038 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
1040 int proxy_type, error;
1042 u_short proxy_server_port;
1043 struct in_addr dest_address;
1044 struct in_addr proxy_server_address;
1046 struct alias_link *lnk;
1048 LIBALIAS_LOCK_ASSERT(la);
1049 tc = (struct tcphdr *)ip_next(pip);
1052 proxy_type = ProxyCheck(la, &proxy_server_address,
1053 &proxy_server_port, pip->ip_src, pip->ip_dst,
1054 tc->th_dport, pip->ip_p);
1058 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1059 return (PKT_ALIAS_OK);
1061 /* If this is a transparent proxy, save original destination,
1062 then alter the destination and adjust checksums */
1063 dest_port = tc->th_dport;
1064 dest_address = pip->ip_dst;
1065 if (proxy_type != 0) {
1068 accumulate = tc->th_dport;
1069 tc->th_dport = proxy_server_port;
1070 accumulate -= tc->th_dport;
1071 accumulate += twowords(&pip->ip_dst);
1072 accumulate -= twowords(&proxy_server_address);
1073 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1075 accumulate = twowords(&pip->ip_dst);
1076 pip->ip_dst = proxy_server_address;
1077 accumulate -= twowords(&pip->ip_dst);
1078 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1080 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
1081 tc->th_sport, tc->th_dport,
1082 IPPROTO_TCP, create);
1084 return (PKT_ALIAS_IGNORED);
1087 struct in_addr alias_address;
1089 struct alias_data ad = {
1092 .aaddr = &alias_address,
1093 .aport = &alias_port,
1094 .sport = &tc->th_sport,
1095 .dport = &tc->th_dport,
1096 .maxpktsize = maxpacketsize
1099 /* Save original destination address, if this is a proxy packet.
1100 Also modify packet to include destination encoding. This may
1101 change the size of IP header. */
1102 if (proxy_type != 0) {
1103 SetProxyPort(lnk, dest_port);
1104 SetProxyAddress(lnk, dest_address);
1105 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
1106 tc = (struct tcphdr *)ip_next(pip);
1108 /* Get alias address and port */
1109 alias_port = GetAliasPort(lnk);
1110 alias_address = GetAliasAddress(lnk);
1112 /* Monitor TCP connection state */
1113 tc = (struct tcphdr *)ip_next(pip);
1114 TcpMonitorOut(tc->th_flags, lnk);
1116 /* Walk out chain. */
1117 error = find_handler(OUT, TCP, la, pip, &ad);
1119 /* Adjust TCP checksum since source port is being aliased */
1120 /* and source address is being altered */
1121 accumulate = tc->th_sport;
1122 tc->th_sport = alias_port;
1123 accumulate -= tc->th_sport;
1124 accumulate += twowords(&pip->ip_src);
1125 accumulate -= twowords(&alias_address);
1127 /* Modify sequence number if necessary */
1128 if (GetAckModified(lnk) == 1) {
1131 tc = (struct tcphdr *)ip_next(pip);
1132 delta = GetDeltaSeqOut(tc->th_seq, lnk);
1134 accumulate += twowords(&tc->th_seq);
1135 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1136 accumulate -= twowords(&tc->th_seq);
1139 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1141 /* Change source address */
1142 accumulate = twowords(&pip->ip_src);
1143 pip->ip_src = alias_address;
1144 accumulate -= twowords(&pip->ip_src);
1145 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1147 return (PKT_ALIAS_OK);
1149 return (PKT_ALIAS_IGNORED);
1155 /* Fragment Handling
1160 The packet aliasing module has a limited ability for handling IP
1161 fragments. If the ICMP, TCP or UDP header is in the first fragment
1162 received, then the ID number of the IP packet is saved, and other
1163 fragments are identified according to their ID number and IP address
1164 they were sent from. Pointers to unresolved fragments can also be
1165 saved and recalled when a header fragment is seen.
1168 /* Local prototypes */
1169 static int FragmentIn(struct libalias *la, struct in_addr ip_src,
1170 struct in_addr *ip_dst, u_short ip_id, u_short *ip_sum);
1171 static int FragmentOut(struct libalias *, struct in_addr *ip_src,
1175 FragmentIn(struct libalias *la, struct in_addr ip_src, struct in_addr *ip_dst,
1176 u_short ip_id, u_short *ip_sum)
1178 struct alias_link *lnk;
1180 LIBALIAS_LOCK_ASSERT(la);
1181 lnk = FindFragmentIn2(la, ip_src, *ip_dst, ip_id);
1183 struct in_addr original_address;
1185 GetFragmentAddr(lnk, &original_address);
1186 DifferentialChecksum(ip_sum,
1187 &original_address, ip_dst, 2);
1188 *ip_dst = original_address;
1190 return (PKT_ALIAS_OK);
1192 return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1196 FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum)
1198 struct in_addr alias_address;
1200 LIBALIAS_LOCK_ASSERT(la);
1201 alias_address = FindAliasAddress(la, *ip_src);
1202 DifferentialChecksum(ip_sum,
1203 &alias_address, ip_src, 2);
1204 *ip_src = alias_address;
1206 return (PKT_ALIAS_OK);
1214 /* Outside World Access
1216 PacketAliasSaveFragment()
1217 PacketAliasGetFragment()
1218 PacketAliasFragmentIn()
1223 (prototypes in alias.h)
1227 LibAliasSaveFragment(struct libalias *la, char *ptr)
1230 struct alias_link *lnk;
1234 pip = (struct ip *)ptr;
1235 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1236 iresult = PKT_ALIAS_ERROR;
1238 SetFragmentPtr(lnk, ptr);
1239 iresult = PKT_ALIAS_OK;
1241 LIBALIAS_UNLOCK(la);
1246 LibAliasGetFragment(struct libalias *la, char *ptr)
1248 struct alias_link *lnk;
1253 pip = (struct ip *)ptr;
1254 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1256 GetFragmentPtr(lnk, &fptr);
1257 SetFragmentPtr(lnk, NULL);
1258 SetExpire(lnk, 0); /* Deletes link */
1262 LIBALIAS_UNLOCK(la);
1267 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
1270 char *ptr_fragment /* Points to fragment which must be
1279 pip = (struct ip *)ptr;
1280 fpip = (struct ip *)ptr_fragment;
1282 DifferentialChecksum(&fpip->ip_sum,
1283 &pip->ip_dst, &fpip->ip_dst, 2);
1284 fpip->ip_dst = pip->ip_dst;
1285 LIBALIAS_UNLOCK(la);
1288 /* Local prototypes */
1290 LibAliasOutLocked(struct libalias *la, char *ptr,
1291 int maxpacketsize, int create);
1293 LibAliasInLocked(struct libalias *la, char *ptr,
1297 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1302 res = LibAliasInLocked(la, ptr, maxpacketsize);
1303 LIBALIAS_UNLOCK(la);
1308 LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize)
1310 struct in_addr alias_addr;
1314 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1315 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1316 iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1317 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1321 ClearCheckNewLink(la);
1322 pip = (struct ip *)ptr;
1323 alias_addr = pip->ip_dst;
1325 /* Defense against mangled packets */
1326 if (ntohs(pip->ip_len) > maxpacketsize
1327 || (pip->ip_hl << 2) > maxpacketsize) {
1328 iresult = PKT_ALIAS_IGNORED;
1332 iresult = PKT_ALIAS_IGNORED;
1333 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1334 switch (pip->ip_p) {
1336 iresult = IcmpAliasIn(la, pip);
1339 iresult = UdpAliasIn(la, pip);
1342 iresult = TcpAliasIn(la, pip);
1346 iresult = SctpAlias(la, pip, SN_TO_LOCAL);
1351 struct alias_data ad = {
1361 /* Walk out chain. */
1362 error = find_handler(IN, IP, la, pip, &ad);
1364 iresult = PKT_ALIAS_OK;
1366 iresult = ProtoAliasIn(la, pip->ip_src,
1367 &pip->ip_dst, pip->ip_p, &pip->ip_sum);
1371 iresult = ProtoAliasIn(la, pip->ip_src, &pip->ip_dst,
1372 pip->ip_p, &pip->ip_sum);
1376 if (ntohs(pip->ip_off) & IP_MF) {
1377 struct alias_link *lnk;
1379 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1381 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1382 SetFragmentAddr(lnk, pip->ip_dst);
1384 iresult = PKT_ALIAS_ERROR;
1388 iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id,
1398 /* Unregistered address ranges */
1400 /* 10.0.0.0 -> 10.255.255.255 */
1401 #define UNREG_ADDR_A_LOWER 0x0a000000
1402 #define UNREG_ADDR_A_UPPER 0x0affffff
1404 /* 172.16.0.0 -> 172.31.255.255 */
1405 #define UNREG_ADDR_B_LOWER 0xac100000
1406 #define UNREG_ADDR_B_UPPER 0xac1fffff
1408 /* 192.168.0.0 -> 192.168.255.255 */
1409 #define UNREG_ADDR_C_LOWER 0xc0a80000
1410 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1413 LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize)
1418 res = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1419 LIBALIAS_UNLOCK(la);
1424 LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create)
1429 res = LibAliasOutLocked(la, ptr, maxpacketsize, create);
1430 LIBALIAS_UNLOCK(la);
1435 LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */
1436 int maxpacketsize, /* How much the packet data may grow (FTP
1437 * and IRC inline changes) */
1438 int create /* Create new entries ? */
1442 struct in_addr addr_save;
1445 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1446 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1447 iresult = LibAliasInLocked(la, ptr, maxpacketsize);
1448 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1452 ClearCheckNewLink(la);
1453 pip = (struct ip *)ptr;
1455 /* Defense against mangled packets */
1456 if (ntohs(pip->ip_len) > maxpacketsize
1457 || (pip->ip_hl << 2) > maxpacketsize) {
1458 iresult = PKT_ALIAS_IGNORED;
1462 addr_save = GetDefaultAliasAddress(la);
1463 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) {
1468 addr = ntohl(pip->ip_src.s_addr);
1469 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1471 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1473 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1477 SetDefaultAliasAddress(la, pip->ip_src);
1479 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1480 SetDefaultAliasAddress(la, pip->ip_src);
1482 iresult = PKT_ALIAS_IGNORED;
1483 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1484 switch (pip->ip_p) {
1486 iresult = IcmpAliasOut(la, pip, create);
1489 iresult = UdpAliasOut(la, pip, maxpacketsize, create);
1492 iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1496 iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
1501 struct alias_data ad = {
1510 /* Walk out chain. */
1511 error = find_handler(OUT, IP, la, pip, &ad);
1513 iresult = PKT_ALIAS_OK;
1515 iresult = ProtoAliasOut(la, &pip->ip_src,
1516 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1520 iresult = ProtoAliasOut(la, &pip->ip_src,
1521 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1525 iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum);
1528 SetDefaultAliasAddress(la, addr_save);
1534 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1535 int maxpacketsize /* for error checking */
1542 struct alias_link *lnk;
1543 int iresult = PKT_ALIAS_IGNORED;
1546 pip = (struct ip *)ptr;
1548 /* Defense against mangled packets */
1549 if (ntohs(pip->ip_len) > maxpacketsize
1550 || (pip->ip_hl << 2) > maxpacketsize)
1553 ud = (struct udphdr *)ip_next(pip);
1554 tc = (struct tcphdr *)ip_next(pip);
1555 ic = (struct icmp *)ip_next(pip);
1558 if (pip->ip_p == IPPROTO_UDP)
1559 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1560 ud->uh_dport, ud->uh_sport,
1562 else if (pip->ip_p == IPPROTO_TCP)
1563 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1564 tc->th_dport, tc->th_sport,
1566 else if (pip->ip_p == IPPROTO_ICMP)
1567 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1571 /* Change it from an aliased packet to an unaliased packet */
1573 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1575 struct in_addr original_address;
1576 u_short original_port;
1578 original_address = GetOriginalAddress(lnk);
1579 original_port = GetOriginalPort(lnk);
1581 /* Adjust TCP/UDP checksum */
1582 accumulate = twowords(&pip->ip_src);
1583 accumulate -= twowords(&original_address);
1585 if (pip->ip_p == IPPROTO_UDP) {
1586 accumulate += ud->uh_sport;
1587 accumulate -= original_port;
1588 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1590 accumulate += tc->th_sport;
1591 accumulate -= original_port;
1592 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1595 /* Adjust IP checksum */
1596 DifferentialChecksum(&pip->ip_sum,
1597 &original_address, &pip->ip_src, 2);
1599 /* Un-alias source address and port number */
1600 pip->ip_src = original_address;
1601 if (pip->ip_p == IPPROTO_UDP)
1602 ud->uh_sport = original_port;
1604 tc->th_sport = original_port;
1606 iresult = PKT_ALIAS_OK;
1608 } else if (pip->ip_p == IPPROTO_ICMP) {
1611 struct in_addr original_address;
1612 u_short original_id;
1614 original_address = GetOriginalAddress(lnk);
1615 original_id = GetOriginalPort(lnk);
1617 /* Adjust ICMP checksum */
1618 accumulate = twowords(&pip->ip_src);
1619 accumulate -= twowords(&original_address);
1620 accumulate += ic->icmp_id;
1621 accumulate -= original_id;
1622 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1624 /* Adjust IP checksum */
1625 DifferentialChecksum(&pip->ip_sum,
1626 &original_address, &pip->ip_src, 2);
1628 /* Un-alias source address and port number */
1629 pip->ip_src = original_address;
1630 ic->icmp_id = original_id;
1632 iresult = PKT_ALIAS_OK;
1636 LIBALIAS_UNLOCK(la);
1644 LibAliasRefreshModules(void)
1646 char buf[256], conf[] = "/etc/libalias.conf";
1650 fd = fopen(conf, "r");
1652 err(1, "fopen(%s)", conf);
1654 LibAliasUnLoadAllModule();
1657 fgets(buf, 256, fd);
1662 for (i = 0; i < len; i++)
1663 if (!isspace(buf[i]))
1667 buf[len - 1] = '\0';
1668 LibAliasLoadModule(buf);
1676 LibAliasLoadModule(char *path)
1680 struct proto_handler *m;
1684 handle = dlopen (path, RTLD_LAZY);
1686 fprintf(stderr, "%s\n", dlerror());
1690 p = dlsym(handle, "alias_mod");
1691 if ((error = dlerror()) != NULL) {
1692 fprintf(stderr, "%s\n", dlerror());
1696 t = malloc(sizeof(struct dll));
1699 strncpy(t->name, p->name, DLL_LEN);
1701 if (attach_dll(t) == EEXIST) {
1703 fprintf(stderr, "dll conflict\n");
1707 m = dlsym(t->handle, "handlers");
1708 if ((error = dlerror()) != NULL) {
1709 fprintf(stderr, "%s\n", error);
1713 LibAliasAttachHandlers(m);
1718 LibAliasUnLoadAllModule(void)
1721 struct proto_handler *p;
1723 /* Unload all modules then reload everything. */
1724 while ((p = first_handler()) != NULL) {
1727 while ((t = walk_dll_chain()) != NULL) {
1738 * m_megapullup() - this function is a big hack.
1739 * Thankfully, it's only used in ng_nat and ipfw+nat.
1741 * It allocates an mbuf with cluster and copies the specified part of the chain
1742 * into cluster, so that it is all contiguous and can be accessed via a plain
1743 * (char *) pointer. This is required, because libalias doesn't know how to
1744 * handle mbuf chains.
1746 * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1747 * the input packet, on failure NULL. The input packet is always consumed.
1750 m_megapullup(struct mbuf *m, int len) {
1753 if (len > m->m_pkthdr.len)
1756 /* Do not reallocate packet if it is sequentional,
1757 * writable and has some extra space for expansion.
1758 * XXX: Constant 100bytes is completely empirical. */
1760 if (m->m_next == NULL && M_WRITABLE(m) && M_TRAILINGSPACE(m) >= RESERVE)
1763 if (len <= MCLBYTES - RESERVE) {
1764 mcl = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1765 } else if (len < MJUM16BYTES) {
1767 if (len <= MJUMPAGESIZE - RESERVE) {
1768 size = MJUMPAGESIZE;
1769 } else if (len <= MJUM9BYTES - RESERVE) {
1774 mcl = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, size);
1781 m_move_pkthdr(mcl, m);
1782 m_copydata(m, 0, len, mtod(mcl, caddr_t));
1783 mcl->m_len = mcl->m_pkthdr.len = len;