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>
117 #include <sys/types.h>
121 #include <netinet/in_systm.h>
122 #include <netinet/in.h>
123 #include <netinet/ip.h>
124 #include <netinet/ip_icmp.h>
125 #include <netinet/tcp.h>
126 #include <netinet/udp.h>
129 #include <netinet/libalias/alias.h>
130 #include <netinet/libalias/alias_local.h>
133 #include "alias_local.h"
136 #define NETBIOS_NS_PORT_NUMBER 137
137 #define NETBIOS_DGM_PORT_NUMBER 138
138 #define FTP_CONTROL_PORT_NUMBER 21
139 #define IRC_CONTROL_PORT_NUMBER_1 6667
140 #define IRC_CONTROL_PORT_NUMBER_2 6668
141 #define CUSEEME_PORT_NUMBER 7648
142 #define RTSP_CONTROL_PORT_NUMBER_1 554
143 #define RTSP_CONTROL_PORT_NUMBER_2 7070
144 #define TFTP_PORT_NUMBER 69
145 #define PPTP_CONTROL_PORT_NUMBER 1723
152 #if BYTE_ORDER == LITTLE_ENDIAN
153 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
154 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
156 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
157 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
162 /* TCP Handling Routines
164 TcpMonitorIn() -- These routines monitor TCP connections, and
165 TcpMonitorOut() delete a link when a connection is closed.
167 These routines look for SYN, FIN and RST flags to determine when TCP
168 connections open and close. When a TCP connection closes, the data
169 structure containing packet aliasing information is deleted after
173 /* Local prototypes */
174 static void TcpMonitorIn(struct ip *, struct alias_link *);
176 static void TcpMonitorOut(struct ip *, struct alias_link *);
180 TcpMonitorIn(struct ip *pip, struct alias_link *lnk)
184 tc = (struct tcphdr *)ip_next(pip);
186 switch (GetStateIn(lnk)) {
187 case ALIAS_TCP_STATE_NOT_CONNECTED:
188 if (tc->th_flags & TH_RST)
189 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
190 else if (tc->th_flags & TH_SYN)
191 SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED);
193 case ALIAS_TCP_STATE_CONNECTED:
194 if (tc->th_flags & (TH_FIN | TH_RST))
195 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
201 TcpMonitorOut(struct ip *pip, struct alias_link *lnk)
205 tc = (struct tcphdr *)ip_next(pip);
207 switch (GetStateOut(lnk)) {
208 case ALIAS_TCP_STATE_NOT_CONNECTED:
209 if (tc->th_flags & TH_RST)
210 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
211 else if (tc->th_flags & TH_SYN)
212 SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED);
214 case ALIAS_TCP_STATE_CONNECTED:
215 if (tc->th_flags & (TH_FIN | TH_RST))
216 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
225 /* Protocol Specific Packet Aliasing Routines
227 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
228 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
229 ProtoAliasIn(), ProtoAliasOut()
230 UdpAliasIn(), UdpAliasOut()
231 TcpAliasIn(), TcpAliasOut()
233 These routines handle protocol specific details of packet aliasing.
234 One may observe a certain amount of repetitive arithmetic in these
235 functions, the purpose of which is to compute a revised checksum
236 without actually summing over the entire data packet, which could be
237 unnecessarily time consuming.
239 The purpose of the packet aliasing routines is to replace the source
240 address of the outgoing packet and then correctly put it back for
241 any incoming packets. For TCP and UDP, ports are also re-mapped.
243 For ICMP echo/timestamp requests and replies, the following scheme
244 is used: the ID number is replaced by an alias for the outgoing
247 ICMP error messages are handled by looking at the IP fragment
248 in the data section of the message.
250 For TCP and UDP protocols, a port number is chosen for an outgoing
251 packet, and then incoming packets are identified by IP address and
252 port numbers. For TCP packets, there is additional logic in the event
253 that sequence and ACK numbers have been altered (as in the case for
254 FTP data port commands).
256 The port numbers used by the packet aliasing module are not true
257 ports in the Unix sense. No sockets are actually bound to ports.
258 They are more correctly thought of as placeholders.
260 All packets go through the aliasing mechanism, whether they come from
261 the gateway machine or other machines on a local area network.
265 /* Local prototypes */
266 static int IcmpAliasIn1(struct libalias *, struct ip *);
267 static int IcmpAliasIn2(struct libalias *, struct ip *);
268 static int IcmpAliasIn(struct libalias *, struct ip *);
270 static int IcmpAliasOut1(struct libalias *, struct ip *, int create);
271 static int IcmpAliasOut2(struct libalias *, struct ip *);
272 static int IcmpAliasOut(struct libalias *, struct ip *, int create);
274 static int ProtoAliasIn(struct libalias *, struct ip *);
275 static int ProtoAliasOut(struct libalias *, struct ip *, int create);
277 static int UdpAliasIn(struct libalias *, struct ip *);
278 static int UdpAliasOut(struct libalias *, struct ip *, int create);
280 static int TcpAliasIn(struct libalias *, struct ip *);
281 static int TcpAliasOut(struct libalias *, struct ip *, int, int create);
285 IcmpAliasIn1(struct libalias *la, struct ip *pip)
288 De-alias incoming echo and timestamp replies.
289 Alias incoming echo and timestamp requests.
291 struct alias_link *lnk;
294 ic = (struct icmp *)ip_next(pip);
296 /* Get source address from ICMP data field and restore original data */
297 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
302 original_id = GetOriginalPort(lnk);
304 /* Adjust ICMP checksum */
305 accumulate = ic->icmp_id;
306 accumulate -= original_id;
307 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
309 /* Put original sequence number back in */
310 ic->icmp_id = original_id;
312 /* Put original address back into IP header */
314 struct in_addr original_address;
316 original_address = GetOriginalAddress(lnk);
317 DifferentialChecksum(&pip->ip_sum,
318 &original_address, &pip->ip_dst, 2);
319 pip->ip_dst = original_address;
322 return (PKT_ALIAS_OK);
324 return (PKT_ALIAS_IGNORED);
328 IcmpAliasIn2(struct libalias *la, struct ip *pip)
331 Alias incoming ICMP error messages containing
332 IP header and first 64 bits of datagram.
335 struct icmp *ic, *ic2;
338 struct alias_link *lnk;
340 ic = (struct icmp *)ip_next(pip);
343 ud = (struct udphdr *)ip_next(ip);
344 tc = (struct tcphdr *)ip_next(ip);
345 ic2 = (struct icmp *)ip_next(ip);
347 if (ip->ip_p == IPPROTO_UDP)
348 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
349 ud->uh_dport, ud->uh_sport,
351 else if (ip->ip_p == IPPROTO_TCP)
352 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
353 tc->th_dport, tc->th_sport,
355 else if (ip->ip_p == IPPROTO_ICMP) {
356 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
357 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
364 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
365 int accumulate, accumulate2;
366 struct in_addr original_address;
367 u_short original_port;
369 original_address = GetOriginalAddress(lnk);
370 original_port = GetOriginalPort(lnk);
372 /* Adjust ICMP checksum */
373 accumulate = twowords(&ip->ip_src);
374 accumulate -= twowords(&original_address);
375 accumulate += ud->uh_sport;
376 accumulate -= original_port;
377 accumulate2 = accumulate;
378 accumulate2 += ip->ip_sum;
379 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
380 accumulate2 -= ip->ip_sum;
381 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
383 /* Un-alias address in IP header */
384 DifferentialChecksum(&pip->ip_sum,
385 &original_address, &pip->ip_dst, 2);
386 pip->ip_dst = original_address;
388 /* Un-alias address and port number of original IP packet
389 fragment contained in ICMP data section */
390 ip->ip_src = original_address;
391 ud->uh_sport = original_port;
392 } else if (ip->ip_p == IPPROTO_ICMP) {
393 int accumulate, accumulate2;
394 struct in_addr original_address;
397 original_address = GetOriginalAddress(lnk);
398 original_id = GetOriginalPort(lnk);
400 /* Adjust ICMP checksum */
401 accumulate = twowords(&ip->ip_src);
402 accumulate -= twowords(&original_address);
403 accumulate += ic2->icmp_id;
404 accumulate -= original_id;
405 accumulate2 = accumulate;
406 accumulate2 += ip->ip_sum;
407 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
408 accumulate2 -= ip->ip_sum;
409 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
411 /* Un-alias address in IP header */
412 DifferentialChecksum(&pip->ip_sum,
413 &original_address, &pip->ip_dst, 2);
414 pip->ip_dst = original_address;
416 /* Un-alias address of original IP packet and sequence number of
417 embedded ICMP datagram */
418 ip->ip_src = original_address;
419 ic2->icmp_id = original_id;
421 return (PKT_ALIAS_OK);
423 return (PKT_ALIAS_IGNORED);
428 IcmpAliasIn(struct libalias *la, struct ip *pip)
433 /* Return if proxy-only mode is enabled */
434 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
435 return (PKT_ALIAS_OK);
437 ic = (struct icmp *)ip_next(pip);
439 iresult = PKT_ALIAS_IGNORED;
440 switch (ic->icmp_type) {
442 case ICMP_TSTAMPREPLY:
443 if (ic->icmp_code == 0) {
444 iresult = IcmpAliasIn1(la, pip);
448 case ICMP_SOURCEQUENCH:
451 iresult = IcmpAliasIn2(la, pip);
455 iresult = IcmpAliasIn1(la, pip);
463 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
466 Alias outgoing echo and timestamp requests.
467 De-alias outgoing echo and timestamp replies.
469 struct alias_link *lnk;
472 ic = (struct icmp *)ip_next(pip);
474 /* Save overwritten data for when echo packet returns */
475 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create);
480 alias_id = GetAliasPort(lnk);
482 /* Since data field is being modified, adjust ICMP checksum */
483 accumulate = ic->icmp_id;
484 accumulate -= alias_id;
485 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
487 /* Alias sequence number */
488 ic->icmp_id = alias_id;
490 /* Change source address */
492 struct in_addr alias_address;
494 alias_address = GetAliasAddress(lnk);
495 DifferentialChecksum(&pip->ip_sum,
496 &alias_address, &pip->ip_src, 2);
497 pip->ip_src = alias_address;
500 return (PKT_ALIAS_OK);
502 return (PKT_ALIAS_IGNORED);
507 IcmpAliasOut2(struct libalias *la, struct ip *pip)
510 Alias outgoing ICMP error messages containing
511 IP header and first 64 bits of datagram.
514 struct icmp *ic, *ic2;
517 struct alias_link *lnk;
519 ic = (struct icmp *)ip_next(pip);
522 ud = (struct udphdr *)ip_next(ip);
523 tc = (struct tcphdr *)ip_next(ip);
524 ic2 = (struct icmp *)ip_next(ip);
526 if (ip->ip_p == IPPROTO_UDP)
527 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
528 ud->uh_dport, ud->uh_sport,
530 else if (ip->ip_p == IPPROTO_TCP)
531 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
532 tc->th_dport, tc->th_sport,
534 else if (ip->ip_p == IPPROTO_ICMP) {
535 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
536 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
543 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
545 struct in_addr alias_address;
548 alias_address = GetAliasAddress(lnk);
549 alias_port = GetAliasPort(lnk);
551 /* Adjust ICMP checksum */
552 accumulate = twowords(&ip->ip_dst);
553 accumulate -= twowords(&alias_address);
554 accumulate += ud->uh_dport;
555 accumulate -= alias_port;
556 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
559 * Alias address in IP header if it comes from the host
560 * the original TCP/UDP packet was destined for.
562 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
563 DifferentialChecksum(&pip->ip_sum,
564 &alias_address, &pip->ip_src, 2);
565 pip->ip_src = alias_address;
567 /* Alias address and port number of original IP packet
568 fragment contained in ICMP data section */
569 ip->ip_dst = alias_address;
570 ud->uh_dport = alias_port;
571 } else if (ip->ip_p == IPPROTO_ICMP) {
573 struct in_addr alias_address;
576 alias_address = GetAliasAddress(lnk);
577 alias_id = GetAliasPort(lnk);
579 /* Adjust ICMP checksum */
580 accumulate = twowords(&ip->ip_dst);
581 accumulate -= twowords(&alias_address);
582 accumulate += ic2->icmp_id;
583 accumulate -= alias_id;
584 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
587 * Alias address in IP header if it comes from the host
588 * the original ICMP message was destined for.
590 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
591 DifferentialChecksum(&pip->ip_sum,
592 &alias_address, &pip->ip_src, 2);
593 pip->ip_src = alias_address;
595 /* Alias address of original IP packet and sequence number of
596 embedded ICMP datagram */
597 ip->ip_dst = alias_address;
598 ic2->icmp_id = alias_id;
600 return (PKT_ALIAS_OK);
602 return (PKT_ALIAS_IGNORED);
607 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
614 /* Return if proxy-only mode is enabled */
615 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
616 return (PKT_ALIAS_OK);
618 ic = (struct icmp *)ip_next(pip);
620 iresult = PKT_ALIAS_IGNORED;
621 switch (ic->icmp_type) {
624 if (ic->icmp_code == 0) {
625 iresult = IcmpAliasOut1(la, pip, create);
629 case ICMP_SOURCEQUENCH:
632 iresult = IcmpAliasOut2(la, pip);
635 case ICMP_TSTAMPREPLY:
636 iresult = IcmpAliasOut1(la, pip, create);
644 ProtoAliasIn(struct libalias *la, struct ip *pip)
647 Handle incoming IP packets. The
648 only thing which is done in this case is to alias
649 the dest IP address of the packet to our inside
652 struct alias_link *lnk;
654 /* Return if proxy-only mode is enabled */
655 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
656 return (PKT_ALIAS_OK);
658 lnk = FindProtoIn(la, pip->ip_src, pip->ip_dst, pip->ip_p);
660 struct in_addr original_address;
662 original_address = GetOriginalAddress(lnk);
664 /* Restore original IP address */
665 DifferentialChecksum(&pip->ip_sum,
666 &original_address, &pip->ip_dst, 2);
667 pip->ip_dst = original_address;
669 return (PKT_ALIAS_OK);
671 return (PKT_ALIAS_IGNORED);
676 ProtoAliasOut(struct libalias *la, struct ip *pip, int create)
679 Handle outgoing IP packets. The
680 only thing which is done in this case is to alias
681 the source IP address of the packet.
683 struct alias_link *lnk;
687 /* Return if proxy-only mode is enabled */
688 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
689 return (PKT_ALIAS_OK);
691 lnk = FindProtoOut(la, pip->ip_src, pip->ip_dst, pip->ip_p);
693 struct in_addr alias_address;
695 alias_address = GetAliasAddress(lnk);
697 /* Change source address */
698 DifferentialChecksum(&pip->ip_sum,
699 &alias_address, &pip->ip_src, 2);
700 pip->ip_src = alias_address;
702 return (PKT_ALIAS_OK);
704 return (PKT_ALIAS_IGNORED);
709 UdpAliasIn(struct libalias *la, struct ip *pip)
712 struct alias_link *lnk;
714 /* Return if proxy-only mode is enabled */
715 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
716 return (PKT_ALIAS_OK);
718 ud = (struct udphdr *)ip_next(pip);
720 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
721 ud->uh_sport, ud->uh_dport,
724 struct in_addr alias_address;
725 struct in_addr original_address;
730 alias_address = GetAliasAddress(lnk);
731 original_address = GetOriginalAddress(lnk);
732 alias_port = ud->uh_dport;
733 ud->uh_dport = GetOriginalPort(lnk);
735 /* Special processing for IP encoding protocols */
736 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
737 AliasHandleCUSeeMeIn(la, pip, original_address);
738 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
739 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
740 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
741 r = AliasHandleUdpNbt(la, pip, lnk, &original_address, ud->uh_dport);
742 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
743 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
744 r = AliasHandleUdpNbtNS(la, pip, lnk, &alias_address, &alias_port,
745 &original_address, &ud->uh_dport);
747 /* If UDP checksum is not zero, then adjust since destination port */
748 /* is being unaliased and destination address is being altered. */
749 if (ud->uh_sum != 0) {
750 accumulate = alias_port;
751 accumulate -= ud->uh_dport;
752 accumulate += twowords(&alias_address);
753 accumulate -= twowords(&original_address);
754 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
756 /* Restore original IP address */
757 DifferentialChecksum(&pip->ip_sum,
758 &original_address, &pip->ip_dst, 2);
759 pip->ip_dst = original_address;
762 * If we cannot figure out the packet, ignore it.
765 return (PKT_ALIAS_IGNORED);
767 return (PKT_ALIAS_OK);
769 return (PKT_ALIAS_IGNORED);
773 UdpAliasOut(struct libalias *la, struct ip *pip, int create)
776 struct alias_link *lnk;
778 /* Return if proxy-only mode is enabled */
779 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
780 return (PKT_ALIAS_OK);
782 ud = (struct udphdr *)ip_next(pip);
784 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
785 ud->uh_sport, ud->uh_dport,
786 IPPROTO_UDP, create);
789 struct in_addr alias_address;
791 alias_address = GetAliasAddress(lnk);
792 alias_port = GetAliasPort(lnk);
794 /* Special processing for IP encoding protocols */
795 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
796 AliasHandleCUSeeMeOut(la, pip, lnk);
797 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
798 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
799 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
800 AliasHandleUdpNbt(la, pip, lnk, &alias_address, alias_port);
801 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
802 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
803 AliasHandleUdpNbtNS(la, pip, lnk, &pip->ip_src, &ud->uh_sport,
804 &alias_address, &alias_port);
806 * We don't know in advance what TID the TFTP server will choose,
807 * so we create a wilcard link (destination port is unspecified)
808 * that will match any TID from a given destination.
810 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
811 FindRtspOut(la, pip->ip_src, pip->ip_dst,
812 ud->uh_sport, alias_port, IPPROTO_UDP);
814 /* If UDP checksum is not zero, adjust since source port is */
815 /* being aliased and source address is being altered */
816 if (ud->uh_sum != 0) {
819 accumulate = ud->uh_sport;
820 accumulate -= alias_port;
821 accumulate += twowords(&pip->ip_src);
822 accumulate -= twowords(&alias_address);
823 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
825 /* Put alias port in UDP header */
826 ud->uh_sport = alias_port;
828 /* Change source address */
829 DifferentialChecksum(&pip->ip_sum,
830 &alias_address, &pip->ip_src, 2);
831 pip->ip_src = alias_address;
833 return (PKT_ALIAS_OK);
835 return (PKT_ALIAS_IGNORED);
841 TcpAliasIn(struct libalias *la, struct ip *pip)
844 struct alias_link *lnk;
846 tc = (struct tcphdr *)ip_next(pip);
848 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
849 tc->th_sport, tc->th_dport,
851 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
853 struct in_addr alias_address;
854 struct in_addr original_address;
855 struct in_addr proxy_address;
860 /* Special processing for IP encoding protocols */
861 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
862 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
863 AliasHandlePptpIn(la, pip, lnk);
864 else if (la->skinnyPort != 0 && (ntohs(tc->th_dport) == la->skinnyPort
865 || ntohs(tc->th_sport) == la->skinnyPort))
866 AliasHandleSkinny(la, pip, lnk);
868 alias_address = GetAliasAddress(lnk);
869 original_address = GetOriginalAddress(lnk);
870 proxy_address = GetProxyAddress(lnk);
871 alias_port = tc->th_dport;
872 tc->th_dport = GetOriginalPort(lnk);
873 proxy_port = GetProxyPort(lnk);
875 /* Adjust TCP checksum since destination port is being unaliased */
876 /* and destination port is being altered. */
877 accumulate = alias_port;
878 accumulate -= tc->th_dport;
879 accumulate += twowords(&alias_address);
880 accumulate -= twowords(&original_address);
882 /* If this is a proxy, then modify the TCP source port and
883 checksum accumulation */
884 if (proxy_port != 0) {
885 accumulate += tc->th_sport;
886 tc->th_sport = proxy_port;
887 accumulate -= tc->th_sport;
888 accumulate += twowords(&pip->ip_src);
889 accumulate -= twowords(&proxy_address);
891 /* See if ACK number needs to be modified */
892 if (GetAckModified(lnk) == 1) {
895 delta = GetDeltaAckIn(pip, lnk);
897 accumulate += twowords(&tc->th_ack);
898 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
899 accumulate -= twowords(&tc->th_ack);
902 ADJUST_CHECKSUM(accumulate, tc->th_sum);
904 /* Restore original IP address */
905 accumulate = twowords(&pip->ip_dst);
906 pip->ip_dst = original_address;
907 accumulate -= twowords(&pip->ip_dst);
909 /* If this is a transparent proxy packet, then modify the source
911 if (proxy_address.s_addr != 0) {
912 accumulate += twowords(&pip->ip_src);
913 pip->ip_src = proxy_address;
914 accumulate -= twowords(&pip->ip_src);
916 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
918 /* Monitor TCP connection state */
919 TcpMonitorIn(pip, lnk);
921 return (PKT_ALIAS_OK);
923 return (PKT_ALIAS_IGNORED);
927 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
931 u_short proxy_server_port;
932 struct in_addr dest_address;
933 struct in_addr proxy_server_address;
935 struct alias_link *lnk;
937 tc = (struct tcphdr *)ip_next(pip);
941 ProxyCheck(la, pip, &proxy_server_address, &proxy_server_port);
945 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
946 return (PKT_ALIAS_OK);
948 /* If this is a transparent proxy, save original destination,
949 then alter the destination and adjust checksums */
950 dest_port = tc->th_dport;
951 dest_address = pip->ip_dst;
952 if (proxy_type != 0) {
955 accumulate = tc->th_dport;
956 tc->th_dport = proxy_server_port;
957 accumulate -= tc->th_dport;
958 accumulate += twowords(&pip->ip_dst);
959 accumulate -= twowords(&proxy_server_address);
960 ADJUST_CHECKSUM(accumulate, tc->th_sum);
962 accumulate = twowords(&pip->ip_dst);
963 pip->ip_dst = proxy_server_address;
964 accumulate -= twowords(&pip->ip_dst);
965 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
967 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
968 tc->th_sport, tc->th_dport,
969 IPPROTO_TCP, create);
971 return (PKT_ALIAS_IGNORED);
974 struct in_addr alias_address;
977 /* Save original destination address, if this is a proxy packet.
978 Also modify packet to include destination encoding. This may
979 change the size of IP header. */
980 if (proxy_type != 0) {
981 SetProxyPort(lnk, dest_port);
982 SetProxyAddress(lnk, dest_address);
983 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
984 tc = (struct tcphdr *)ip_next(pip);
986 /* Get alias address and port */
987 alias_port = GetAliasPort(lnk);
988 alias_address = GetAliasAddress(lnk);
990 /* Monitor TCP connection state */
991 TcpMonitorOut(pip, lnk);
993 /* Special processing for IP encoding protocols */
994 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
995 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
996 AliasHandleFtpOut(la, pip, lnk, maxpacketsize);
997 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
998 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
999 AliasHandleIrcOut(la, pip, lnk, maxpacketsize);
1000 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1001 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1002 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1003 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1004 AliasHandleRtspOut(la, pip, lnk, maxpacketsize);
1005 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1006 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1007 AliasHandlePptpOut(la, pip, lnk);
1008 else if (la->skinnyPort != 0 && (ntohs(tc->th_sport) == la->skinnyPort
1009 || ntohs(tc->th_dport) == la->skinnyPort))
1010 AliasHandleSkinny(la, pip, lnk);
1012 /* Adjust TCP checksum since source port is being aliased */
1013 /* and source address is being altered */
1014 accumulate = tc->th_sport;
1015 tc->th_sport = alias_port;
1016 accumulate -= tc->th_sport;
1017 accumulate += twowords(&pip->ip_src);
1018 accumulate -= twowords(&alias_address);
1020 /* Modify sequence number if necessary */
1021 if (GetAckModified(lnk) == 1) {
1024 delta = GetDeltaSeqOut(pip, lnk);
1026 accumulate += twowords(&tc->th_seq);
1027 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1028 accumulate -= twowords(&tc->th_seq);
1031 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1033 /* Change source address */
1034 accumulate = twowords(&pip->ip_src);
1035 pip->ip_src = alias_address;
1036 accumulate -= twowords(&pip->ip_src);
1037 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1039 return (PKT_ALIAS_OK);
1041 return (PKT_ALIAS_IGNORED);
1047 /* Fragment Handling
1052 The packet aliasing module has a limited ability for handling IP
1053 fragments. If the ICMP, TCP or UDP header is in the first fragment
1054 received, then the ID number of the IP packet is saved, and other
1055 fragments are identified according to their ID number and IP address
1056 they were sent from. Pointers to unresolved fragments can also be
1057 saved and recalled when a header fragment is seen.
1060 /* Local prototypes */
1061 static int FragmentIn(struct libalias *, struct ip *);
1062 static int FragmentOut(struct libalias *, struct ip *);
1066 FragmentIn(struct libalias *la, struct ip *pip)
1068 struct alias_link *lnk;
1070 lnk = FindFragmentIn2(la, pip->ip_src, pip->ip_dst, pip->ip_id);
1072 struct in_addr original_address;
1074 GetFragmentAddr(lnk, &original_address);
1075 DifferentialChecksum(&pip->ip_sum,
1076 &original_address, &pip->ip_dst, 2);
1077 pip->ip_dst = original_address;
1079 return (PKT_ALIAS_OK);
1081 return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1086 FragmentOut(struct libalias *la, struct ip *pip)
1088 struct in_addr alias_address;
1090 alias_address = FindAliasAddress(la, pip->ip_src);
1091 DifferentialChecksum(&pip->ip_sum,
1092 &alias_address, &pip->ip_src, 2);
1093 pip->ip_src = alias_address;
1095 return (PKT_ALIAS_OK);
1103 /* Outside World Access
1105 PacketAliasSaveFragment()
1106 PacketAliasGetFragment()
1107 PacketAliasFragmentIn()
1112 (prototypes in alias.h)
1117 LibAliasSaveFragment(struct libalias *la, char *ptr)
1120 struct alias_link *lnk;
1123 pip = (struct ip *)ptr;
1124 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1125 iresult = PKT_ALIAS_ERROR;
1127 SetFragmentPtr(lnk, ptr);
1128 iresult = PKT_ALIAS_OK;
1135 LibAliasGetFragment(struct libalias *la, char *ptr)
1137 struct alias_link *lnk;
1141 pip = (struct ip *)ptr;
1142 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1144 GetFragmentPtr(lnk, &fptr);
1145 SetFragmentPtr(lnk, NULL);
1146 SetExpire(lnk, 0); /* Deletes link */
1156 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
1159 char *ptr_fragment /* Points to fragment which must be
1167 pip = (struct ip *)ptr;
1168 fpip = (struct ip *)ptr_fragment;
1170 DifferentialChecksum(&fpip->ip_sum,
1171 &pip->ip_dst, &fpip->ip_dst, 2);
1172 fpip->ip_dst = pip->ip_dst;
1177 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1179 struct in_addr alias_addr;
1183 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1184 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1185 iresult = LibAliasOut(la, ptr, maxpacketsize);
1186 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1190 ClearCheckNewLink(la);
1191 pip = (struct ip *)ptr;
1192 alias_addr = pip->ip_dst;
1194 /* Defense against mangled packets */
1195 if (ntohs(pip->ip_len) > maxpacketsize
1196 || (pip->ip_hl << 2) > maxpacketsize)
1197 return (PKT_ALIAS_IGNORED);
1199 iresult = PKT_ALIAS_IGNORED;
1200 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1201 switch (pip->ip_p) {
1203 iresult = IcmpAliasIn(la, pip);
1206 iresult = UdpAliasIn(la, pip);
1209 iresult = TcpAliasIn(la, pip);
1212 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1213 AliasHandlePptpGreIn(la, pip) == 0)
1214 iresult = PKT_ALIAS_OK;
1216 iresult = ProtoAliasIn(la, pip);
1219 iresult = ProtoAliasIn(la, pip);
1223 if (ntohs(pip->ip_off) & IP_MF) {
1224 struct alias_link *lnk;
1226 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1228 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1229 SetFragmentAddr(lnk, pip->ip_dst);
1231 iresult = PKT_ALIAS_ERROR;
1235 iresult = FragmentIn(la, pip);
1243 /* Unregistered address ranges */
1245 /* 10.0.0.0 -> 10.255.255.255 */
1246 #define UNREG_ADDR_A_LOWER 0x0a000000
1247 #define UNREG_ADDR_A_UPPER 0x0affffff
1249 /* 172.16.0.0 -> 172.31.255.255 */
1250 #define UNREG_ADDR_B_LOWER 0xac100000
1251 #define UNREG_ADDR_B_UPPER 0xac1fffff
1253 /* 192.168.0.0 -> 192.168.255.255 */
1254 #define UNREG_ADDR_C_LOWER 0xc0a80000
1255 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1258 LibAliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1259 int maxpacketsize /* How much the packet data may grow (FTP
1260 * and IRC inline changes) */
1263 return (LibAliasOutTry(la, ptr, maxpacketsize, 1));
1267 LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */
1268 int maxpacketsize, /* How much the packet data may grow (FTP
1269 * and IRC inline changes) */
1270 int create /* Create new entries ? */
1274 struct in_addr addr_save;
1277 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1278 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1279 iresult = LibAliasIn(la, ptr, maxpacketsize);
1280 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1284 ClearCheckNewLink(la);
1285 pip = (struct ip *)ptr;
1287 /* Defense against mangled packets */
1288 if (ntohs(pip->ip_len) > maxpacketsize
1289 || (pip->ip_hl << 2) > maxpacketsize)
1290 return (PKT_ALIAS_IGNORED);
1292 addr_save = GetDefaultAliasAddress(la);
1293 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) {
1298 addr = ntohl(pip->ip_src.s_addr);
1299 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1301 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1303 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1307 SetDefaultAliasAddress(la, pip->ip_src);
1309 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1310 SetDefaultAliasAddress(la, pip->ip_src);
1312 iresult = PKT_ALIAS_IGNORED;
1313 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1314 switch (pip->ip_p) {
1316 iresult = IcmpAliasOut(la, pip, create);
1319 iresult = UdpAliasOut(la, pip, create);
1322 iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1325 if (AliasHandlePptpGreOut(la, pip) == 0)
1326 iresult = PKT_ALIAS_OK;
1328 iresult = ProtoAliasOut(la, pip, create);
1331 iresult = ProtoAliasOut(la, pip, create);
1335 iresult = FragmentOut(la, pip);
1338 SetDefaultAliasAddress(la, addr_save);
1343 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1344 int maxpacketsize /* for error checking */
1351 struct alias_link *lnk;
1352 int iresult = PKT_ALIAS_IGNORED;
1354 pip = (struct ip *)ptr;
1356 /* Defense against mangled packets */
1357 if (ntohs(pip->ip_len) > maxpacketsize
1358 || (pip->ip_hl << 2) > maxpacketsize)
1361 ud = (struct udphdr *)ip_next(pip);
1362 tc = (struct tcphdr *)ip_next(pip);
1363 ic = (struct icmp *)ip_next(pip);
1366 if (pip->ip_p == IPPROTO_UDP)
1367 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1368 ud->uh_dport, ud->uh_sport,
1370 else if (pip->ip_p == IPPROTO_TCP)
1371 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1372 tc->th_dport, tc->th_sport,
1374 else if (pip->ip_p == IPPROTO_ICMP)
1375 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1379 /* Change it from an aliased packet to an unaliased packet */
1381 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1383 struct in_addr original_address;
1384 u_short original_port;
1386 original_address = GetOriginalAddress(lnk);
1387 original_port = GetOriginalPort(lnk);
1389 /* Adjust TCP/UDP checksum */
1390 accumulate = twowords(&pip->ip_src);
1391 accumulate -= twowords(&original_address);
1393 if (pip->ip_p == IPPROTO_UDP) {
1394 accumulate += ud->uh_sport;
1395 accumulate -= original_port;
1396 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1398 accumulate += tc->th_sport;
1399 accumulate -= original_port;
1400 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1403 /* Adjust IP checksum */
1404 DifferentialChecksum(&pip->ip_sum,
1405 &original_address, &pip->ip_src, 2);
1407 /* Un-alias source address and port number */
1408 pip->ip_src = original_address;
1409 if (pip->ip_p == IPPROTO_UDP)
1410 ud->uh_sport = original_port;
1412 tc->th_sport = original_port;
1414 iresult = PKT_ALIAS_OK;
1416 } else if (pip->ip_p == IPPROTO_ICMP) {
1419 struct in_addr original_address;
1420 u_short original_id;
1422 original_address = GetOriginalAddress(lnk);
1423 original_id = GetOriginalPort(lnk);
1425 /* Adjust ICMP checksum */
1426 accumulate = twowords(&pip->ip_src);
1427 accumulate -= twowords(&original_address);
1428 accumulate += ic->icmp_id;
1429 accumulate -= original_id;
1430 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1432 /* Adjust IP checksum */
1433 DifferentialChecksum(&pip->ip_sum,
1434 &original_address, &pip->ip_src, 2);
1436 /* Un-alias source address and port number */
1437 pip->ip_src = original_address;
1438 ic->icmp_id = original_id;
1440 iresult = PKT_ALIAS_OK;