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
28 * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.11 2002/07/25 12:31:37 ru Exp $
32 Alias.c provides supervisory control for the functions of the
33 packet aliasing software. It consists of routines to monitor
34 TCP connection state, protocol-specific aliasing routines,
35 fragment handling and the following outside world functional
36 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
37 PacketAliasIn and PacketAliasOut.
39 The other C program files are briefly described. The data
40 structure framework which holds information needed to translate
41 packets is encapsulated in alias_db.c. Data is accessed by
42 function calls, so other segments of the program need not know
43 about the underlying data structures. Alias_ftp.c contains
44 special code for modifying the ftp PORT command used to establish
45 data connections, while alias_irc.c does the same for IRC
46 DCC. Alias_util.c contains a few utility routines.
48 Version 1.0 August, 1996 (cjm)
50 Version 1.1 August 20, 1996 (cjm)
51 PPP host accepts incoming connections for ports 0 to 1023.
52 (Gary Roberts pointed out the need to handle incoming
55 Version 1.2 September 7, 1996 (cjm)
56 Fragment handling error in alias_db.c corrected.
57 (Tom Torrance helped fix this problem.)
59 Version 1.4 September 16, 1996 (cjm)
60 - A more generalized method for handling incoming
61 connections, without the 0-1023 restriction, is
62 implemented in alias_db.c
63 - Improved ICMP support in alias.c. Traceroute
64 packet streams can now be correctly aliased.
65 - TCP connection closing logic simplified in
66 alias.c and now allows for additional 1 minute
67 "grace period" after FIN or RST is observed.
69 Version 1.5 September 17, 1996 (cjm)
70 Corrected error in handling incoming UDP packets with 0 checksum.
71 (Tom Torrance helped fix this problem.)
73 Version 1.6 September 18, 1996 (cjm)
74 Simplified ICMP aliasing scheme. Should now support
75 traceroute from Win95 as well as FreeBSD.
77 Version 1.7 January 9, 1997 (cjm)
78 - Out-of-order fragment handling.
79 - IP checksum error fixed for ftp transfers
81 - Integer return codes added to all
82 aliasing/de-aliasing functions.
83 - Some obsolete comments cleaned up.
84 - Differential checksum computations for
85 IP header (TCP, UDP and ICMP were already
88 Version 2.1 May 1997 (cjm)
89 - Added support for outgoing ICMP error
91 - Added two functions PacketAliasIn2()
92 and PacketAliasOut2() for dynamic address
93 control (e.g. round-robin allocation of
96 Version 2.2 July 1997 (cjm)
97 - Rationalized API function names to begin
99 - Eliminated PacketAliasIn2() and
100 PacketAliasOut2() as poorly conceived.
102 Version 2.3 Dec 1998 (dillon)
103 - Major bounds checking additions, see FreeBSD/CVS
105 Version 3.1 May, 2000 (salander)
106 - Added hooks to handle PPTP.
108 Version 3.2 July, 2000 (salander and satoh)
109 - Added PacketUnaliasOut routine.
110 - Added hooks to handle RTSP/RTP.
112 See HISTORY file for additional revisions.
115 #include <sys/types.h>
117 #include <netinet/in_systm.h>
118 #include <netinet/in.h>
119 #include <netinet/ip.h>
120 #include <netinet/ip_icmp.h>
121 #include <netinet/tcp.h>
122 #include <netinet/udp.h>
126 #include "alias_local.h"
129 #define NETBIOS_NS_PORT_NUMBER 137
130 #define NETBIOS_DGM_PORT_NUMBER 138
131 #define FTP_CONTROL_PORT_NUMBER 21
132 #define IRC_CONTROL_PORT_NUMBER_1 6667
133 #define IRC_CONTROL_PORT_NUMBER_2 6668
134 #define CUSEEME_PORT_NUMBER 7648
135 #define RTSP_CONTROL_PORT_NUMBER_1 554
136 #define RTSP_CONTROL_PORT_NUMBER_2 7070
137 #define TFTP_PORT_NUMBER 69
138 #define PPTP_CONTROL_PORT_NUMBER 1723
143 /* TCP Handling Routines
145 TcpMonitorIn() -- These routines monitor TCP connections, and
146 TcpMonitorOut() delete a link when a connection is closed.
148 These routines look for SYN, FIN and RST flags to determine when TCP
149 connections open and close. When a TCP connection closes, the data
150 structure containing packet aliasing information is deleted after
154 /* Local prototypes */
155 static void TcpMonitorIn(struct ip *, struct alias_link *);
157 static void TcpMonitorOut(struct ip *, struct alias_link *);
161 TcpMonitorIn(struct ip *pip, struct alias_link *link)
165 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
167 switch (GetStateIn(link))
169 case ALIAS_TCP_STATE_NOT_CONNECTED:
170 if (tc->th_flags & TH_RST)
171 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
172 else if (tc->th_flags & TH_SYN)
173 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
175 case ALIAS_TCP_STATE_CONNECTED:
176 if (tc->th_flags & (TH_FIN | TH_RST))
177 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
183 TcpMonitorOut(struct ip *pip, struct alias_link *link)
187 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
189 switch (GetStateOut(link))
191 case ALIAS_TCP_STATE_NOT_CONNECTED:
192 if (tc->th_flags & TH_RST)
193 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
194 else if (tc->th_flags & TH_SYN)
195 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
197 case ALIAS_TCP_STATE_CONNECTED:
198 if (tc->th_flags & (TH_FIN | TH_RST))
199 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
208 /* Protocol Specific Packet Aliasing Routines
210 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
211 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
212 ProtoAliasIn(), ProtoAliasOut()
213 UdpAliasIn(), UdpAliasOut()
214 TcpAliasIn(), TcpAliasOut()
216 These routines handle protocol specific details of packet aliasing.
217 One may observe a certain amount of repetitive arithmetic in these
218 functions, the purpose of which is to compute a revised checksum
219 without actually summing over the entire data packet, which could be
220 unnecessarily time consuming.
222 The purpose of the packet aliasing routines is to replace the source
223 address of the outgoing packet and then correctly put it back for
224 any incoming packets. For TCP and UDP, ports are also re-mapped.
226 For ICMP echo/timestamp requests and replies, the following scheme
227 is used: the ID number is replaced by an alias for the outgoing
230 ICMP error messages are handled by looking at the IP fragment
231 in the data section of the message.
233 For TCP and UDP protocols, a port number is chosen for an outgoing
234 packet, and then incoming packets are identified by IP address and
235 port numbers. For TCP packets, there is additional logic in the event
236 that sequence and ACK numbers have been altered (as in the case for
237 FTP data port commands).
239 The port numbers used by the packet aliasing module are not true
240 ports in the Unix sense. No sockets are actually bound to ports.
241 They are more correctly thought of as placeholders.
243 All packets go through the aliasing mechanism, whether they come from
244 the gateway machine or other machines on a local area network.
248 /* Local prototypes */
249 static int IcmpAliasIn1(struct ip *);
250 static int IcmpAliasIn2(struct ip *);
251 static int IcmpAliasIn (struct ip *);
253 static int IcmpAliasOut1(struct ip *);
254 static int IcmpAliasOut2(struct ip *);
255 static int IcmpAliasOut (struct ip *);
257 static int ProtoAliasIn(struct ip *);
258 static int ProtoAliasOut(struct ip *);
260 static int UdpAliasOut(struct ip *);
261 static int UdpAliasIn (struct ip *);
263 static int TcpAliasOut(struct ip *, int);
264 static int TcpAliasIn (struct ip *);
268 IcmpAliasIn1(struct ip *pip)
271 De-alias incoming echo and timestamp replies.
272 Alias incoming echo and timestamp requests.
274 struct alias_link *link;
277 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
279 /* Get source address from ICMP data field and restore original data */
280 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
286 original_id = GetOriginalPort(link);
288 /* Adjust ICMP checksum */
289 accumulate = ic->icmp_id;
290 accumulate -= original_id;
291 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
293 /* Put original sequence number back in */
294 ic->icmp_id = original_id;
296 /* Put original address back into IP header */
298 struct in_addr original_address;
300 original_address = GetOriginalAddress(link);
301 DifferentialChecksum(&pip->ip_sum,
302 (u_short *) &original_address,
303 (u_short *) &pip->ip_dst,
305 pip->ip_dst = original_address;
308 return(PKT_ALIAS_OK);
310 return(PKT_ALIAS_IGNORED);
314 IcmpAliasIn2(struct ip *pip)
317 Alias incoming ICMP error messages containing
318 IP header and first 64 bits of datagram.
321 struct icmp *ic, *ic2;
324 struct alias_link *link;
326 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
329 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
330 tc = (struct tcphdr *) ud;
331 ic2 = (struct icmp *) ud;
333 if (ip->ip_p == IPPROTO_UDP)
334 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
335 ud->uh_dport, ud->uh_sport,
337 else if (ip->ip_p == IPPROTO_TCP)
338 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
339 tc->th_dport, tc->th_sport,
341 else if (ip->ip_p == IPPROTO_ICMP) {
342 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
343 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
351 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
354 int accumulate, accumulate2;
355 struct in_addr original_address;
356 u_short original_port;
358 original_address = GetOriginalAddress(link);
359 original_port = GetOriginalPort(link);
361 /* Adjust ICMP checksum */
362 sptr = (u_short *) &(ip->ip_src);
363 accumulate = *sptr++;
365 sptr = (u_short *) &original_address;
366 accumulate -= *sptr++;
368 accumulate += ud->uh_sport;
369 accumulate -= original_port;
370 accumulate2 = accumulate;
371 accumulate2 += ip->ip_sum;
372 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
373 accumulate2 -= ip->ip_sum;
374 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
376 /* Un-alias address in IP header */
377 DifferentialChecksum(&pip->ip_sum,
378 (u_short *) &original_address,
379 (u_short *) &pip->ip_dst,
381 pip->ip_dst = original_address;
383 /* Un-alias address and port number of original IP packet
384 fragment contained in ICMP data section */
385 ip->ip_src = original_address;
386 ud->uh_sport = original_port;
388 else if (ip->ip_p == IPPROTO_ICMP)
391 int accumulate, accumulate2;
392 struct in_addr original_address;
395 original_address = GetOriginalAddress(link);
396 original_id = GetOriginalPort(link);
398 /* Adjust ICMP checksum */
399 sptr = (u_short *) &(ip->ip_src);
400 accumulate = *sptr++;
402 sptr = (u_short *) &original_address;
403 accumulate -= *sptr++;
405 accumulate += ic2->icmp_id;
406 accumulate -= original_id;
407 accumulate2 = accumulate;
408 accumulate2 += ip->ip_sum;
409 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
410 accumulate2 -= ip->ip_sum;
411 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
413 /* Un-alias address in IP header */
414 DifferentialChecksum(&pip->ip_sum,
415 (u_short *) &original_address,
416 (u_short *) &pip->ip_dst,
418 pip->ip_dst = original_address;
420 /* Un-alias address of original IP packet and sequence number of
421 embedded ICMP datagram */
422 ip->ip_src = original_address;
423 ic2->icmp_id = original_id;
425 return(PKT_ALIAS_OK);
427 return(PKT_ALIAS_IGNORED);
432 IcmpAliasIn(struct ip *pip)
437 /* Return if proxy-only mode is enabled */
438 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
441 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
443 iresult = PKT_ALIAS_IGNORED;
444 switch (ic->icmp_type)
447 case ICMP_TSTAMPREPLY:
448 if (ic->icmp_code == 0)
450 iresult = IcmpAliasIn1(pip);
454 case ICMP_SOURCEQUENCH:
457 iresult = IcmpAliasIn2(pip);
461 iresult = IcmpAliasIn1(pip);
469 IcmpAliasOut1(struct ip *pip)
472 Alias outgoing echo and timestamp requests.
473 De-alias outgoing echo and timestamp replies.
475 struct alias_link *link;
478 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
480 /* Save overwritten data for when echo packet returns */
481 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
487 alias_id = GetAliasPort(link);
489 /* Since data field is being modified, adjust ICMP checksum */
490 accumulate = ic->icmp_id;
491 accumulate -= alias_id;
492 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
494 /* Alias sequence number */
495 ic->icmp_id = alias_id;
497 /* Change source address */
499 struct in_addr alias_address;
501 alias_address = GetAliasAddress(link);
502 DifferentialChecksum(&pip->ip_sum,
503 (u_short *) &alias_address,
504 (u_short *) &pip->ip_src,
506 pip->ip_src = alias_address;
509 return(PKT_ALIAS_OK);
511 return(PKT_ALIAS_IGNORED);
516 IcmpAliasOut2(struct ip *pip)
519 Alias outgoing ICMP error messages containing
520 IP header and first 64 bits of datagram.
523 struct icmp *ic, *ic2;
526 struct alias_link *link;
528 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
531 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
532 tc = (struct tcphdr *) ud;
533 ic2 = (struct icmp *) ud;
535 if (ip->ip_p == IPPROTO_UDP)
536 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
537 ud->uh_dport, ud->uh_sport,
539 else if (ip->ip_p == IPPROTO_TCP)
540 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
541 tc->th_dport, tc->th_sport,
543 else if (ip->ip_p == IPPROTO_ICMP) {
544 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
545 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
553 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
557 struct in_addr alias_address;
560 alias_address = GetAliasAddress(link);
561 alias_port = GetAliasPort(link);
563 /* Adjust ICMP checksum */
564 sptr = (u_short *) &(ip->ip_dst);
565 accumulate = *sptr++;
567 sptr = (u_short *) &alias_address;
568 accumulate -= *sptr++;
570 accumulate += ud->uh_dport;
571 accumulate -= alias_port;
572 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
575 * Alias address in IP header if it comes from the host
576 * the original TCP/UDP packet was destined for.
578 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
579 DifferentialChecksum(&pip->ip_sum,
580 (u_short *) &alias_address,
581 (u_short *) &pip->ip_src,
583 pip->ip_src = alias_address;
586 /* Alias address and port number of original IP packet
587 fragment contained in ICMP data section */
588 ip->ip_dst = alias_address;
589 ud->uh_dport = alias_port;
591 else if (ip->ip_p == IPPROTO_ICMP)
595 struct in_addr alias_address;
598 alias_address = GetAliasAddress(link);
599 alias_id = GetAliasPort(link);
601 /* Adjust ICMP checksum */
602 sptr = (u_short *) &(ip->ip_dst);
603 accumulate = *sptr++;
605 sptr = (u_short *) &alias_address;
606 accumulate -= *sptr++;
608 accumulate += ic2->icmp_id;
609 accumulate -= alias_id;
610 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
613 * Alias address in IP header if it comes from the host
614 * the original ICMP message was destined for.
616 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
617 DifferentialChecksum(&pip->ip_sum,
618 (u_short *) &alias_address,
619 (u_short *) &pip->ip_src,
621 pip->ip_src = alias_address;
624 /* Alias address of original IP packet and sequence number of
625 embedded ICMP datagram */
626 ip->ip_dst = alias_address;
627 ic2->icmp_id = alias_id;
629 return(PKT_ALIAS_OK);
631 return(PKT_ALIAS_IGNORED);
636 IcmpAliasOut(struct ip *pip)
641 /* Return if proxy-only mode is enabled */
642 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
645 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
647 iresult = PKT_ALIAS_IGNORED;
648 switch (ic->icmp_type)
652 if (ic->icmp_code == 0)
654 iresult = IcmpAliasOut1(pip);
658 case ICMP_SOURCEQUENCH:
661 iresult = IcmpAliasOut2(pip);
664 case ICMP_TSTAMPREPLY:
665 iresult = IcmpAliasOut1(pip);
673 ProtoAliasIn(struct ip *pip)
676 Handle incoming IP packets. The
677 only thing which is done in this case is to alias
678 the dest IP address of the packet to our inside
681 struct alias_link *link;
683 /* Return if proxy-only mode is enabled */
684 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
687 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
690 struct in_addr original_address;
692 original_address = GetOriginalAddress(link);
694 /* Restore original IP address */
695 DifferentialChecksum(&pip->ip_sum,
696 (u_short *) &original_address,
697 (u_short *) &pip->ip_dst,
699 pip->ip_dst = original_address;
701 return(PKT_ALIAS_OK);
703 return(PKT_ALIAS_IGNORED);
708 ProtoAliasOut(struct ip *pip)
711 Handle outgoing IP packets. The
712 only thing which is done in this case is to alias
713 the source IP address of the packet.
715 struct alias_link *link;
717 /* Return if proxy-only mode is enabled */
718 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
721 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
724 struct in_addr alias_address;
726 alias_address = GetAliasAddress(link);
728 /* Change source address */
729 DifferentialChecksum(&pip->ip_sum,
730 (u_short *) &alias_address,
731 (u_short *) &pip->ip_src,
733 pip->ip_src = alias_address;
735 return(PKT_ALIAS_OK);
737 return(PKT_ALIAS_IGNORED);
742 UdpAliasIn(struct ip *pip)
745 struct alias_link *link;
747 /* Return if proxy-only mode is enabled */
748 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
751 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
753 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
754 ud->uh_sport, ud->uh_dport,
758 struct in_addr alias_address;
759 struct in_addr original_address;
765 alias_address = GetAliasAddress(link);
766 original_address = GetOriginalAddress(link);
767 alias_port = ud->uh_dport;
768 ud->uh_dport = GetOriginalPort(link);
770 /* Special processing for IP encoding protocols */
771 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
772 AliasHandleCUSeeMeIn(pip, original_address);
773 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
774 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
775 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
776 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
777 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
778 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
779 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
780 &original_address, &ud->uh_dport);
782 /* If UDP checksum is not zero, then adjust since destination port */
783 /* is being unaliased and destination address is being altered. */
786 accumulate = alias_port;
787 accumulate -= ud->uh_dport;
788 sptr = (u_short *) &alias_address;
789 accumulate += *sptr++;
791 sptr = (u_short *) &original_address;
792 accumulate -= *sptr++;
794 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
797 /* Restore original IP address */
798 DifferentialChecksum(&pip->ip_sum,
799 (u_short *) &original_address,
800 (u_short *) &pip->ip_dst,
802 pip->ip_dst = original_address;
805 * If we cannot figure out the packet, ignore it.
808 return(PKT_ALIAS_IGNORED);
810 return(PKT_ALIAS_OK);
812 return(PKT_ALIAS_IGNORED);
816 UdpAliasOut(struct ip *pip)
819 struct alias_link *link;
821 /* Return if proxy-only mode is enabled */
822 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
825 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
827 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
828 ud->uh_sport, ud->uh_dport,
833 struct in_addr alias_address;
835 alias_address = GetAliasAddress(link);
836 alias_port = GetAliasPort(link);
838 /* Special processing for IP encoding protocols */
839 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
840 AliasHandleCUSeeMeOut(pip, link);
841 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
842 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
843 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
844 AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
845 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
846 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
847 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
848 &alias_address, &alias_port);
850 * We don't know in advance what TID the TFTP server will choose,
851 * so we create a wilcard link (destination port is unspecified)
852 * that will match any TID from a given destination.
854 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
855 FindRtspOut(pip->ip_src, pip->ip_dst,
856 ud->uh_sport, alias_port, IPPROTO_UDP);
858 /* If UDP checksum is not zero, adjust since source port is */
859 /* being aliased and source address is being altered */
865 accumulate = ud->uh_sport;
866 accumulate -= alias_port;
867 sptr = (u_short *) &(pip->ip_src);
868 accumulate += *sptr++;
870 sptr = (u_short *) &alias_address;
871 accumulate -= *sptr++;
873 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
876 /* Put alias port in UDP header */
877 ud->uh_sport = alias_port;
879 /* Change source address */
880 DifferentialChecksum(&pip->ip_sum,
881 (u_short *) &alias_address,
882 (u_short *) &pip->ip_src,
884 pip->ip_src = alias_address;
886 return(PKT_ALIAS_OK);
888 return(PKT_ALIAS_IGNORED);
894 TcpAliasIn(struct ip *pip)
897 struct alias_link *link;
899 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
901 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
902 tc->th_sport, tc->th_dport,
904 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
907 struct in_addr alias_address;
908 struct in_addr original_address;
909 struct in_addr proxy_address;
915 /* Special processing for IP encoding protocols */
916 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
917 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
918 AliasHandlePptpIn(pip, link);
920 alias_address = GetAliasAddress(link);
921 original_address = GetOriginalAddress(link);
922 proxy_address = GetProxyAddress(link);
923 alias_port = tc->th_dport;
924 tc->th_dport = GetOriginalPort(link);
925 proxy_port = GetProxyPort(link);
927 /* Adjust TCP checksum since destination port is being unaliased */
928 /* and destination port is being altered. */
929 accumulate = alias_port;
930 accumulate -= tc->th_dport;
931 sptr = (u_short *) &alias_address;
932 accumulate += *sptr++;
934 sptr = (u_short *) &original_address;
935 accumulate -= *sptr++;
938 /* If this is a proxy, then modify the TCP source port and
939 checksum accumulation */
942 accumulate += tc->th_sport;
943 tc->th_sport = proxy_port;
944 accumulate -= tc->th_sport;
946 sptr = (u_short *) &pip->ip_src;
947 accumulate += *sptr++;
949 sptr = (u_short *) &proxy_address;
950 accumulate -= *sptr++;
954 /* See if ACK number needs to be modified */
955 if (GetAckModified(link) == 1)
959 delta = GetDeltaAckIn(pip, link);
962 sptr = (u_short *) &tc->th_ack;
963 accumulate += *sptr++;
965 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
966 sptr = (u_short *) &tc->th_ack;
967 accumulate -= *sptr++;
972 ADJUST_CHECKSUM(accumulate, tc->th_sum);
974 /* Restore original IP address */
975 sptr = (u_short *) &pip->ip_dst;
976 accumulate = *sptr++;
978 pip->ip_dst = original_address;
979 sptr = (u_short *) &pip->ip_dst;
980 accumulate -= *sptr++;
983 /* If this is a transparent proxy packet, then modify the source
985 if (proxy_address.s_addr != 0)
987 sptr = (u_short *) &pip->ip_src;
988 accumulate += *sptr++;
990 pip->ip_src = proxy_address;
991 sptr = (u_short *) &pip->ip_src;
992 accumulate -= *sptr++;
996 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
998 /* Monitor TCP connection state */
999 TcpMonitorIn(pip, link);
1001 return(PKT_ALIAS_OK);
1003 return(PKT_ALIAS_IGNORED);
1007 TcpAliasOut(struct ip *pip, int maxpacketsize)
1011 u_short proxy_server_port;
1012 struct in_addr dest_address;
1013 struct in_addr proxy_server_address;
1015 struct alias_link *link;
1017 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1019 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1021 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1022 return PKT_ALIAS_OK;
1024 /* If this is a transparent proxy, save original destination,
1025 then alter the destination and adjust checksums */
1026 dest_port = tc->th_dport;
1027 dest_address = pip->ip_dst;
1028 if (proxy_type != 0)
1033 accumulate = tc->th_dport;
1034 tc->th_dport = proxy_server_port;
1035 accumulate -= tc->th_dport;
1037 sptr = (u_short *) &(pip->ip_dst);
1038 accumulate += *sptr++;
1039 accumulate += *sptr;
1040 sptr = (u_short *) &proxy_server_address;
1041 accumulate -= *sptr++;
1042 accumulate -= *sptr;
1044 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1046 sptr = (u_short *) &(pip->ip_dst);
1047 accumulate = *sptr++;
1048 accumulate += *sptr;
1049 pip->ip_dst = proxy_server_address;
1050 sptr = (u_short *) &(pip->ip_dst);
1051 accumulate -= *sptr++;
1052 accumulate -= *sptr;
1054 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1057 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1058 tc->th_sport, tc->th_dport,
1063 struct in_addr alias_address;
1067 /* Save original destination address, if this is a proxy packet.
1068 Also modify packet to include destination encoding. This may
1069 change the size of IP header. */
1070 if (proxy_type != 0)
1072 SetProxyPort(link, dest_port);
1073 SetProxyAddress(link, dest_address);
1074 ProxyModify(link, pip, maxpacketsize, proxy_type);
1075 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1078 /* Get alias address and port */
1079 alias_port = GetAliasPort(link);
1080 alias_address = GetAliasAddress(link);
1082 /* Monitor TCP connection state */
1083 TcpMonitorOut(pip, link);
1085 /* Special processing for IP encoding protocols */
1086 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1087 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1088 AliasHandleFtpOut(pip, link, maxpacketsize);
1089 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1090 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1091 AliasHandleIrcOut(pip, link, maxpacketsize);
1092 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1093 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1094 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1095 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1096 AliasHandleRtspOut(pip, link, maxpacketsize);
1097 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1098 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1099 AliasHandlePptpOut(pip, link);
1101 /* Adjust TCP checksum since source port is being aliased */
1102 /* and source address is being altered */
1103 accumulate = tc->th_sport;
1104 tc->th_sport = alias_port;
1105 accumulate -= tc->th_sport;
1107 sptr = (u_short *) &(pip->ip_src);
1108 accumulate += *sptr++;
1109 accumulate += *sptr;
1110 sptr = (u_short *) &alias_address;
1111 accumulate -= *sptr++;
1112 accumulate -= *sptr;
1114 /* Modify sequence number if necessary */
1115 if (GetAckModified(link) == 1)
1119 delta = GetDeltaSeqOut(pip, link);
1122 sptr = (u_short *) &tc->th_seq;
1123 accumulate += *sptr++;
1124 accumulate += *sptr;
1125 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1126 sptr = (u_short *) &tc->th_seq;
1127 accumulate -= *sptr++;
1128 accumulate -= *sptr;
1132 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1134 /* Change source address */
1135 sptr = (u_short *) &(pip->ip_src);
1136 accumulate = *sptr++;
1137 accumulate += *sptr;
1138 pip->ip_src = alias_address;
1139 sptr = (u_short *) &(pip->ip_src);
1140 accumulate -= *sptr++;
1141 accumulate -= *sptr;
1143 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1145 return(PKT_ALIAS_OK);
1147 return(PKT_ALIAS_IGNORED);
1153 /* Fragment Handling
1158 The packet aliasing module has a limited ability for handling IP
1159 fragments. If the ICMP, TCP or UDP header is in the first fragment
1160 received, then the ID number of the IP packet is saved, and other
1161 fragments are identified according to their ID number and IP address
1162 they were sent from. Pointers to unresolved fragments can also be
1163 saved and recalled when a header fragment is seen.
1166 /* Local prototypes */
1167 static int FragmentIn(struct ip *);
1168 static int FragmentOut(struct ip *);
1172 FragmentIn(struct ip *pip)
1174 struct alias_link *link;
1176 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1179 struct in_addr original_address;
1181 GetFragmentAddr(link, &original_address);
1182 DifferentialChecksum(&pip->ip_sum,
1183 (u_short *) &original_address,
1184 (u_short *) &pip->ip_dst,
1186 pip->ip_dst = original_address;
1188 return(PKT_ALIAS_OK);
1190 return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1195 FragmentOut(struct ip *pip)
1197 struct in_addr alias_address;
1199 alias_address = FindAliasAddress(pip->ip_src);
1200 DifferentialChecksum(&pip->ip_sum,
1201 (u_short *) &alias_address,
1202 (u_short *) &pip->ip_src,
1204 pip->ip_src = alias_address;
1206 return(PKT_ALIAS_OK);
1214 /* Outside World Access
1216 PacketAliasSaveFragment()
1217 PacketAliasGetFragment()
1218 PacketAliasFragmentIn()
1223 (prototypes in alias.h)
1228 PacketAliasSaveFragment(char *ptr)
1231 struct alias_link *link;
1234 pip = (struct ip *) ptr;
1235 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1236 iresult = PKT_ALIAS_ERROR;
1239 SetFragmentPtr(link, ptr);
1240 iresult = PKT_ALIAS_OK;
1247 PacketAliasGetFragment(char *ptr)
1249 struct alias_link *link;
1253 pip = (struct ip *) ptr;
1254 link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1257 GetFragmentPtr(link, &fptr);
1258 SetFragmentPtr(link, NULL);
1259 SetExpire(link, 0); /* Deletes link */
1271 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased
1273 char *ptr_fragment /* Points to fragment which must
1280 pip = (struct ip *) ptr;
1281 fpip = (struct ip *) ptr_fragment;
1283 DifferentialChecksum(&fpip->ip_sum,
1284 (u_short *) &pip->ip_dst,
1285 (u_short *) &fpip->ip_dst,
1287 fpip->ip_dst = pip->ip_dst;
1292 PacketAliasIn(char *ptr, int maxpacketsize)
1294 struct in_addr alias_addr;
1298 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1299 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1300 iresult = PacketAliasOut(ptr, maxpacketsize);
1301 packetAliasMode |= PKT_ALIAS_REVERSE;
1306 ClearCheckNewLink();
1307 pip = (struct ip *) ptr;
1308 alias_addr = pip->ip_dst;
1310 /* Defense against mangled packets */
1311 if (ntohs(pip->ip_len) > maxpacketsize
1312 || (pip->ip_hl<<2) > maxpacketsize)
1313 return PKT_ALIAS_IGNORED;
1315 iresult = PKT_ALIAS_IGNORED;
1316 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1321 iresult = IcmpAliasIn(pip);
1324 iresult = UdpAliasIn(pip);
1327 iresult = TcpAliasIn(pip);
1330 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1331 AliasHandlePptpGreIn(pip) == 0)
1332 iresult = PKT_ALIAS_OK;
1334 iresult = ProtoAliasIn(pip);
1337 iresult = ProtoAliasIn(pip);
1341 if (ntohs(pip->ip_off) & IP_MF)
1343 struct alias_link *link;
1345 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1348 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1349 SetFragmentAddr(link, pip->ip_dst);
1353 iresult = PKT_ALIAS_ERROR;
1359 iresult = FragmentIn(pip);
1367 /* Unregistered address ranges */
1369 /* 10.0.0.0 -> 10.255.255.255 */
1370 #define UNREG_ADDR_A_LOWER 0x0a000000
1371 #define UNREG_ADDR_A_UPPER 0x0affffff
1373 /* 172.16.0.0 -> 172.31.255.255 */
1374 #define UNREG_ADDR_B_LOWER 0xac100000
1375 #define UNREG_ADDR_B_UPPER 0xac1fffff
1377 /* 192.168.0.0 -> 192.168.255.255 */
1378 #define UNREG_ADDR_C_LOWER 0xc0a80000
1379 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1382 PacketAliasOut(char *ptr, /* valid IP packet */
1383 int maxpacketsize /* How much the packet data may grow
1384 (FTP and IRC inline changes) */
1388 struct in_addr addr_save;
1391 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1392 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1393 iresult = PacketAliasIn(ptr, maxpacketsize);
1394 packetAliasMode |= PKT_ALIAS_REVERSE;
1399 ClearCheckNewLink();
1400 pip = (struct ip *) ptr;
1402 /* Defense against mangled packets */
1403 if (ntohs(pip->ip_len) > maxpacketsize
1404 || (pip->ip_hl<<2) > maxpacketsize)
1405 return PKT_ALIAS_IGNORED;
1407 addr_save = GetDefaultAliasAddress();
1408 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1414 addr = ntohl(pip->ip_src.s_addr);
1415 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1417 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1419 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1424 SetDefaultAliasAddress(pip->ip_src);
1428 iresult = PKT_ALIAS_IGNORED;
1429 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1434 iresult = IcmpAliasOut(pip);
1437 iresult = UdpAliasOut(pip);
1440 iresult = TcpAliasOut(pip, maxpacketsize);
1443 if (AliasHandlePptpGreOut(pip) == 0)
1444 iresult = PKT_ALIAS_OK;
1446 iresult = ProtoAliasOut(pip);
1449 iresult = ProtoAliasOut(pip);
1455 iresult = FragmentOut(pip);
1458 SetDefaultAliasAddress(addr_save);
1463 PacketUnaliasOut(char *ptr, /* valid IP packet */
1464 int maxpacketsize /* for error checking */
1471 struct alias_link *link;
1472 int iresult = PKT_ALIAS_IGNORED;
1474 pip = (struct ip *) ptr;
1476 /* Defense against mangled packets */
1477 if (ntohs(pip->ip_len) > maxpacketsize
1478 || (pip->ip_hl<<2) > maxpacketsize)
1481 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1482 tc = (struct tcphdr *) ud;
1483 ic = (struct icmp *) ud;
1486 if (pip->ip_p == IPPROTO_UDP)
1487 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1488 ud->uh_dport, ud->uh_sport,
1490 else if (pip->ip_p == IPPROTO_TCP)
1491 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1492 tc->th_dport, tc->th_sport,
1494 else if (pip->ip_p == IPPROTO_ICMP)
1495 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1499 /* Change it from an aliased packet to an unaliased packet */
1502 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1506 struct in_addr original_address;
1507 u_short original_port;
1509 original_address = GetOriginalAddress(link);
1510 original_port = GetOriginalPort(link);
1512 /* Adjust TCP/UDP checksum */
1513 sptr = (u_short *) &(pip->ip_src);
1514 accumulate = *sptr++;
1515 accumulate += *sptr;
1516 sptr = (u_short *) &original_address;
1517 accumulate -= *sptr++;
1518 accumulate -= *sptr;
1520 if (pip->ip_p == IPPROTO_UDP) {
1521 accumulate += ud->uh_sport;
1522 accumulate -= original_port;
1523 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1525 accumulate += tc->th_sport;
1526 accumulate -= original_port;
1527 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1530 /* Adjust IP checksum */
1531 DifferentialChecksum(&pip->ip_sum,
1532 (u_short *) &original_address,
1533 (u_short *) &pip->ip_src,
1536 /* Un-alias source address and port number */
1537 pip->ip_src = original_address;
1538 if (pip->ip_p == IPPROTO_UDP)
1539 ud->uh_sport = original_port;
1541 tc->th_sport = original_port;
1543 iresult = PKT_ALIAS_OK;
1545 } else if (pip->ip_p == IPPROTO_ICMP) {
1549 struct in_addr original_address;
1550 u_short original_id;
1552 original_address = GetOriginalAddress(link);
1553 original_id = GetOriginalPort(link);
1555 /* Adjust ICMP checksum */
1556 sptr = (u_short *) &(pip->ip_src);
1557 accumulate = *sptr++;
1558 accumulate += *sptr;
1559 sptr = (u_short *) &original_address;
1560 accumulate -= *sptr++;
1561 accumulate -= *sptr;
1562 accumulate += ic->icmp_id;
1563 accumulate -= original_id;
1564 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1566 /* Adjust IP checksum */
1567 DifferentialChecksum(&pip->ip_sum,
1568 (u_short *) &original_address,
1569 (u_short *) &pip->ip_src,
1572 /* Un-alias source address and port number */
1573 pip->ip_src = original_address;
1574 ic->icmp_id = original_id;
1576 iresult = PKT_ALIAS_OK;