2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
33 Alias.c provides supervisory control for the functions of the
34 packet aliasing software. It consists of routines to monitor
35 TCP connection state, protocol-specific aliasing routines,
36 fragment handling and the following outside world functional
37 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
38 PacketAliasIn and PacketAliasOut.
40 The other C program files are briefly described. The data
41 structure framework which holds information needed to translate
42 packets is encapsulated in alias_db.c. Data is accessed by
43 function calls, so other segments of the program need not know
44 about the underlying data structures. Alias_ftp.c contains
45 special code for modifying the ftp PORT command used to establish
46 data connections, while alias_irc.c does the same for IRC
47 DCC. Alias_util.c contains a few utility routines.
49 Version 1.0 August, 1996 (cjm)
51 Version 1.1 August 20, 1996 (cjm)
52 PPP host accepts incoming connections for ports 0 to 1023.
53 (Gary Roberts pointed out the need to handle incoming
56 Version 1.2 September 7, 1996 (cjm)
57 Fragment handling error in alias_db.c corrected.
58 (Tom Torrance helped fix this problem.)
60 Version 1.4 September 16, 1996 (cjm)
61 - A more generalized method for handling incoming
62 connections, without the 0-1023 restriction, is
63 implemented in alias_db.c
64 - Improved ICMP support in alias.c. Traceroute
65 packet streams can now be correctly aliased.
66 - TCP connection closing logic simplified in
67 alias.c and now allows for additional 1 minute
68 "grace period" after FIN or RST is observed.
70 Version 1.5 September 17, 1996 (cjm)
71 Corrected error in handling incoming UDP packets with 0 checksum.
72 (Tom Torrance helped fix this problem.)
74 Version 1.6 September 18, 1996 (cjm)
75 Simplified ICMP aliasing scheme. Should now support
76 traceroute from Win95 as well as FreeBSD.
78 Version 1.7 January 9, 1997 (cjm)
79 - Out-of-order fragment handling.
80 - IP checksum error fixed for ftp transfers
82 - Integer return codes added to all
83 aliasing/de-aliasing functions.
84 - Some obsolete comments cleaned up.
85 - Differential checksum computations for
86 IP header (TCP, UDP and ICMP were already
89 Version 2.1 May 1997 (cjm)
90 - Added support for outgoing ICMP error
92 - Added two functions PacketAliasIn2()
93 and PacketAliasOut2() for dynamic address
94 control (e.g. round-robin allocation of
97 Version 2.2 July 1997 (cjm)
98 - Rationalized API function names to begin
100 - Eliminated PacketAliasIn2() and
101 PacketAliasOut2() as poorly conceived.
103 Version 2.3 Dec 1998 (dillon)
104 - Major bounds checking additions, see FreeBSD/CVS
106 Version 3.1 May, 2000 (salander)
107 - Added hooks to handle PPTP.
109 Version 3.2 July, 2000 (salander and satoh)
110 - Added PacketUnaliasOut routine.
111 - Added hooks to handle RTSP/RTP.
113 See HISTORY file for additional revisions.
117 #include <sys/param.h>
118 #include <sys/systm.h>
119 #include <sys/mbuf.h>
120 #include <sys/sysctl.h>
122 #include <sys/types.h>
131 #include <netinet/in_systm.h>
132 #include <netinet/in.h>
133 #include <netinet/ip.h>
134 #include <netinet/ip_icmp.h>
135 #include <netinet/tcp.h>
136 #include <netinet/udp.h>
139 #include <netinet/libalias/alias.h>
140 #include <netinet/libalias/alias_local.h>
141 #include <netinet/libalias/alias_mod.h>
145 #include "alias_local.h"
146 #include "alias_mod.h"
150 * Define libalias SYSCTL Node
154 SYSCTL_DECL(_net_inet);
155 SYSCTL_DECL(_net_inet_ip);
156 SYSCTL_NODE(_net_inet_ip, OID_AUTO, alias, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
157 "Libalias sysctl API");
166 #if BYTE_ORDER == LITTLE_ENDIAN
167 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
168 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
170 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
171 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
176 /* TCP Handling Routines
178 TcpMonitorIn() -- These routines monitor TCP connections, and
179 TcpMonitorOut() delete a link when a connection is closed.
181 These routines look for SYN, FIN and RST flags to determine when TCP
182 connections open and close. When a TCP connection closes, the data
183 structure containing packet aliasing information is deleted after
187 /* Local prototypes */
188 static void TcpMonitorIn(u_char, struct alias_link *);
190 static void TcpMonitorOut(u_char, struct alias_link *);
194 TcpMonitorIn(u_char th_flags, struct alias_link *lnk)
197 switch (GetStateIn(lnk)) {
198 case ALIAS_TCP_STATE_NOT_CONNECTED:
199 if (th_flags & TH_RST)
200 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
201 else if (th_flags & TH_SYN)
202 SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED);
204 case ALIAS_TCP_STATE_CONNECTED:
205 if (th_flags & (TH_FIN | TH_RST))
206 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
212 TcpMonitorOut(u_char th_flags, struct alias_link *lnk)
215 switch (GetStateOut(lnk)) {
216 case ALIAS_TCP_STATE_NOT_CONNECTED:
217 if (th_flags & TH_RST)
218 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
219 else if (th_flags & TH_SYN)
220 SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED);
222 case ALIAS_TCP_STATE_CONNECTED:
223 if (th_flags & (TH_FIN | TH_RST))
224 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
233 /* Protocol Specific Packet Aliasing Routines
235 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
236 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
237 ProtoAliasIn(), ProtoAliasOut()
238 UdpAliasIn(), UdpAliasOut()
239 TcpAliasIn(), TcpAliasOut()
241 These routines handle protocol specific details of packet aliasing.
242 One may observe a certain amount of repetitive arithmetic in these
243 functions, the purpose of which is to compute a revised checksum
244 without actually summing over the entire data packet, which could be
245 unnecessarily time consuming.
247 The purpose of the packet aliasing routines is to replace the source
248 address of the outgoing packet and then correctly put it back for
249 any incoming packets. For TCP and UDP, ports are also re-mapped.
251 For ICMP echo/timestamp requests and replies, the following scheme
252 is used: the ID number is replaced by an alias for the outgoing
255 ICMP error messages are handled by looking at the IP fragment
256 in the data section of the message.
258 For TCP and UDP protocols, a port number is chosen for an outgoing
259 packet, and then incoming packets are identified by IP address and
260 port numbers. For TCP packets, there is additional logic in the event
261 that sequence and ACK numbers have been altered (as in the case for
262 FTP data port commands).
264 The port numbers used by the packet aliasing module are not true
265 ports in the Unix sense. No sockets are actually bound to ports.
266 They are more correctly thought of as placeholders.
268 All packets go through the aliasing mechanism, whether they come from
269 the gateway machine or other machines on a local area network.
273 /* Local prototypes */
274 static int IcmpAliasIn1(struct libalias *, struct ip *);
275 static int IcmpAliasIn2(struct libalias *, struct ip *);
276 static int IcmpAliasIn(struct libalias *, struct ip *);
278 static int IcmpAliasOut1(struct libalias *, struct ip *, int create);
279 static int IcmpAliasOut2(struct libalias *, struct ip *);
280 static int IcmpAliasOut(struct libalias *, struct ip *, int create);
282 static int ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
283 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum);
284 static int ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
285 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum,
288 static int UdpAliasIn(struct libalias *, struct ip *);
289 static int UdpAliasOut(struct libalias *, struct ip *, int, int create);
291 static int TcpAliasIn(struct libalias *, struct ip *);
292 static int TcpAliasOut(struct libalias *, struct ip *, int, int create);
296 IcmpAliasIn1(struct libalias *la, struct ip *pip)
299 LIBALIAS_LOCK_ASSERT(la);
301 De-alias incoming echo and timestamp replies.
302 Alias incoming echo and timestamp requests.
304 struct alias_link *lnk;
307 ic = (struct icmp *)ip_next(pip);
309 /* Get source address from ICMP data field and restore original data */
310 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
315 original_id = GetOriginalPort(lnk);
317 /* Adjust ICMP checksum */
318 accumulate = ic->icmp_id;
319 accumulate -= original_id;
320 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
322 /* Put original sequence number back in */
323 ic->icmp_id = original_id;
325 /* Put original address back into IP header */
327 struct in_addr original_address;
329 original_address = GetOriginalAddress(lnk);
330 DifferentialChecksum(&pip->ip_sum,
331 &original_address, &pip->ip_dst, 2);
332 pip->ip_dst = original_address;
335 return (PKT_ALIAS_OK);
337 return (PKT_ALIAS_IGNORED);
341 IcmpAliasIn2(struct libalias *la, struct ip *pip)
344 LIBALIAS_LOCK_ASSERT(la);
346 Alias incoming ICMP error messages containing
347 IP header and first 64 bits of datagram.
350 struct icmp *ic, *ic2;
353 struct alias_link *lnk;
355 ic = (struct icmp *)ip_next(pip);
358 ud = (struct udphdr *)ip_next(ip);
359 tc = (struct tcphdr *)ip_next(ip);
360 ic2 = (struct icmp *)ip_next(ip);
362 if (ip->ip_p == IPPROTO_UDP)
363 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
364 ud->uh_dport, ud->uh_sport,
366 else if (ip->ip_p == IPPROTO_TCP)
367 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
368 tc->th_dport, tc->th_sport,
370 else if (ip->ip_p == IPPROTO_ICMP) {
371 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
372 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
379 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
380 int accumulate, accumulate2;
381 struct in_addr original_address;
382 u_short original_port;
384 original_address = GetOriginalAddress(lnk);
385 original_port = GetOriginalPort(lnk);
387 /* Adjust ICMP checksum */
388 accumulate = twowords(&ip->ip_src);
389 accumulate -= twowords(&original_address);
390 accumulate += ud->uh_sport;
391 accumulate -= original_port;
392 accumulate2 = accumulate;
393 accumulate2 += ip->ip_sum;
394 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
395 accumulate2 -= ip->ip_sum;
396 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
398 /* Un-alias address in IP header */
399 DifferentialChecksum(&pip->ip_sum,
400 &original_address, &pip->ip_dst, 2);
401 pip->ip_dst = original_address;
403 /* Un-alias address and port number of original IP packet
404 fragment contained in ICMP data section */
405 ip->ip_src = original_address;
406 ud->uh_sport = original_port;
407 } else if (ip->ip_p == IPPROTO_ICMP) {
408 int accumulate, accumulate2;
409 struct in_addr original_address;
412 original_address = GetOriginalAddress(lnk);
413 original_id = GetOriginalPort(lnk);
415 /* Adjust ICMP checksum */
416 accumulate = twowords(&ip->ip_src);
417 accumulate -= twowords(&original_address);
418 accumulate += ic2->icmp_id;
419 accumulate -= original_id;
420 accumulate2 = accumulate;
421 accumulate2 += ip->ip_sum;
422 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
423 accumulate2 -= ip->ip_sum;
424 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
426 /* Un-alias address in IP header */
427 DifferentialChecksum(&pip->ip_sum,
428 &original_address, &pip->ip_dst, 2);
429 pip->ip_dst = original_address;
431 /* Un-alias address of original IP packet and sequence number of
432 embedded ICMP datagram */
433 ip->ip_src = original_address;
434 ic2->icmp_id = original_id;
436 return (PKT_ALIAS_OK);
438 return (PKT_ALIAS_IGNORED);
443 IcmpAliasIn(struct libalias *la, struct ip *pip)
448 LIBALIAS_LOCK_ASSERT(la);
449 /* Return if proxy-only mode is enabled */
450 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
451 return (PKT_ALIAS_OK);
453 ic = (struct icmp *)ip_next(pip);
455 iresult = PKT_ALIAS_IGNORED;
456 switch (ic->icmp_type) {
458 case ICMP_TSTAMPREPLY:
459 if (ic->icmp_code == 0) {
460 iresult = IcmpAliasIn1(la, pip);
464 case ICMP_SOURCEQUENCH:
467 iresult = IcmpAliasIn2(la, pip);
471 iresult = IcmpAliasIn1(la, pip);
479 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
482 Alias outgoing echo and timestamp requests.
483 De-alias outgoing echo and timestamp replies.
485 struct alias_link *lnk;
488 LIBALIAS_LOCK_ASSERT(la);
489 ic = (struct icmp *)ip_next(pip);
491 /* Save overwritten data for when echo packet returns */
492 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create);
497 alias_id = GetAliasPort(lnk);
499 /* Since data field is being modified, adjust ICMP checksum */
500 accumulate = ic->icmp_id;
501 accumulate -= alias_id;
502 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
504 /* Alias sequence number */
505 ic->icmp_id = alias_id;
507 /* Change source address */
509 struct in_addr alias_address;
511 alias_address = GetAliasAddress(lnk);
512 DifferentialChecksum(&pip->ip_sum,
513 &alias_address, &pip->ip_src, 2);
514 pip->ip_src = alias_address;
517 return (PKT_ALIAS_OK);
519 return (PKT_ALIAS_IGNORED);
524 IcmpAliasOut2(struct libalias *la, struct ip *pip)
527 Alias outgoing ICMP error messages containing
528 IP header and first 64 bits of datagram.
531 struct icmp *ic, *ic2;
534 struct alias_link *lnk;
536 LIBALIAS_LOCK_ASSERT(la);
537 ic = (struct icmp *)ip_next(pip);
540 ud = (struct udphdr *)ip_next(ip);
541 tc = (struct tcphdr *)ip_next(ip);
542 ic2 = (struct icmp *)ip_next(ip);
544 if (ip->ip_p == IPPROTO_UDP)
545 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
546 ud->uh_dport, ud->uh_sport,
548 else if (ip->ip_p == IPPROTO_TCP)
549 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
550 tc->th_dport, tc->th_sport,
552 else if (ip->ip_p == IPPROTO_ICMP) {
553 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
554 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
561 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
563 struct in_addr alias_address;
566 alias_address = GetAliasAddress(lnk);
567 alias_port = GetAliasPort(lnk);
569 /* Adjust ICMP checksum */
570 accumulate = twowords(&ip->ip_dst);
571 accumulate -= twowords(&alias_address);
572 accumulate += ud->uh_dport;
573 accumulate -= alias_port;
574 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
577 * Alias address in IP header if it comes from the host
578 * the original TCP/UDP packet was destined for.
580 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
581 DifferentialChecksum(&pip->ip_sum,
582 &alias_address, &pip->ip_src, 2);
583 pip->ip_src = alias_address;
585 /* Alias address and port number of original IP packet
586 fragment contained in ICMP data section */
587 ip->ip_dst = alias_address;
588 ud->uh_dport = alias_port;
589 } else if (ip->ip_p == IPPROTO_ICMP) {
591 struct in_addr alias_address;
594 alias_address = GetAliasAddress(lnk);
595 alias_id = GetAliasPort(lnk);
597 /* Adjust ICMP checksum */
598 accumulate = twowords(&ip->ip_dst);
599 accumulate -= twowords(&alias_address);
600 accumulate += ic2->icmp_id;
601 accumulate -= alias_id;
602 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
605 * Alias address in IP header if it comes from the host
606 * the original ICMP message was destined for.
608 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
609 DifferentialChecksum(&pip->ip_sum,
610 &alias_address, &pip->ip_src, 2);
611 pip->ip_src = alias_address;
613 /* Alias address of original IP packet and sequence number of
614 embedded ICMP datagram */
615 ip->ip_dst = alias_address;
616 ic2->icmp_id = alias_id;
618 return (PKT_ALIAS_OK);
620 return (PKT_ALIAS_IGNORED);
625 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
630 LIBALIAS_LOCK_ASSERT(la);
633 /* Return if proxy-only mode is enabled */
634 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
635 return (PKT_ALIAS_OK);
637 ic = (struct icmp *)ip_next(pip);
639 iresult = PKT_ALIAS_IGNORED;
640 switch (ic->icmp_type) {
643 if (ic->icmp_code == 0) {
644 iresult = IcmpAliasOut1(la, pip, create);
648 case ICMP_SOURCEQUENCH:
651 iresult = IcmpAliasOut2(la, pip);
654 case ICMP_TSTAMPREPLY:
655 iresult = IcmpAliasOut1(la, pip, create);
661 ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
662 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum)
665 Handle incoming IP packets. The
666 only thing which is done in this case is to alias
667 the dest IP address of the packet to our inside
670 struct alias_link *lnk;
672 LIBALIAS_LOCK_ASSERT(la);
673 /* Return if proxy-only mode is enabled */
674 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
675 return (PKT_ALIAS_OK);
677 lnk = FindProtoIn(la, ip_src, *ip_dst, ip_p);
679 struct in_addr original_address;
681 original_address = GetOriginalAddress(lnk);
683 /* Restore original IP address */
684 DifferentialChecksum(ip_sum,
685 &original_address, ip_dst, 2);
686 *ip_dst = original_address;
688 return (PKT_ALIAS_OK);
690 return (PKT_ALIAS_IGNORED);
694 ProtoAliasOut(struct libalias *la, struct in_addr *ip_src,
695 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
698 Handle outgoing IP packets. The
699 only thing which is done in this case is to alias
700 the source IP address of the packet.
702 struct alias_link *lnk;
704 LIBALIAS_LOCK_ASSERT(la);
706 /* Return if proxy-only mode is enabled */
707 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
708 return (PKT_ALIAS_OK);
711 return (PKT_ALIAS_IGNORED);
713 lnk = FindProtoOut(la, *ip_src, ip_dst, ip_p);
715 struct in_addr alias_address;
717 alias_address = GetAliasAddress(lnk);
719 /* Change source address */
720 DifferentialChecksum(ip_sum,
721 &alias_address, ip_src, 2);
722 *ip_src = alias_address;
724 return (PKT_ALIAS_OK);
726 return (PKT_ALIAS_IGNORED);
731 UdpAliasIn(struct libalias *la, struct ip *pip)
734 struct alias_link *lnk;
736 LIBALIAS_LOCK_ASSERT(la);
738 ud = (struct udphdr *)ip_next(pip);
740 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
741 ud->uh_sport, ud->uh_dport,
742 IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
744 struct in_addr alias_address;
745 struct in_addr original_address;
746 struct in_addr proxy_address;
751 struct alias_data ad = {
753 .oaddr = &original_address,
754 .aaddr = &alias_address,
755 .aport = &alias_port,
756 .sport = &ud->uh_sport,
757 .dport = &ud->uh_dport,
761 alias_address = GetAliasAddress(lnk);
762 original_address = GetOriginalAddress(lnk);
763 proxy_address = GetProxyAddress(lnk);
764 alias_port = ud->uh_dport;
765 ud->uh_dport = GetOriginalPort(lnk);
766 proxy_port = GetProxyPort(lnk);
768 /* Walk out chain. */
769 error = find_handler(IN, UDP, la, pip, &ad);
770 /* If we cannot figure out the packet, ignore it. */
772 return (PKT_ALIAS_IGNORED);
774 /* If UDP checksum is not zero, then adjust since destination port */
775 /* is being unaliased and destination address is being altered. */
776 if (ud->uh_sum != 0) {
777 accumulate = alias_port;
778 accumulate -= ud->uh_dport;
779 accumulate += twowords(&alias_address);
780 accumulate -= twowords(&original_address);
782 /* If this is a proxy packet, modify checksum because of source change.*/
783 if (proxy_port != 0) {
784 accumulate += ud->uh_sport;
785 accumulate -= proxy_port;
788 if (proxy_address.s_addr != 0) {
789 accumulate += twowords(&pip->ip_src);
790 accumulate -= twowords(&proxy_address);
793 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
795 /* XXX: Could the two if's below be concatenated to one ? */
796 /* Restore source port and/or address in case of proxying*/
799 ud->uh_sport = proxy_port;
801 if (proxy_address.s_addr != 0) {
802 DifferentialChecksum(&pip->ip_sum,
803 &proxy_address, &pip->ip_src, 2);
804 pip->ip_src = proxy_address;
807 /* Restore original IP address */
808 DifferentialChecksum(&pip->ip_sum,
809 &original_address, &pip->ip_dst, 2);
810 pip->ip_dst = original_address;
812 return (PKT_ALIAS_OK);
814 return (PKT_ALIAS_IGNORED);
818 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
821 struct alias_link *lnk;
822 struct in_addr dest_address;
823 struct in_addr proxy_server_address;
825 u_short proxy_server_port;
829 LIBALIAS_LOCK_ASSERT(la);
831 /* Return if proxy-only mode is enabled and not proxyrule found.*/
832 ud = (struct udphdr *)ip_next(pip);
833 proxy_type = ProxyCheck(la, &proxy_server_address,
834 &proxy_server_port, pip->ip_src, pip->ip_dst,
835 ud->uh_dport, pip->ip_p);
836 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
837 return (PKT_ALIAS_OK);
839 /* If this is a transparent proxy, save original destination,
840 * then alter the destination and adjust checksums */
841 dest_port = ud->uh_dport;
842 dest_address = pip->ip_dst;
844 if (proxy_type != 0) {
847 accumulate = twowords(&pip->ip_dst);
848 accumulate -= twowords(&proxy_server_address);
850 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
852 if (ud->uh_sum != 0) {
853 accumulate = twowords(&pip->ip_dst);
854 accumulate -= twowords(&proxy_server_address);
855 accumulate += ud->uh_dport;
856 accumulate -= proxy_server_port;
857 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
859 pip->ip_dst = proxy_server_address;
860 ud->uh_dport = proxy_server_port;
862 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
863 ud->uh_sport, ud->uh_dport,
864 IPPROTO_UDP, create);
867 struct in_addr alias_address;
868 struct alias_data ad = {
871 .aaddr = &alias_address,
872 .aport = &alias_port,
873 .sport = &ud->uh_sport,
874 .dport = &ud->uh_dport,
878 /* Save original destination address, if this is a proxy packet.
879 * Also modify packet to include destination encoding. This may
880 * change the size of IP header. */
881 if (proxy_type != 0) {
882 SetProxyPort(lnk, dest_port);
883 SetProxyAddress(lnk, dest_address);
884 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
885 ud = (struct udphdr *)ip_next(pip);
888 alias_address = GetAliasAddress(lnk);
889 alias_port = GetAliasPort(lnk);
891 /* Walk out chain. */
892 error = find_handler(OUT, UDP, la, pip, &ad);
894 /* If UDP checksum is not zero, adjust since source port is */
895 /* being aliased and source address is being altered */
896 if (ud->uh_sum != 0) {
899 accumulate = ud->uh_sport;
900 accumulate -= alias_port;
901 accumulate += twowords(&pip->ip_src);
902 accumulate -= twowords(&alias_address);
903 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
905 /* Put alias port in UDP header */
906 ud->uh_sport = alias_port;
908 /* Change source address */
909 DifferentialChecksum(&pip->ip_sum,
910 &alias_address, &pip->ip_src, 2);
911 pip->ip_src = alias_address;
913 return (PKT_ALIAS_OK);
915 return (PKT_ALIAS_IGNORED);
921 TcpAliasIn(struct libalias *la, struct ip *pip)
924 struct alias_link *lnk;
926 LIBALIAS_LOCK_ASSERT(la);
927 tc = (struct tcphdr *)ip_next(pip);
929 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
930 tc->th_sport, tc->th_dport,
932 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
934 struct in_addr alias_address;
935 struct in_addr original_address;
936 struct in_addr proxy_address;
939 int accumulate, error;
942 * The init of MANY vars is a bit below, but aliashandlepptpin
943 * seems to need the destination port that came within the
944 * packet and not the original one looks below [*].
947 struct alias_data ad = {
952 .sport = &tc->th_sport,
953 .dport = &tc->th_dport,
957 /* Walk out chain. */
958 error = find_handler(IN, TCP, la, pip, &ad);
960 alias_address = GetAliasAddress(lnk);
961 original_address = GetOriginalAddress(lnk);
962 proxy_address = GetProxyAddress(lnk);
963 alias_port = tc->th_dport;
964 tc->th_dport = GetOriginalPort(lnk);
965 proxy_port = GetProxyPort(lnk);
968 * Look above, if anyone is going to add find_handler AFTER
969 * this aliashandlepptpin/point, please redo alias_data too.
970 * Uncommenting the piece here below should be enough.
973 struct alias_data ad = {
975 .oaddr = &original_address,
976 .aaddr = &alias_address,
977 .aport = &alias_port,
978 .sport = &ud->uh_sport,
979 .dport = &ud->uh_dport,
983 /* Walk out chain. */
984 error = find_handler(la, pip, &ad);
986 printf("Protocol handler not found\n");
989 /* Adjust TCP checksum since destination port is being unaliased */
990 /* and destination port is being altered. */
991 accumulate = alias_port;
992 accumulate -= tc->th_dport;
993 accumulate += twowords(&alias_address);
994 accumulate -= twowords(&original_address);
996 /* If this is a proxy, then modify the TCP source port and
997 checksum accumulation */
998 if (proxy_port != 0) {
999 accumulate += tc->th_sport;
1000 tc->th_sport = proxy_port;
1001 accumulate -= tc->th_sport;
1002 accumulate += twowords(&pip->ip_src);
1003 accumulate -= twowords(&proxy_address);
1005 /* See if ACK number needs to be modified */
1006 if (GetAckModified(lnk) == 1) {
1009 tc = (struct tcphdr *)ip_next(pip);
1010 delta = GetDeltaAckIn(tc->th_ack, lnk);
1012 accumulate += twowords(&tc->th_ack);
1013 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
1014 accumulate -= twowords(&tc->th_ack);
1017 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1019 /* Restore original IP address */
1020 accumulate = twowords(&pip->ip_dst);
1021 pip->ip_dst = original_address;
1022 accumulate -= twowords(&pip->ip_dst);
1024 /* If this is a transparent proxy packet, then modify the source
1026 if (proxy_address.s_addr != 0) {
1027 accumulate += twowords(&pip->ip_src);
1028 pip->ip_src = proxy_address;
1029 accumulate -= twowords(&pip->ip_src);
1031 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1033 /* Monitor TCP connection state */
1034 tc = (struct tcphdr *)ip_next(pip);
1035 TcpMonitorIn(tc->th_flags, lnk);
1037 return (PKT_ALIAS_OK);
1039 return (PKT_ALIAS_IGNORED);
1043 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
1045 int proxy_type, error;
1047 u_short proxy_server_port;
1048 struct in_addr dest_address;
1049 struct in_addr proxy_server_address;
1051 struct alias_link *lnk;
1053 LIBALIAS_LOCK_ASSERT(la);
1054 tc = (struct tcphdr *)ip_next(pip);
1057 proxy_type = ProxyCheck(la, &proxy_server_address,
1058 &proxy_server_port, pip->ip_src, pip->ip_dst,
1059 tc->th_dport, pip->ip_p);
1063 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1064 return (PKT_ALIAS_OK);
1066 /* If this is a transparent proxy, save original destination,
1067 then alter the destination and adjust checksums */
1068 dest_port = tc->th_dport;
1069 dest_address = pip->ip_dst;
1070 if (proxy_type != 0) {
1073 accumulate = tc->th_dport;
1074 tc->th_dport = proxy_server_port;
1075 accumulate -= tc->th_dport;
1076 accumulate += twowords(&pip->ip_dst);
1077 accumulate -= twowords(&proxy_server_address);
1078 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1080 accumulate = twowords(&pip->ip_dst);
1081 pip->ip_dst = proxy_server_address;
1082 accumulate -= twowords(&pip->ip_dst);
1083 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1085 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
1086 tc->th_sport, tc->th_dport,
1087 IPPROTO_TCP, create);
1089 return (PKT_ALIAS_IGNORED);
1092 struct in_addr alias_address;
1094 struct alias_data ad = {
1097 .aaddr = &alias_address,
1098 .aport = &alias_port,
1099 .sport = &tc->th_sport,
1100 .dport = &tc->th_dport,
1101 .maxpktsize = maxpacketsize
1104 /* Save original destination address, if this is a proxy packet.
1105 Also modify packet to include destination encoding. This may
1106 change the size of IP header. */
1107 if (proxy_type != 0) {
1108 SetProxyPort(lnk, dest_port);
1109 SetProxyAddress(lnk, dest_address);
1110 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
1111 tc = (struct tcphdr *)ip_next(pip);
1113 /* Get alias address and port */
1114 alias_port = GetAliasPort(lnk);
1115 alias_address = GetAliasAddress(lnk);
1117 /* Monitor TCP connection state */
1118 tc = (struct tcphdr *)ip_next(pip);
1119 TcpMonitorOut(tc->th_flags, lnk);
1121 /* Walk out chain. */
1122 error = find_handler(OUT, TCP, la, pip, &ad);
1124 /* Adjust TCP checksum since source port is being aliased */
1125 /* and source address is being altered */
1126 accumulate = tc->th_sport;
1127 tc->th_sport = alias_port;
1128 accumulate -= tc->th_sport;
1129 accumulate += twowords(&pip->ip_src);
1130 accumulate -= twowords(&alias_address);
1132 /* Modify sequence number if necessary */
1133 if (GetAckModified(lnk) == 1) {
1136 tc = (struct tcphdr *)ip_next(pip);
1137 delta = GetDeltaSeqOut(tc->th_seq, lnk);
1139 accumulate += twowords(&tc->th_seq);
1140 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1141 accumulate -= twowords(&tc->th_seq);
1144 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1146 /* Change source address */
1147 accumulate = twowords(&pip->ip_src);
1148 pip->ip_src = alias_address;
1149 accumulate -= twowords(&pip->ip_src);
1150 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1152 return (PKT_ALIAS_OK);
1154 return (PKT_ALIAS_IGNORED);
1160 /* Fragment Handling
1165 The packet aliasing module has a limited ability for handling IP
1166 fragments. If the ICMP, TCP or UDP header is in the first fragment
1167 received, then the ID number of the IP packet is saved, and other
1168 fragments are identified according to their ID number and IP address
1169 they were sent from. Pointers to unresolved fragments can also be
1170 saved and recalled when a header fragment is seen.
1173 /* Local prototypes */
1174 static int FragmentIn(struct libalias *la, struct in_addr ip_src,
1175 struct in_addr *ip_dst, u_short ip_id, u_short *ip_sum);
1176 static int FragmentOut(struct libalias *, struct in_addr *ip_src,
1180 FragmentIn(struct libalias *la, struct in_addr ip_src, struct in_addr *ip_dst,
1181 u_short ip_id, u_short *ip_sum)
1183 struct alias_link *lnk;
1185 LIBALIAS_LOCK_ASSERT(la);
1186 lnk = FindFragmentIn2(la, ip_src, *ip_dst, ip_id);
1188 struct in_addr original_address;
1190 GetFragmentAddr(lnk, &original_address);
1191 DifferentialChecksum(ip_sum,
1192 &original_address, ip_dst, 2);
1193 *ip_dst = original_address;
1195 return (PKT_ALIAS_OK);
1197 return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1201 FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum)
1203 struct in_addr alias_address;
1205 LIBALIAS_LOCK_ASSERT(la);
1206 alias_address = FindAliasAddress(la, *ip_src);
1207 DifferentialChecksum(ip_sum,
1208 &alias_address, ip_src, 2);
1209 *ip_src = alias_address;
1211 return (PKT_ALIAS_OK);
1219 /* Outside World Access
1221 PacketAliasSaveFragment()
1222 PacketAliasGetFragment()
1223 PacketAliasFragmentIn()
1228 (prototypes in alias.h)
1232 LibAliasSaveFragment(struct libalias *la, char *ptr)
1235 struct alias_link *lnk;
1239 pip = (struct ip *)ptr;
1240 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1241 iresult = PKT_ALIAS_ERROR;
1243 SetFragmentPtr(lnk, ptr);
1244 iresult = PKT_ALIAS_OK;
1246 LIBALIAS_UNLOCK(la);
1251 LibAliasGetFragment(struct libalias *la, char *ptr)
1253 struct alias_link *lnk;
1258 pip = (struct ip *)ptr;
1259 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1261 GetFragmentPtr(lnk, &fptr);
1262 SetFragmentPtr(lnk, NULL);
1263 SetExpire(lnk, 0); /* Deletes link */
1267 LIBALIAS_UNLOCK(la);
1272 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
1275 char *ptr_fragment /* Points to fragment which must be
1284 pip = (struct ip *)ptr;
1285 fpip = (struct ip *)ptr_fragment;
1287 DifferentialChecksum(&fpip->ip_sum,
1288 &pip->ip_dst, &fpip->ip_dst, 2);
1289 fpip->ip_dst = pip->ip_dst;
1290 LIBALIAS_UNLOCK(la);
1293 /* Local prototypes */
1295 LibAliasOutLocked(struct libalias *la, char *ptr,
1296 int maxpacketsize, int create);
1298 LibAliasInLocked(struct libalias *la, char *ptr,
1302 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1307 res = LibAliasInLocked(la, ptr, maxpacketsize);
1308 LIBALIAS_UNLOCK(la);
1313 LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize)
1315 struct in_addr alias_addr;
1319 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1320 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1321 iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1322 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1326 ClearCheckNewLink(la);
1327 pip = (struct ip *)ptr;
1328 alias_addr = pip->ip_dst;
1330 /* Defense against mangled packets */
1331 if (ntohs(pip->ip_len) > maxpacketsize
1332 || (pip->ip_hl << 2) > maxpacketsize) {
1333 iresult = PKT_ALIAS_IGNORED;
1337 iresult = PKT_ALIAS_IGNORED;
1338 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1339 switch (pip->ip_p) {
1341 iresult = IcmpAliasIn(la, pip);
1344 iresult = UdpAliasIn(la, pip);
1347 iresult = TcpAliasIn(la, pip);
1351 iresult = SctpAlias(la, pip, SN_TO_LOCAL);
1356 struct alias_data ad = {
1366 /* Walk out chain. */
1367 error = find_handler(IN, IP, la, pip, &ad);
1369 iresult = PKT_ALIAS_OK;
1371 iresult = ProtoAliasIn(la, pip->ip_src,
1372 &pip->ip_dst, pip->ip_p, &pip->ip_sum);
1376 iresult = ProtoAliasIn(la, pip->ip_src, &pip->ip_dst,
1377 pip->ip_p, &pip->ip_sum);
1381 if (ntohs(pip->ip_off) & IP_MF) {
1382 struct alias_link *lnk;
1384 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1386 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1387 SetFragmentAddr(lnk, pip->ip_dst);
1389 iresult = PKT_ALIAS_ERROR;
1393 iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id,
1403 /* Unregistered address ranges */
1405 /* 10.0.0.0 -> 10.255.255.255 */
1406 #define UNREG_ADDR_A_LOWER 0x0a000000
1407 #define UNREG_ADDR_A_UPPER 0x0affffff
1409 /* 172.16.0.0 -> 172.31.255.255 */
1410 #define UNREG_ADDR_B_LOWER 0xac100000
1411 #define UNREG_ADDR_B_UPPER 0xac1fffff
1413 /* 192.168.0.0 -> 192.168.255.255 */
1414 #define UNREG_ADDR_C_LOWER 0xc0a80000
1415 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1417 /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */
1418 #define UNREG_ADDR_CGN_LOWER 0x64400000
1419 #define UNREG_ADDR_CGN_UPPER 0x647fffff
1422 LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize)
1427 res = LibAliasOutLocked(la, ptr, maxpacketsize, 1);
1428 LIBALIAS_UNLOCK(la);
1433 LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create)
1438 res = LibAliasOutLocked(la, ptr, maxpacketsize, create);
1439 LIBALIAS_UNLOCK(la);
1444 LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */
1445 int maxpacketsize, /* How much the packet data may grow (FTP
1446 * and IRC inline changes) */
1447 int create /* Create new entries ? */
1451 struct in_addr addr_save;
1454 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1455 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1456 iresult = LibAliasInLocked(la, ptr, maxpacketsize);
1457 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1461 ClearCheckNewLink(la);
1462 pip = (struct ip *)ptr;
1464 /* Defense against mangled packets */
1465 if (ntohs(pip->ip_len) > maxpacketsize
1466 || (pip->ip_hl << 2) > maxpacketsize) {
1467 iresult = PKT_ALIAS_IGNORED;
1471 addr_save = GetDefaultAliasAddress(la);
1472 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY ||
1473 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) {
1478 addr = ntohl(pip->ip_src.s_addr);
1479 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1481 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1483 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1485 else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER &&
1486 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN)
1490 SetDefaultAliasAddress(la, pip->ip_src);
1492 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1493 SetDefaultAliasAddress(la, pip->ip_src);
1495 iresult = PKT_ALIAS_IGNORED;
1496 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1497 switch (pip->ip_p) {
1499 iresult = IcmpAliasOut(la, pip, create);
1502 iresult = UdpAliasOut(la, pip, maxpacketsize, create);
1505 iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1509 iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
1514 struct alias_data ad = {
1523 /* Walk out chain. */
1524 error = find_handler(OUT, IP, la, pip, &ad);
1526 iresult = PKT_ALIAS_OK;
1528 iresult = ProtoAliasOut(la, &pip->ip_src,
1529 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1533 iresult = ProtoAliasOut(la, &pip->ip_src,
1534 pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
1538 iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum);
1541 SetDefaultAliasAddress(la, addr_save);
1547 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1548 int maxpacketsize /* for error checking */
1555 struct alias_link *lnk;
1556 int iresult = PKT_ALIAS_IGNORED;
1559 pip = (struct ip *)ptr;
1561 /* Defense against mangled packets */
1562 if (ntohs(pip->ip_len) > maxpacketsize
1563 || (pip->ip_hl << 2) > maxpacketsize)
1566 ud = (struct udphdr *)ip_next(pip);
1567 tc = (struct tcphdr *)ip_next(pip);
1568 ic = (struct icmp *)ip_next(pip);
1571 if (pip->ip_p == IPPROTO_UDP)
1572 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1573 ud->uh_dport, ud->uh_sport,
1575 else if (pip->ip_p == IPPROTO_TCP)
1576 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1577 tc->th_dport, tc->th_sport,
1579 else if (pip->ip_p == IPPROTO_ICMP)
1580 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1584 /* Change it from an aliased packet to an unaliased packet */
1586 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1588 struct in_addr original_address;
1589 u_short original_port;
1591 original_address = GetOriginalAddress(lnk);
1592 original_port = GetOriginalPort(lnk);
1594 /* Adjust TCP/UDP checksum */
1595 accumulate = twowords(&pip->ip_src);
1596 accumulate -= twowords(&original_address);
1598 if (pip->ip_p == IPPROTO_UDP) {
1599 accumulate += ud->uh_sport;
1600 accumulate -= original_port;
1601 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1603 accumulate += tc->th_sport;
1604 accumulate -= original_port;
1605 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1608 /* Adjust IP checksum */
1609 DifferentialChecksum(&pip->ip_sum,
1610 &original_address, &pip->ip_src, 2);
1612 /* Un-alias source address and port number */
1613 pip->ip_src = original_address;
1614 if (pip->ip_p == IPPROTO_UDP)
1615 ud->uh_sport = original_port;
1617 tc->th_sport = original_port;
1619 iresult = PKT_ALIAS_OK;
1621 } else if (pip->ip_p == IPPROTO_ICMP) {
1624 struct in_addr original_address;
1625 u_short original_id;
1627 original_address = GetOriginalAddress(lnk);
1628 original_id = GetOriginalPort(lnk);
1630 /* Adjust ICMP checksum */
1631 accumulate = twowords(&pip->ip_src);
1632 accumulate -= twowords(&original_address);
1633 accumulate += ic->icmp_id;
1634 accumulate -= original_id;
1635 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1637 /* Adjust IP checksum */
1638 DifferentialChecksum(&pip->ip_sum,
1639 &original_address, &pip->ip_src, 2);
1641 /* Un-alias source address and port number */
1642 pip->ip_src = original_address;
1643 ic->icmp_id = original_id;
1645 iresult = PKT_ALIAS_OK;
1649 LIBALIAS_UNLOCK(la);
1657 LibAliasRefreshModules(void)
1659 char buf[256], conf[] = "/etc/libalias.conf";
1663 fd = fopen(conf, "r");
1665 err(1, "fopen(%s)", conf);
1667 LibAliasUnLoadAllModule();
1670 fgets(buf, 256, fd);
1675 for (i = 0; i < len; i++)
1676 if (!isspace(buf[i]))
1680 buf[len - 1] = '\0';
1681 LibAliasLoadModule(buf);
1689 LibAliasLoadModule(char *path)
1693 struct proto_handler *m;
1697 handle = dlopen (path, RTLD_LAZY);
1699 fprintf(stderr, "%s\n", dlerror());
1703 p = dlsym(handle, "alias_mod");
1704 if ((error = dlerror()) != NULL) {
1705 fprintf(stderr, "%s\n", dlerror());
1709 t = malloc(sizeof(struct dll));
1712 strncpy(t->name, p->name, DLL_LEN);
1714 if (attach_dll(t) == EEXIST) {
1716 fprintf(stderr, "dll conflict\n");
1720 m = dlsym(t->handle, "handlers");
1721 if ((error = dlerror()) != NULL) {
1722 fprintf(stderr, "%s\n", error);
1726 LibAliasAttachHandlers(m);
1731 LibAliasUnLoadAllModule(void)
1734 struct proto_handler *p;
1736 /* Unload all modules then reload everything. */
1737 while ((p = first_handler()) != NULL) {
1738 LibAliasDetachHandlers(p);
1740 while ((t = walk_dll_chain()) != NULL) {
1751 * m_megapullup() - this function is a big hack.
1752 * Thankfully, it's only used in ng_nat and ipfw+nat.
1754 * It allocates an mbuf with cluster and copies the specified part of the chain
1755 * into cluster, so that it is all contiguous and can be accessed via a plain
1756 * (char *) pointer. This is required, because libalias doesn't know how to
1757 * handle mbuf chains.
1759 * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1760 * the input packet, on failure NULL. The input packet is always consumed.
1763 m_megapullup(struct mbuf *m, int len)
1767 if (len > m->m_pkthdr.len)
1770 if (m->m_next == NULL && M_WRITABLE(m))
1773 if (len <= MJUMPAGESIZE)
1774 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
1775 else if (len <= MJUM9BYTES)
1776 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1777 else if (len <= MJUM16BYTES)
1778 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
1784 m_move_pkthdr(mcl, m);
1785 m_copydata(m, 0, len, mtod(mcl, caddr_t));
1786 mcl->m_len = mcl->m_pkthdr.len = len;