1 /* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
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.
116 #include <sys/types.h>
118 #include <netinet/in_systm.h>
119 #include <netinet/in.h>
120 #include <netinet/ip.h>
121 #include <netinet/ip_icmp.h>
122 #include <netinet/tcp.h>
123 #include <netinet/udp.h>
127 #include "alias_local.h"
130 #define NETBIOS_NS_PORT_NUMBER 137
131 #define NETBIOS_DGM_PORT_NUMBER 138
132 #define FTP_CONTROL_PORT_NUMBER 21
133 #define IRC_CONTROL_PORT_NUMBER_1 6667
134 #define IRC_CONTROL_PORT_NUMBER_2 6668
135 #define CUSEEME_PORT_NUMBER 7648
136 #define RTSP_CONTROL_PORT_NUMBER_1 554
137 #define RTSP_CONTROL_PORT_NUMBER_2 7070
138 #define TFTP_PORT_NUMBER 69
139 #define PPTP_CONTROL_PORT_NUMBER 1723
144 /* TCP Handling Routines
146 TcpMonitorIn() -- These routines monitor TCP connections, and
147 TcpMonitorOut() delete a link when a connection is closed.
149 These routines look for SYN, FIN and RST flags to determine when TCP
150 connections open and close. When a TCP connection closes, the data
151 structure containing packet aliasing information is deleted after
155 /* Local prototypes */
156 static void TcpMonitorIn(struct ip *, struct alias_link *);
158 static void TcpMonitorOut(struct ip *, struct alias_link *);
162 TcpMonitorIn(struct ip *pip, struct alias_link *link)
166 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
168 switch (GetStateIn(link))
170 case ALIAS_TCP_STATE_NOT_CONNECTED:
171 if (tc->th_flags & TH_RST)
172 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
173 else if (tc->th_flags & TH_SYN)
174 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
176 case ALIAS_TCP_STATE_CONNECTED:
177 if (tc->th_flags & (TH_FIN | TH_RST))
178 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
184 TcpMonitorOut(struct ip *pip, struct alias_link *link)
188 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
190 switch (GetStateOut(link))
192 case ALIAS_TCP_STATE_NOT_CONNECTED:
193 if (tc->th_flags & TH_RST)
194 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
195 else if (tc->th_flags & TH_SYN)
196 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
198 case ALIAS_TCP_STATE_CONNECTED:
199 if (tc->th_flags & (TH_FIN | TH_RST))
200 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
209 /* Protocol Specific Packet Aliasing Routines
211 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
212 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
213 ProtoAliasIn(), ProtoAliasOut()
214 UdpAliasIn(), UdpAliasOut()
215 TcpAliasIn(), TcpAliasOut()
217 These routines handle protocol specific details of packet aliasing.
218 One may observe a certain amount of repetitive arithmetic in these
219 functions, the purpose of which is to compute a revised checksum
220 without actually summing over the entire data packet, which could be
221 unnecessarily time consuming.
223 The purpose of the packet aliasing routines is to replace the source
224 address of the outgoing packet and then correctly put it back for
225 any incoming packets. For TCP and UDP, ports are also re-mapped.
227 For ICMP echo/timestamp requests and replies, the following scheme
228 is used: the ID number is replaced by an alias for the outgoing
231 ICMP error messages are handled by looking at the IP fragment
232 in the data section of the message.
234 For TCP and UDP protocols, a port number is chosen for an outgoing
235 packet, and then incoming packets are identified by IP address and
236 port numbers. For TCP packets, there is additional logic in the event
237 that sequence and ACK numbers have been altered (as in the case for
238 FTP data port commands).
240 The port numbers used by the packet aliasing module are not true
241 ports in the Unix sense. No sockets are actually bound to ports.
242 They are more correctly thought of as placeholders.
244 All packets go through the aliasing mechanism, whether they come from
245 the gateway machine or other machines on a local area network.
249 /* Local prototypes */
250 static int IcmpAliasIn1(struct ip *);
251 static int IcmpAliasIn2(struct ip *);
252 static int IcmpAliasIn (struct ip *);
254 static int IcmpAliasOut1(struct ip *);
255 static int IcmpAliasOut2(struct ip *);
256 static int IcmpAliasOut (struct ip *);
258 static int ProtoAliasIn(struct ip *);
259 static int ProtoAliasOut(struct ip *);
261 static int UdpAliasOut(struct ip *);
262 static int UdpAliasIn (struct ip *);
264 static int TcpAliasOut(struct ip *, int);
265 static int TcpAliasIn (struct ip *);
269 IcmpAliasIn1(struct ip *pip)
272 De-alias incoming echo and timestamp replies.
273 Alias incoming echo and timestamp requests.
275 struct alias_link *link;
278 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
280 /* Get source address from ICMP data field and restore original data */
281 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
287 original_id = GetOriginalPort(link);
289 /* Adjust ICMP checksum */
290 accumulate = ic->icmp_id;
291 accumulate -= original_id;
292 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
294 /* Put original sequence number back in */
295 ic->icmp_id = original_id;
297 /* Put original address back into IP header */
299 struct in_addr original_address;
301 original_address = GetOriginalAddress(link);
302 DifferentialChecksum(&pip->ip_sum,
303 (u_short *) &original_address,
304 (u_short *) &pip->ip_dst,
306 pip->ip_dst = original_address;
309 return(PKT_ALIAS_OK);
311 return(PKT_ALIAS_IGNORED);
315 IcmpAliasIn2(struct ip *pip)
318 Alias incoming ICMP error messages containing
319 IP header and first 64 bits of datagram.
322 struct icmp *ic, *ic2;
325 struct alias_link *link;
327 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
330 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
331 tc = (struct tcphdr *) ud;
332 ic2 = (struct icmp *) ud;
334 if (ip->ip_p == IPPROTO_UDP)
335 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
336 ud->uh_dport, ud->uh_sport,
338 else if (ip->ip_p == IPPROTO_TCP)
339 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
340 tc->th_dport, tc->th_sport,
342 else if (ip->ip_p == IPPROTO_ICMP) {
343 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
344 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
352 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
356 struct in_addr original_address;
357 u_short original_port;
359 original_address = GetOriginalAddress(link);
360 original_port = GetOriginalPort(link);
362 /* Adjust ICMP checksum */
363 sptr = (u_short *) &(ip->ip_src);
364 accumulate = *sptr++;
366 sptr = (u_short *) &original_address;
367 accumulate -= *sptr++;
369 accumulate += ud->uh_sport;
370 accumulate -= original_port;
371 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
373 /* Un-alias address in IP header */
374 DifferentialChecksum(&pip->ip_sum,
375 (u_short *) &original_address,
376 (u_short *) &pip->ip_dst,
378 pip->ip_dst = original_address;
380 /* Un-alias address and port number of original IP packet
381 fragment contained in ICMP data section */
382 ip->ip_src = original_address;
383 ud->uh_sport = original_port;
385 else if (ip->ip_p == IPPROTO_ICMP)
389 struct in_addr original_address;
392 original_address = GetOriginalAddress(link);
393 original_id = GetOriginalPort(link);
395 /* Adjust ICMP checksum */
396 sptr = (u_short *) &(ip->ip_src);
397 accumulate = *sptr++;
399 sptr = (u_short *) &original_address;
400 accumulate -= *sptr++;
402 accumulate += ic2->icmp_id;
403 accumulate -= original_id;
404 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
406 /* Un-alias address in IP header */
407 DifferentialChecksum(&pip->ip_sum,
408 (u_short *) &original_address,
409 (u_short *) &pip->ip_dst,
411 pip->ip_dst = original_address;
413 /* Un-alias address of original IP packet and sequence number of
414 embedded ICMP datagram */
415 ip->ip_src = original_address;
416 ic2->icmp_id = original_id;
418 return(PKT_ALIAS_OK);
420 return(PKT_ALIAS_IGNORED);
425 IcmpAliasIn(struct ip *pip)
430 /* Return if proxy-only mode is enabled */
431 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
434 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
436 iresult = PKT_ALIAS_IGNORED;
437 switch (ic->icmp_type)
440 case ICMP_TSTAMPREPLY:
441 if (ic->icmp_code == 0)
443 iresult = IcmpAliasIn1(pip);
447 case ICMP_SOURCEQUENCH:
450 iresult = IcmpAliasIn2(pip);
454 iresult = IcmpAliasIn1(pip);
462 IcmpAliasOut1(struct ip *pip)
465 Alias outgoing echo and timestamp requests.
466 De-alias outgoing echo and timestamp replies.
468 struct alias_link *link;
471 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
473 /* Save overwritten data for when echo packet returns */
474 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
480 alias_id = GetAliasPort(link);
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(link);
495 DifferentialChecksum(&pip->ip_sum,
496 (u_short *) &alias_address,
497 (u_short *) &pip->ip_src,
499 pip->ip_src = alias_address;
502 return(PKT_ALIAS_OK);
504 return(PKT_ALIAS_IGNORED);
509 IcmpAliasOut2(struct ip *pip)
512 Alias outgoing ICMP error messages containing
513 IP header and first 64 bits of datagram.
516 struct icmp *ic, *ic2;
519 struct alias_link *link;
521 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
524 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
525 tc = (struct tcphdr *) ud;
526 ic2 = (struct icmp *) ud;
528 if (ip->ip_p == IPPROTO_UDP)
529 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
530 ud->uh_dport, ud->uh_sport,
532 else if (ip->ip_p == IPPROTO_TCP)
533 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
534 tc->th_dport, tc->th_sport,
536 else if (ip->ip_p == IPPROTO_ICMP) {
537 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
538 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
546 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
550 struct in_addr alias_address;
553 alias_address = GetAliasAddress(link);
554 alias_port = GetAliasPort(link);
556 /* Adjust ICMP checksum */
557 sptr = (u_short *) &(ip->ip_dst);
558 accumulate = *sptr++;
560 sptr = (u_short *) &alias_address;
561 accumulate -= *sptr++;
563 accumulate += ud->uh_dport;
564 accumulate -= alias_port;
565 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
568 * Alias address in IP header if it comes from the host
569 * the original TCP/UDP packet was destined for.
571 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
572 DifferentialChecksum(&pip->ip_sum,
573 (u_short *) &alias_address,
574 (u_short *) &pip->ip_src,
576 pip->ip_src = alias_address;
579 /* Alias address and port number of original IP packet
580 fragment contained in ICMP data section */
581 ip->ip_dst = alias_address;
582 ud->uh_dport = alias_port;
584 else if (ip->ip_p == IPPROTO_ICMP)
588 struct in_addr alias_address;
591 alias_address = GetAliasAddress(link);
592 alias_id = GetAliasPort(link);
594 /* Adjust ICMP checksum */
595 sptr = (u_short *) &(ip->ip_dst);
596 accumulate = *sptr++;
598 sptr = (u_short *) &alias_address;
599 accumulate -= *sptr++;
601 accumulate += ic2->icmp_id;
602 accumulate -= alias_id;
603 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
606 * Alias address in IP header if it comes from the host
607 * the original ICMP message was destined for.
609 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
610 DifferentialChecksum(&pip->ip_sum,
611 (u_short *) &alias_address,
612 (u_short *) &pip->ip_src,
614 pip->ip_src = alias_address;
617 /* Alias address of original IP packet and sequence number of
618 embedded ICMP datagram */
619 ip->ip_dst = alias_address;
620 ic2->icmp_id = alias_id;
622 return(PKT_ALIAS_OK);
624 return(PKT_ALIAS_IGNORED);
629 IcmpAliasOut(struct ip *pip)
634 /* Return if proxy-only mode is enabled */
635 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
638 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
640 iresult = PKT_ALIAS_IGNORED;
641 switch (ic->icmp_type)
645 if (ic->icmp_code == 0)
647 iresult = IcmpAliasOut1(pip);
651 case ICMP_SOURCEQUENCH:
654 iresult = IcmpAliasOut2(pip);
657 case ICMP_TSTAMPREPLY:
658 iresult = IcmpAliasOut1(pip);
666 ProtoAliasIn(struct ip *pip)
669 Handle incoming IP packets. The
670 only thing which is done in this case is to alias
671 the dest IP address of the packet to our inside
674 struct alias_link *link;
676 /* Return if proxy-only mode is enabled */
677 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
680 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
683 struct in_addr original_address;
685 original_address = GetOriginalAddress(link);
687 /* Restore original IP address */
688 DifferentialChecksum(&pip->ip_sum,
689 (u_short *) &original_address,
690 (u_short *) &pip->ip_dst,
692 pip->ip_dst = original_address;
694 return(PKT_ALIAS_OK);
696 return(PKT_ALIAS_IGNORED);
701 ProtoAliasOut(struct ip *pip)
704 Handle outgoing IP packets. The
705 only thing which is done in this case is to alias
706 the source IP address of the packet.
708 struct alias_link *link;
710 /* Return if proxy-only mode is enabled */
711 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
714 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
717 struct in_addr alias_address;
719 alias_address = GetAliasAddress(link);
721 /* Change source address */
722 DifferentialChecksum(&pip->ip_sum,
723 (u_short *) &alias_address,
724 (u_short *) &pip->ip_src,
726 pip->ip_src = alias_address;
728 return(PKT_ALIAS_OK);
730 return(PKT_ALIAS_IGNORED);
735 UdpAliasIn(struct ip *pip)
738 struct alias_link *link;
740 /* Return if proxy-only mode is enabled */
741 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
744 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
746 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
747 ud->uh_sport, ud->uh_dport,
751 struct in_addr alias_address;
752 struct in_addr original_address;
758 alias_address = GetAliasAddress(link);
759 original_address = GetOriginalAddress(link);
760 alias_port = ud->uh_dport;
761 ud->uh_dport = GetOriginalPort(link);
763 /* Special processing for IP encoding protocols */
764 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
765 AliasHandleCUSeeMeIn(pip, original_address);
766 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
767 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
768 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
769 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
770 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
771 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
772 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
773 &original_address, &ud->uh_dport);
775 /* If UDP checksum is not zero, then adjust since destination port */
776 /* is being unaliased and destination address is being altered. */
779 accumulate = alias_port;
780 accumulate -= ud->uh_dport;
781 sptr = (u_short *) &alias_address;
782 accumulate += *sptr++;
784 sptr = (u_short *) &original_address;
785 accumulate -= *sptr++;
787 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
790 /* Restore original IP address */
791 DifferentialChecksum(&pip->ip_sum,
792 (u_short *) &original_address,
793 (u_short *) &pip->ip_dst,
795 pip->ip_dst = original_address;
798 * If we cannot figure out the packet, ignore it.
801 return(PKT_ALIAS_IGNORED);
803 return(PKT_ALIAS_OK);
805 return(PKT_ALIAS_IGNORED);
809 UdpAliasOut(struct ip *pip)
812 struct alias_link *link;
814 /* Return if proxy-only mode is enabled */
815 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
818 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
820 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
821 ud->uh_sport, ud->uh_dport,
826 struct in_addr alias_address;
828 alias_address = GetAliasAddress(link);
829 alias_port = GetAliasPort(link);
831 /* Special processing for IP encoding protocols */
832 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
833 AliasHandleCUSeeMeOut(pip, link);
834 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
835 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
836 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
837 AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
838 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
839 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
840 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
841 &alias_address, &alias_port);
843 * We don't know in advance what TID the TFTP server will choose,
844 * so we create a wilcard link (destination port is unspecified)
845 * that will match any TID from a given destination.
847 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
848 FindRtspOut(pip->ip_src, pip->ip_dst,
849 ud->uh_sport, alias_port, IPPROTO_UDP);
851 /* If UDP checksum is not zero, adjust since source port is */
852 /* being aliased and source address is being altered */
858 accumulate = ud->uh_sport;
859 accumulate -= alias_port;
860 sptr = (u_short *) &(pip->ip_src);
861 accumulate += *sptr++;
863 sptr = (u_short *) &alias_address;
864 accumulate -= *sptr++;
866 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
869 /* Put alias port in UDP header */
870 ud->uh_sport = alias_port;
872 /* Change source address */
873 DifferentialChecksum(&pip->ip_sum,
874 (u_short *) &alias_address,
875 (u_short *) &pip->ip_src,
877 pip->ip_src = alias_address;
879 return(PKT_ALIAS_OK);
881 return(PKT_ALIAS_IGNORED);
887 TcpAliasIn(struct ip *pip)
890 struct alias_link *link;
892 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
894 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
895 tc->th_sport, tc->th_dport,
897 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
900 struct in_addr alias_address;
901 struct in_addr original_address;
902 struct in_addr proxy_address;
908 /* Special processing for IP encoding protocols */
909 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
910 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
911 AliasHandlePptpIn(pip, link);
913 alias_address = GetAliasAddress(link);
914 original_address = GetOriginalAddress(link);
915 proxy_address = GetProxyAddress(link);
916 alias_port = tc->th_dport;
917 tc->th_dport = GetOriginalPort(link);
918 proxy_port = GetProxyPort(link);
920 /* Adjust TCP checksum since destination port is being unaliased */
921 /* and destination port is being altered. */
922 accumulate = alias_port;
923 accumulate -= tc->th_dport;
924 sptr = (u_short *) &alias_address;
925 accumulate += *sptr++;
927 sptr = (u_short *) &original_address;
928 accumulate -= *sptr++;
931 /* If this is a proxy, then modify the TCP source port and
932 checksum accumulation */
935 accumulate += tc->th_sport;
936 tc->th_sport = proxy_port;
937 accumulate -= tc->th_sport;
939 sptr = (u_short *) &pip->ip_src;
940 accumulate += *sptr++;
942 sptr = (u_short *) &proxy_address;
943 accumulate -= *sptr++;
947 /* See if ACK number needs to be modified */
948 if (GetAckModified(link) == 1)
952 delta = GetDeltaAckIn(pip, link);
955 sptr = (u_short *) &tc->th_ack;
956 accumulate += *sptr++;
958 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
959 sptr = (u_short *) &tc->th_ack;
960 accumulate -= *sptr++;
965 ADJUST_CHECKSUM(accumulate, tc->th_sum);
967 /* Restore original IP address */
968 sptr = (u_short *) &pip->ip_dst;
969 accumulate = *sptr++;
971 pip->ip_dst = original_address;
972 sptr = (u_short *) &pip->ip_dst;
973 accumulate -= *sptr++;
976 /* If this is a transparent proxy packet, then modify the source
978 if (proxy_address.s_addr != 0)
980 sptr = (u_short *) &pip->ip_src;
981 accumulate += *sptr++;
983 pip->ip_src = proxy_address;
984 sptr = (u_short *) &pip->ip_src;
985 accumulate -= *sptr++;
989 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
991 /* Monitor TCP connection state */
992 TcpMonitorIn(pip, link);
994 return(PKT_ALIAS_OK);
996 return(PKT_ALIAS_IGNORED);
1000 TcpAliasOut(struct ip *pip, int maxpacketsize)
1004 u_short proxy_server_port;
1005 struct in_addr dest_address;
1006 struct in_addr proxy_server_address;
1008 struct alias_link *link;
1010 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1012 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1014 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1015 return PKT_ALIAS_OK;
1017 /* If this is a transparent proxy, save original destination,
1018 then alter the destination and adjust checksums */
1019 dest_port = tc->th_dport;
1020 dest_address = pip->ip_dst;
1021 if (proxy_type != 0)
1026 accumulate = tc->th_dport;
1027 tc->th_dport = proxy_server_port;
1028 accumulate -= tc->th_dport;
1030 sptr = (u_short *) &(pip->ip_dst);
1031 accumulate += *sptr++;
1032 accumulate += *sptr;
1033 sptr = (u_short *) &proxy_server_address;
1034 accumulate -= *sptr++;
1035 accumulate -= *sptr;
1037 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1039 sptr = (u_short *) &(pip->ip_dst);
1040 accumulate = *sptr++;
1041 accumulate += *sptr;
1042 pip->ip_dst = proxy_server_address;
1043 sptr = (u_short *) &(pip->ip_dst);
1044 accumulate -= *sptr++;
1045 accumulate -= *sptr;
1047 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1050 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1051 tc->th_sport, tc->th_dport,
1056 struct in_addr alias_address;
1060 /* Save original destination address, if this is a proxy packet.
1061 Also modify packet to include destination encoding. This may
1062 change the size of IP header. */
1063 if (proxy_type != 0)
1065 SetProxyPort(link, dest_port);
1066 SetProxyAddress(link, dest_address);
1067 ProxyModify(link, pip, maxpacketsize, proxy_type);
1068 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1071 /* Get alias address and port */
1072 alias_port = GetAliasPort(link);
1073 alias_address = GetAliasAddress(link);
1075 /* Monitor TCP connection state */
1076 TcpMonitorOut(pip, link);
1078 /* Special processing for IP encoding protocols */
1079 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1080 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1081 AliasHandleFtpOut(pip, link, maxpacketsize);
1082 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1083 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1084 AliasHandleIrcOut(pip, link, maxpacketsize);
1085 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1086 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1087 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1088 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1089 AliasHandleRtspOut(pip, link, maxpacketsize);
1090 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1091 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1092 AliasHandlePptpOut(pip, link);
1094 /* Adjust TCP checksum since source port is being aliased */
1095 /* and source address is being altered */
1096 accumulate = tc->th_sport;
1097 tc->th_sport = alias_port;
1098 accumulate -= tc->th_sport;
1100 sptr = (u_short *) &(pip->ip_src);
1101 accumulate += *sptr++;
1102 accumulate += *sptr;
1103 sptr = (u_short *) &alias_address;
1104 accumulate -= *sptr++;
1105 accumulate -= *sptr;
1107 /* Modify sequence number if necessary */
1108 if (GetAckModified(link) == 1)
1112 delta = GetDeltaSeqOut(pip, link);
1115 sptr = (u_short *) &tc->th_seq;
1116 accumulate += *sptr++;
1117 accumulate += *sptr;
1118 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1119 sptr = (u_short *) &tc->th_seq;
1120 accumulate -= *sptr++;
1121 accumulate -= *sptr;
1125 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1127 /* Change source address */
1128 sptr = (u_short *) &(pip->ip_src);
1129 accumulate = *sptr++;
1130 accumulate += *sptr;
1131 pip->ip_src = alias_address;
1132 sptr = (u_short *) &(pip->ip_src);
1133 accumulate -= *sptr++;
1134 accumulate -= *sptr;
1136 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1138 return(PKT_ALIAS_OK);
1140 return(PKT_ALIAS_IGNORED);
1146 /* Fragment Handling
1151 The packet aliasing module has a limited ability for handling IP
1152 fragments. If the ICMP, TCP or UDP header is in the first fragment
1153 received, then the ID number of the IP packet is saved, and other
1154 fragments are identified according to their ID number and IP address
1155 they were sent from. Pointers to unresolved fragments can also be
1156 saved and recalled when a header fragment is seen.
1159 /* Local prototypes */
1160 static int FragmentIn(struct ip *);
1161 static int FragmentOut(struct ip *);
1165 FragmentIn(struct ip *pip)
1167 struct alias_link *link;
1169 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1172 struct in_addr original_address;
1174 GetFragmentAddr(link, &original_address);
1175 DifferentialChecksum(&pip->ip_sum,
1176 (u_short *) &original_address,
1177 (u_short *) &pip->ip_dst,
1179 pip->ip_dst = original_address;
1181 return(PKT_ALIAS_OK);
1183 return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1188 FragmentOut(struct ip *pip)
1190 struct in_addr alias_address;
1192 alias_address = FindAliasAddress(pip->ip_src);
1193 DifferentialChecksum(&pip->ip_sum,
1194 (u_short *) &alias_address,
1195 (u_short *) &pip->ip_src,
1197 pip->ip_src = alias_address;
1199 return(PKT_ALIAS_OK);
1207 /* Outside World Access
1209 PacketAliasSaveFragment()
1210 PacketAliasGetFragment()
1211 PacketAliasFragmentIn()
1216 (prototypes in alias.h)
1221 PacketAliasSaveFragment(char *ptr)
1224 struct alias_link *link;
1227 pip = (struct ip *) ptr;
1228 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1229 iresult = PKT_ALIAS_ERROR;
1232 SetFragmentPtr(link, ptr);
1233 iresult = PKT_ALIAS_OK;
1240 PacketAliasGetFragment(char *ptr)
1242 struct alias_link *link;
1246 pip = (struct ip *) ptr;
1247 link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1250 GetFragmentPtr(link, &fptr);
1251 SetFragmentPtr(link, NULL);
1252 SetExpire(link, 0); /* Deletes link */
1264 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased
1266 char *ptr_fragment /* Points to fragment which must
1273 pip = (struct ip *) ptr;
1274 fpip = (struct ip *) ptr_fragment;
1276 DifferentialChecksum(&fpip->ip_sum,
1277 (u_short *) &pip->ip_dst,
1278 (u_short *) &fpip->ip_dst,
1280 fpip->ip_dst = pip->ip_dst;
1285 PacketAliasIn(char *ptr, int maxpacketsize)
1287 struct in_addr alias_addr;
1291 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1292 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1293 iresult = PacketAliasOut(ptr, maxpacketsize);
1294 packetAliasMode |= PKT_ALIAS_REVERSE;
1299 ClearCheckNewLink();
1300 pip = (struct ip *) ptr;
1301 alias_addr = pip->ip_dst;
1303 /* Defense against mangled packets */
1304 if (ntohs(pip->ip_len) > maxpacketsize
1305 || (pip->ip_hl<<2) > maxpacketsize)
1306 return PKT_ALIAS_IGNORED;
1308 iresult = PKT_ALIAS_IGNORED;
1309 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1314 iresult = IcmpAliasIn(pip);
1317 iresult = UdpAliasIn(pip);
1320 iresult = TcpAliasIn(pip);
1323 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1324 AliasHandlePptpGreIn(pip) == 0)
1325 iresult = PKT_ALIAS_OK;
1327 iresult = ProtoAliasIn(pip);
1330 iresult = ProtoAliasIn(pip);
1334 if (ntohs(pip->ip_off) & IP_MF)
1336 struct alias_link *link;
1338 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1341 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1342 SetFragmentAddr(link, pip->ip_dst);
1346 iresult = PKT_ALIAS_ERROR;
1352 iresult = FragmentIn(pip);
1360 /* Unregistered address ranges */
1362 /* 10.0.0.0 -> 10.255.255.255 */
1363 #define UNREG_ADDR_A_LOWER 0x0a000000
1364 #define UNREG_ADDR_A_UPPER 0x0affffff
1366 /* 172.16.0.0 -> 172.31.255.255 */
1367 #define UNREG_ADDR_B_LOWER 0xac100000
1368 #define UNREG_ADDR_B_UPPER 0xac1fffff
1370 /* 192.168.0.0 -> 192.168.255.255 */
1371 #define UNREG_ADDR_C_LOWER 0xc0a80000
1372 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1375 PacketAliasOut(char *ptr, /* valid IP packet */
1376 int maxpacketsize /* How much the packet data may grow
1377 (FTP and IRC inline changes) */
1381 struct in_addr addr_save;
1384 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1385 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1386 iresult = PacketAliasIn(ptr, maxpacketsize);
1387 packetAliasMode |= PKT_ALIAS_REVERSE;
1392 ClearCheckNewLink();
1393 pip = (struct ip *) ptr;
1395 /* Defense against mangled packets */
1396 if (ntohs(pip->ip_len) > maxpacketsize
1397 || (pip->ip_hl<<2) > maxpacketsize)
1398 return PKT_ALIAS_IGNORED;
1400 addr_save = GetDefaultAliasAddress();
1401 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1407 addr = ntohl(pip->ip_src.s_addr);
1408 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1410 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1412 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1417 SetDefaultAliasAddress(pip->ip_src);
1421 iresult = PKT_ALIAS_IGNORED;
1422 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1427 iresult = IcmpAliasOut(pip);
1430 iresult = UdpAliasOut(pip);
1433 iresult = TcpAliasOut(pip, maxpacketsize);
1436 if (AliasHandlePptpGreOut(pip) == 0)
1437 iresult = PKT_ALIAS_OK;
1439 iresult = ProtoAliasOut(pip);
1442 iresult = ProtoAliasOut(pip);
1448 iresult = FragmentOut(pip);
1451 SetDefaultAliasAddress(addr_save);
1456 PacketUnaliasOut(char *ptr, /* valid IP packet */
1457 int maxpacketsize /* for error checking */
1464 struct alias_link *link;
1465 int iresult = PKT_ALIAS_IGNORED;
1467 pip = (struct ip *) ptr;
1469 /* Defense against mangled packets */
1470 if (ntohs(pip->ip_len) > maxpacketsize
1471 || (pip->ip_hl<<2) > maxpacketsize)
1474 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1475 tc = (struct tcphdr *) ud;
1476 ic = (struct icmp *) ud;
1479 if (pip->ip_p == IPPROTO_UDP)
1480 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1481 ud->uh_dport, ud->uh_sport,
1483 else if (pip->ip_p == IPPROTO_TCP)
1484 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1485 tc->th_dport, tc->th_sport,
1487 else if (pip->ip_p == IPPROTO_ICMP)
1488 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1492 /* Change it from an aliased packet to an unaliased packet */
1495 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1499 struct in_addr original_address;
1500 u_short original_port;
1502 original_address = GetOriginalAddress(link);
1503 original_port = GetOriginalPort(link);
1505 /* Adjust TCP/UDP checksum */
1506 sptr = (u_short *) &(pip->ip_src);
1507 accumulate = *sptr++;
1508 accumulate += *sptr;
1509 sptr = (u_short *) &original_address;
1510 accumulate -= *sptr++;
1511 accumulate -= *sptr;
1513 if (pip->ip_p == IPPROTO_UDP) {
1514 accumulate += ud->uh_sport;
1515 accumulate -= original_port;
1516 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1518 accumulate += tc->th_sport;
1519 accumulate -= original_port;
1520 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1523 /* Adjust IP checksum */
1524 DifferentialChecksum(&pip->ip_sum,
1525 (u_short *) &original_address,
1526 (u_short *) &pip->ip_src,
1529 /* Un-alias source address and port number */
1530 pip->ip_src = original_address;
1531 if (pip->ip_p == IPPROTO_UDP)
1532 ud->uh_sport = original_port;
1534 tc->th_sport = original_port;
1536 iresult = PKT_ALIAS_OK;
1538 } else if (pip->ip_p == IPPROTO_ICMP) {
1542 struct in_addr original_address;
1543 u_short original_id;
1545 original_address = GetOriginalAddress(link);
1546 original_id = GetOriginalPort(link);
1548 /* Adjust ICMP checksum */
1549 sptr = (u_short *) &(pip->ip_src);
1550 accumulate = *sptr++;
1551 accumulate += *sptr;
1552 sptr = (u_short *) &original_address;
1553 accumulate -= *sptr++;
1554 accumulate -= *sptr;
1555 accumulate += ic->icmp_id;
1556 accumulate -= original_id;
1557 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1559 /* Adjust IP checksum */
1560 DifferentialChecksum(&pip->ip_sum,
1561 (u_short *) &original_address,
1562 (u_short *) &pip->ip_src,
1565 /* Un-alias source address and port number */
1566 pip->ip_src = original_address;
1567 ic->icmp_id = original_id;
1569 iresult = PKT_ALIAS_OK;