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/param.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
145 #if BYTE_ORDER == LITTLE_ENDIAN
146 uint16_t s1
= ((uint16_t)c
[1] << 8) + (uint16_t)c
[0];
147 uint16_t s2
= ((uint16_t)c
[3] << 8) + (uint16_t)c
[2];
149 uint16_t s1
= ((uint16_t)c
[0] << 8) + (uint16_t)c
[1];
150 uint16_t s2
= ((uint16_t)c
[2] << 8) + (uint16_t)c
[3];
155 /* TCP Handling Routines
157 TcpMonitorIn() -- These routines monitor TCP connections, and
158 TcpMonitorOut() delete a link when a connection is closed.
160 These routines look for SYN, FIN and RST flags to determine when TCP
161 connections open and close. When a TCP connection closes, the data
162 structure containing packet aliasing information is deleted after
166 /* Local prototypes */
167 static void TcpMonitorIn(struct ip
*, struct alias_link
*);
169 static void TcpMonitorOut(struct ip
*, struct alias_link
*);
173 TcpMonitorIn(struct ip
*pip
, struct alias_link
*link
)
177 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
179 switch (GetStateIn(link
))
181 case ALIAS_TCP_STATE_NOT_CONNECTED
:
182 if (tc
->th_flags
& TH_RST
)
183 SetStateIn(link
, ALIAS_TCP_STATE_DISCONNECTED
);
184 else if (tc
->th_flags
& TH_SYN
)
185 SetStateIn(link
, ALIAS_TCP_STATE_CONNECTED
);
187 case ALIAS_TCP_STATE_CONNECTED
:
188 if (tc
->th_flags
& (TH_FIN
| TH_RST
))
189 SetStateIn(link
, ALIAS_TCP_STATE_DISCONNECTED
);
195 TcpMonitorOut(struct ip
*pip
, struct alias_link
*link
)
199 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
201 switch (GetStateOut(link
))
203 case ALIAS_TCP_STATE_NOT_CONNECTED
:
204 if (tc
->th_flags
& TH_RST
)
205 SetStateOut(link
, ALIAS_TCP_STATE_DISCONNECTED
);
206 else if (tc
->th_flags
& TH_SYN
)
207 SetStateOut(link
, ALIAS_TCP_STATE_CONNECTED
);
209 case ALIAS_TCP_STATE_CONNECTED
:
210 if (tc
->th_flags
& (TH_FIN
| TH_RST
))
211 SetStateOut(link
, ALIAS_TCP_STATE_DISCONNECTED
);
220 /* Protocol Specific Packet Aliasing Routines
222 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
223 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
224 ProtoAliasIn(), ProtoAliasOut()
225 UdpAliasIn(), UdpAliasOut()
226 TcpAliasIn(), TcpAliasOut()
228 These routines handle protocol specific details of packet aliasing.
229 One may observe a certain amount of repetitive arithmetic in these
230 functions, the purpose of which is to compute a revised checksum
231 without actually summing over the entire data packet, which could be
232 unnecessarily time consuming.
234 The purpose of the packet aliasing routines is to replace the source
235 address of the outgoing packet and then correctly put it back for
236 any incoming packets. For TCP and UDP, ports are also re-mapped.
238 For ICMP echo/timestamp requests and replies, the following scheme
239 is used: the ID number is replaced by an alias for the outgoing
242 ICMP error messages are handled by looking at the IP fragment
243 in the data section of the message.
245 For TCP and UDP protocols, a port number is chosen for an outgoing
246 packet, and then incoming packets are identified by IP address and
247 port numbers. For TCP packets, there is additional logic in the event
248 that sequence and ACK numbers have been altered (as in the case for
249 FTP data port commands).
251 The port numbers used by the packet aliasing module are not true
252 ports in the Unix sense. No sockets are actually bound to ports.
253 They are more correctly thought of as placeholders.
255 All packets go through the aliasing mechanism, whether they come from
256 the gateway machine or other machines on a local area network.
260 /* Local prototypes */
261 static int IcmpAliasIn1(struct ip
*);
262 static int IcmpAliasIn2(struct ip
*);
263 static int IcmpAliasIn (struct ip
*);
265 static int IcmpAliasOut1(struct ip
*);
266 static int IcmpAliasOut2(struct ip
*);
267 static int IcmpAliasOut (struct ip
*);
269 static int ProtoAliasIn(struct ip
*);
270 static int ProtoAliasOut(struct ip
*);
272 static int UdpAliasOut(struct ip
*);
273 static int UdpAliasIn (struct ip
*);
275 static int TcpAliasOut(struct ip
*, int);
276 static int TcpAliasIn (struct ip
*);
280 IcmpAliasIn1(struct ip
*pip
)
283 De-alias incoming echo and timestamp replies.
284 Alias incoming echo and timestamp requests.
286 struct alias_link
*link
;
289 ic
= (struct icmp
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
291 /* Get source address from ICMP data field and restore original data */
292 link
= FindIcmpIn(pip
->ip_src
, pip
->ip_dst
, ic
->icmp_id
, 1);
298 original_id
= GetOriginalPort(link
);
300 /* Adjust ICMP checksum */
301 accumulate
= ic
->icmp_id
;
302 accumulate
-= original_id
;
303 ADJUST_CHECKSUM(accumulate
, ic
->icmp_cksum
);
305 /* Put original sequence number back in */
306 ic
->icmp_id
= original_id
;
308 /* Put original address back into IP header */
310 struct in_addr original_address
;
312 original_address
= GetOriginalAddress(link
);
313 DifferentialChecksum(&pip
->ip_sum
,
314 (u_short
*) &original_address
,
315 (u_short
*) &pip
->ip_dst
,
317 pip
->ip_dst
= original_address
;
320 return(PKT_ALIAS_OK
);
322 return(PKT_ALIAS_IGNORED
);
326 IcmpAliasIn2(struct ip
*pip
)
329 Alias incoming ICMP error messages containing
330 IP header and first 64 bits of datagram.
333 struct icmp
*ic
, *ic2
;
336 struct alias_link
*link
;
338 ic
= (struct icmp
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
341 ud
= (struct udphdr
*) ((char *) ip
+ (ip
->ip_hl
<<2));
342 tc
= (struct tcphdr
*) ud
;
343 ic2
= (struct icmp
*) ud
;
345 if (ip
->ip_p
== IPPROTO_UDP
)
346 link
= FindUdpTcpIn(ip
->ip_dst
, ip
->ip_src
,
347 ud
->uh_dport
, ud
->uh_sport
,
349 else if (ip
->ip_p
== IPPROTO_TCP
)
350 link
= FindUdpTcpIn(ip
->ip_dst
, ip
->ip_src
,
351 tc
->th_dport
, tc
->th_sport
,
353 else if (ip
->ip_p
== IPPROTO_ICMP
) {
354 if (ic2
->icmp_type
== ICMP_ECHO
|| ic2
->icmp_type
== ICMP_TSTAMP
)
355 link
= FindIcmpIn(ip
->ip_dst
, ip
->ip_src
, ic2
->icmp_id
, 0);
363 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(link
);
370 original_port
= GetOriginalPort(link
);
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 (u_short
*) &original_address
,
386 (u_short
*) &pip
->ip_dst
,
388 pip
->ip_dst
= original_address
;
390 /* Un-alias address and port number of original IP packet
391 fragment contained in ICMP data section */
392 ip
->ip_src
= original_address
;
393 ud
->uh_sport
= original_port
;
395 else if (ip
->ip_p
== IPPROTO_ICMP
)
397 int accumulate
, accumulate2
;
398 struct in_addr original_address
;
401 original_address
= GetOriginalAddress(link
);
402 original_id
= GetOriginalPort(link
);
404 /* Adjust ICMP checksum */
405 accumulate
= twowords(&ip
->ip_src
);
406 accumulate
-= twowords(&original_address
);
407 accumulate
+= ic2
->icmp_id
;
408 accumulate
-= original_id
;
409 accumulate2
= accumulate
;
410 accumulate2
+= ip
->ip_sum
;
411 ADJUST_CHECKSUM(accumulate
, ip
->ip_sum
);
412 accumulate2
-= ip
->ip_sum
;
413 ADJUST_CHECKSUM(accumulate2
, ic
->icmp_cksum
);
415 /* Un-alias address in IP header */
416 DifferentialChecksum(&pip
->ip_sum
,
417 (u_short
*) &original_address
,
418 (u_short
*) &pip
->ip_dst
,
420 pip
->ip_dst
= original_address
;
422 /* Un-alias address of original IP packet and sequence number of
423 embedded ICMP datagram */
424 ip
->ip_src
= original_address
;
425 ic2
->icmp_id
= original_id
;
427 return(PKT_ALIAS_OK
);
429 return(PKT_ALIAS_IGNORED
);
434 IcmpAliasIn(struct ip
*pip
)
439 /* Return if proxy-only mode is enabled */
440 if (packetAliasMode
& PKT_ALIAS_PROXY_ONLY
)
443 ic
= (struct icmp
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
445 iresult
= PKT_ALIAS_IGNORED
;
446 switch (ic
->icmp_type
)
449 case ICMP_TSTAMPREPLY
:
450 if (ic
->icmp_code
== 0)
452 iresult
= IcmpAliasIn1(pip
);
456 case ICMP_SOURCEQUENCH
:
459 iresult
= IcmpAliasIn2(pip
);
463 iresult
= IcmpAliasIn1(pip
);
471 IcmpAliasOut1(struct ip
*pip
)
474 Alias outgoing echo and timestamp requests.
475 De-alias outgoing echo and timestamp replies.
477 struct alias_link
*link
;
480 ic
= (struct icmp
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
482 /* Save overwritten data for when echo packet returns */
483 link
= FindIcmpOut(pip
->ip_src
, pip
->ip_dst
, ic
->icmp_id
, 1);
489 alias_id
= GetAliasPort(link
);
491 /* Since data field is being modified, adjust ICMP checksum */
492 accumulate
= ic
->icmp_id
;
493 accumulate
-= alias_id
;
494 ADJUST_CHECKSUM(accumulate
, ic
->icmp_cksum
);
496 /* Alias sequence number */
497 ic
->icmp_id
= alias_id
;
499 /* Change source address */
501 struct in_addr alias_address
;
503 alias_address
= GetAliasAddress(link
);
504 DifferentialChecksum(&pip
->ip_sum
,
505 (u_short
*) &alias_address
,
506 (u_short
*) &pip
->ip_src
,
508 pip
->ip_src
= alias_address
;
511 return(PKT_ALIAS_OK
);
513 return(PKT_ALIAS_IGNORED
);
518 IcmpAliasOut2(struct ip
*pip
)
521 Alias outgoing ICMP error messages containing
522 IP header and first 64 bits of datagram.
525 struct icmp
*ic
, *ic2
;
528 struct alias_link
*link
;
530 ic
= (struct icmp
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
533 ud
= (struct udphdr
*) ((char *) ip
+ (ip
->ip_hl
<<2));
534 tc
= (struct tcphdr
*) ud
;
535 ic2
= (struct icmp
*) ud
;
537 if (ip
->ip_p
== IPPROTO_UDP
)
538 link
= FindUdpTcpOut(ip
->ip_dst
, ip
->ip_src
,
539 ud
->uh_dport
, ud
->uh_sport
,
541 else if (ip
->ip_p
== IPPROTO_TCP
)
542 link
= FindUdpTcpOut(ip
->ip_dst
, ip
->ip_src
,
543 tc
->th_dport
, tc
->th_sport
,
545 else if (ip
->ip_p
== IPPROTO_ICMP
) {
546 if (ic2
->icmp_type
== ICMP_ECHO
|| ic2
->icmp_type
== ICMP_TSTAMP
)
547 link
= FindIcmpOut(ip
->ip_dst
, ip
->ip_src
, ic2
->icmp_id
, 0);
555 if (ip
->ip_p
== IPPROTO_UDP
|| ip
->ip_p
== IPPROTO_TCP
)
558 struct in_addr alias_address
;
561 alias_address
= GetAliasAddress(link
);
562 alias_port
= GetAliasPort(link
);
564 /* Adjust ICMP checksum */
565 accumulate
= twowords(&ip
->ip_dst
);
566 accumulate
-= twowords(&alias_address
);
567 accumulate
+= ud
->uh_dport
;
568 accumulate
-= alias_port
;
569 ADJUST_CHECKSUM(accumulate
, ic
->icmp_cksum
);
572 * Alias address in IP header if it comes from the host
573 * the original TCP/UDP packet was destined for.
575 if (pip
->ip_src
.s_addr
== ip
->ip_dst
.s_addr
) {
576 DifferentialChecksum(&pip
->ip_sum
,
577 (u_short
*) &alias_address
,
578 (u_short
*) &pip
->ip_src
,
580 pip
->ip_src
= alias_address
;
583 /* Alias address and port number of original IP packet
584 fragment contained in ICMP data section */
585 ip
->ip_dst
= alias_address
;
586 ud
->uh_dport
= alias_port
;
588 else if (ip
->ip_p
== IPPROTO_ICMP
)
591 struct in_addr alias_address
;
594 alias_address
= GetAliasAddress(link
);
595 alias_id
= GetAliasPort(link
);
597 /* Adjust ICMP checksum */
598 accumulate
= twowords(&ip
->ip_dst
);
599 accumulate
-= twowords(&alias_address
);
600 accumulate
+= ic2
->icmp_id
;
601 accumulate
-= alias_id
;
602 ADJUST_CHECKSUM(accumulate
, ic
->icmp_cksum
);
605 * Alias address in IP header if it comes from the host
606 * the original ICMP message was destined for.
608 if (pip
->ip_src
.s_addr
== ip
->ip_dst
.s_addr
) {
609 DifferentialChecksum(&pip
->ip_sum
,
610 (u_short
*) &alias_address
,
611 (u_short
*) &pip
->ip_src
,
613 pip
->ip_src
= alias_address
;
616 /* Alias address of original IP packet and sequence number of
617 embedded ICMP datagram */
618 ip
->ip_dst
= alias_address
;
619 ic2
->icmp_id
= alias_id
;
621 return(PKT_ALIAS_OK
);
623 return(PKT_ALIAS_IGNORED
);
628 IcmpAliasOut(struct ip
*pip
)
633 /* Return if proxy-only mode is enabled */
634 if (packetAliasMode
& PKT_ALIAS_PROXY_ONLY
)
637 ic
= (struct icmp
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
639 iresult
= PKT_ALIAS_IGNORED
;
640 switch (ic
->icmp_type
)
644 if (ic
->icmp_code
== 0)
646 iresult
= IcmpAliasOut1(pip
);
650 case ICMP_SOURCEQUENCH
:
653 iresult
= IcmpAliasOut2(pip
);
656 case ICMP_TSTAMPREPLY
:
657 iresult
= IcmpAliasOut1(pip
);
665 ProtoAliasIn(struct ip
*pip
)
668 Handle incoming IP packets. The
669 only thing which is done in this case is to alias
670 the dest IP address of the packet to our inside
673 struct alias_link
*link
;
675 /* Return if proxy-only mode is enabled */
676 if (packetAliasMode
& PKT_ALIAS_PROXY_ONLY
)
679 link
= FindProtoIn(pip
->ip_src
, pip
->ip_dst
, pip
->ip_p
);
682 struct in_addr original_address
;
684 original_address
= GetOriginalAddress(link
);
686 /* Restore original IP address */
687 DifferentialChecksum(&pip
->ip_sum
,
688 (u_short
*) &original_address
,
689 (u_short
*) &pip
->ip_dst
,
691 pip
->ip_dst
= original_address
;
693 return(PKT_ALIAS_OK
);
695 return(PKT_ALIAS_IGNORED
);
700 ProtoAliasOut(struct ip
*pip
)
703 Handle outgoing IP packets. The
704 only thing which is done in this case is to alias
705 the source IP address of the packet.
707 struct alias_link
*link
;
709 /* Return if proxy-only mode is enabled */
710 if (packetAliasMode
& PKT_ALIAS_PROXY_ONLY
)
713 link
= FindProtoOut(pip
->ip_src
, pip
->ip_dst
, pip
->ip_p
);
716 struct in_addr alias_address
;
718 alias_address
= GetAliasAddress(link
);
720 /* Change source address */
721 DifferentialChecksum(&pip
->ip_sum
,
722 (u_short
*) &alias_address
,
723 (u_short
*) &pip
->ip_src
,
725 pip
->ip_src
= alias_address
;
727 return(PKT_ALIAS_OK
);
729 return(PKT_ALIAS_IGNORED
);
734 UdpAliasIn(struct ip
*pip
)
737 struct alias_link
*link
;
739 /* Return if proxy-only mode is enabled */
740 if (packetAliasMode
& PKT_ALIAS_PROXY_ONLY
)
743 ud
= (struct udphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
745 link
= FindUdpTcpIn(pip
->ip_src
, pip
->ip_dst
,
746 ud
->uh_sport
, ud
->uh_dport
,
750 struct in_addr alias_address
;
751 struct in_addr original_address
;
756 alias_address
= GetAliasAddress(link
);
757 original_address
= GetOriginalAddress(link
);
758 alias_port
= ud
->uh_dport
;
759 ud
->uh_dport
= GetOriginalPort(link
);
761 /* Special processing for IP encoding protocols */
762 if (ntohs(ud
->uh_dport
) == CUSEEME_PORT_NUMBER
)
763 AliasHandleCUSeeMeIn(pip
, original_address
);
764 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
765 else if (ntohs(ud
->uh_dport
) == NETBIOS_DGM_PORT_NUMBER
766 || ntohs(ud
->uh_sport
) == NETBIOS_DGM_PORT_NUMBER
)
767 r
= AliasHandleUdpNbt(pip
, link
, &original_address
, ud
->uh_dport
);
768 else if (ntohs(ud
->uh_dport
) == NETBIOS_NS_PORT_NUMBER
769 || ntohs(ud
->uh_sport
) == NETBIOS_NS_PORT_NUMBER
)
770 r
= AliasHandleUdpNbtNS(pip
, link
, &alias_address
, &alias_port
,
771 &original_address
, &ud
->uh_dport
);
773 /* If UDP checksum is not zero, then adjust since destination port */
774 /* is being unaliased and destination address is being altered. */
777 accumulate
= alias_port
;
778 accumulate
-= ud
->uh_dport
;
779 accumulate
+= twowords(&alias_address
);
780 accumulate
-= twowords(&original_address
);
781 ADJUST_CHECKSUM(accumulate
, ud
->uh_sum
);
784 /* Restore original IP address */
785 DifferentialChecksum(&pip
->ip_sum
,
786 (u_short
*) &original_address
,
787 (u_short
*) &pip
->ip_dst
,
789 pip
->ip_dst
= original_address
;
792 * If we cannot figure out the packet, ignore it.
795 return(PKT_ALIAS_IGNORED
);
797 return(PKT_ALIAS_OK
);
799 return(PKT_ALIAS_IGNORED
);
803 UdpAliasOut(struct ip
*pip
)
806 struct alias_link
*link
;
808 /* Return if proxy-only mode is enabled */
809 if (packetAliasMode
& PKT_ALIAS_PROXY_ONLY
)
812 ud
= (struct udphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
814 link
= FindUdpTcpOut(pip
->ip_src
, pip
->ip_dst
,
815 ud
->uh_sport
, ud
->uh_dport
,
820 struct in_addr alias_address
;
822 alias_address
= GetAliasAddress(link
);
823 alias_port
= GetAliasPort(link
);
825 /* Special processing for IP encoding protocols */
826 if (ntohs(ud
->uh_dport
) == CUSEEME_PORT_NUMBER
)
827 AliasHandleCUSeeMeOut(pip
, link
);
828 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
829 else if (ntohs(ud
->uh_dport
) == NETBIOS_DGM_PORT_NUMBER
830 || ntohs(ud
->uh_sport
) == NETBIOS_DGM_PORT_NUMBER
)
831 AliasHandleUdpNbt(pip
, link
, &alias_address
, alias_port
);
832 else if (ntohs(ud
->uh_dport
) == NETBIOS_NS_PORT_NUMBER
833 || ntohs(ud
->uh_sport
) == NETBIOS_NS_PORT_NUMBER
)
834 AliasHandleUdpNbtNS(pip
, link
, &pip
->ip_src
, &ud
->uh_sport
,
835 &alias_address
, &alias_port
);
837 * We don't know in advance what TID the TFTP server will choose,
838 * so we create a wilcard link (destination port is unspecified)
839 * that will match any TID from a given destination.
841 else if (ntohs(ud
->uh_dport
) == TFTP_PORT_NUMBER
)
842 FindRtspOut(pip
->ip_src
, pip
->ip_dst
,
843 ud
->uh_sport
, alias_port
, IPPROTO_UDP
);
845 /* If UDP checksum is not zero, adjust since source port is */
846 /* being aliased and source address is being altered */
851 accumulate
= ud
->uh_sport
;
852 accumulate
-= alias_port
;
853 accumulate
+= twowords(&pip
->ip_src
);
854 accumulate
-= twowords(&alias_address
);
855 ADJUST_CHECKSUM(accumulate
, ud
->uh_sum
);
858 /* Put alias port in UDP header */
859 ud
->uh_sport
= alias_port
;
861 /* Change source address */
862 DifferentialChecksum(&pip
->ip_sum
,
863 (u_short
*) &alias_address
,
864 (u_short
*) &pip
->ip_src
,
866 pip
->ip_src
= alias_address
;
868 return(PKT_ALIAS_OK
);
870 return(PKT_ALIAS_IGNORED
);
876 TcpAliasIn(struct ip
*pip
)
879 struct alias_link
*link
;
881 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
883 link
= FindUdpTcpIn(pip
->ip_src
, pip
->ip_dst
,
884 tc
->th_sport
, tc
->th_dport
,
886 !(packetAliasMode
& PKT_ALIAS_PROXY_ONLY
));
889 struct in_addr alias_address
;
890 struct in_addr original_address
;
891 struct in_addr proxy_address
;
896 /* Special processing for IP encoding protocols */
897 if (ntohs(tc
->th_dport
) == PPTP_CONTROL_PORT_NUMBER
898 || ntohs(tc
->th_sport
) == PPTP_CONTROL_PORT_NUMBER
)
899 AliasHandlePptpIn(pip
, link
);
901 alias_address
= GetAliasAddress(link
);
902 original_address
= GetOriginalAddress(link
);
903 proxy_address
= GetProxyAddress(link
);
904 alias_port
= tc
->th_dport
;
905 tc
->th_dport
= GetOriginalPort(link
);
906 proxy_port
= GetProxyPort(link
);
908 /* Adjust TCP checksum since destination port is being unaliased */
909 /* and destination port is being altered. */
910 accumulate
= alias_port
;
911 accumulate
-= tc
->th_dport
;
912 accumulate
+= twowords(&alias_address
);
913 accumulate
-= twowords(&original_address
);
915 /* If this is a proxy, then modify the TCP source port and
916 checksum accumulation */
919 accumulate
+= tc
->th_sport
;
920 tc
->th_sport
= proxy_port
;
921 accumulate
-= tc
->th_sport
;
922 accumulate
+= twowords(&pip
->ip_src
);
923 accumulate
-= twowords(&proxy_address
);
926 /* See if ACK number needs to be modified */
927 if (GetAckModified(link
) == 1)
931 delta
= GetDeltaAckIn(pip
, link
);
934 accumulate
+= twowords(&tc
->th_ack
);
935 tc
->th_ack
= htonl(ntohl(tc
->th_ack
) - delta
);
936 accumulate
-= twowords(&tc
->th_ack
);
940 ADJUST_CHECKSUM(accumulate
, tc
->th_sum
);
942 /* Restore original IP address */
943 accumulate
= twowords(&pip
->ip_dst
);
944 pip
->ip_dst
= original_address
;
945 accumulate
-= twowords(&pip
->ip_dst
);
947 /* If this is a transparent proxy packet, then modify the source
949 if (proxy_address
.s_addr
!= 0)
951 accumulate
+= twowords(&pip
->ip_src
);
952 pip
->ip_src
= proxy_address
;
953 accumulate
-= twowords(&pip
->ip_src
);
956 ADJUST_CHECKSUM(accumulate
, pip
->ip_sum
);
958 /* Monitor TCP connection state */
959 TcpMonitorIn(pip
, link
);
961 return(PKT_ALIAS_OK
);
963 return(PKT_ALIAS_IGNORED
);
967 TcpAliasOut(struct ip
*pip
, int maxpacketsize
)
971 u_short proxy_server_port
;
972 struct in_addr dest_address
;
973 struct in_addr proxy_server_address
;
975 struct alias_link
*link
;
977 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
979 proxy_type
= ProxyCheck(pip
, &proxy_server_address
, &proxy_server_port
);
981 if (proxy_type
== 0 && (packetAliasMode
& PKT_ALIAS_PROXY_ONLY
))
984 /* If this is a transparent proxy, save original destination,
985 then alter the destination and adjust checksums */
986 dest_port
= tc
->th_dport
;
987 dest_address
= pip
->ip_dst
;
992 accumulate
= tc
->th_dport
;
993 tc
->th_dport
= proxy_server_port
;
994 accumulate
-= tc
->th_dport
;
995 accumulate
+= twowords(&pip
->ip_dst
);
996 accumulate
-= twowords(&proxy_server_address
);
997 ADJUST_CHECKSUM(accumulate
, tc
->th_sum
);
999 accumulate
= twowords(&pip
->ip_dst
);
1000 pip
->ip_dst
= proxy_server_address
;
1001 accumulate
-= twowords(&pip
->ip_dst
);
1002 ADJUST_CHECKSUM(accumulate
, pip
->ip_sum
);
1005 link
= FindUdpTcpOut(pip
->ip_src
, pip
->ip_dst
,
1006 tc
->th_sport
, tc
->th_dport
,
1011 struct in_addr alias_address
;
1014 /* Save original destination address, if this is a proxy packet.
1015 Also modify packet to include destination encoding. This may
1016 change the size of IP header. */
1017 if (proxy_type
!= 0)
1019 SetProxyPort(link
, dest_port
);
1020 SetProxyAddress(link
, dest_address
);
1021 ProxyModify(link
, pip
, maxpacketsize
, proxy_type
);
1022 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
1025 /* Get alias address and port */
1026 alias_port
= GetAliasPort(link
);
1027 alias_address
= GetAliasAddress(link
);
1029 /* Monitor TCP connection state */
1030 TcpMonitorOut(pip
, link
);
1032 /* Special processing for IP encoding protocols */
1033 if (ntohs(tc
->th_dport
) == FTP_CONTROL_PORT_NUMBER
1034 || ntohs(tc
->th_sport
) == FTP_CONTROL_PORT_NUMBER
)
1035 AliasHandleFtpOut(pip
, link
, maxpacketsize
);
1036 else if (ntohs(tc
->th_dport
) == IRC_CONTROL_PORT_NUMBER_1
1037 || ntohs(tc
->th_dport
) == IRC_CONTROL_PORT_NUMBER_2
)
1038 AliasHandleIrcOut(pip
, link
, maxpacketsize
);
1039 else if (ntohs(tc
->th_dport
) == RTSP_CONTROL_PORT_NUMBER_1
1040 || ntohs(tc
->th_sport
) == RTSP_CONTROL_PORT_NUMBER_1
1041 || ntohs(tc
->th_dport
) == RTSP_CONTROL_PORT_NUMBER_2
1042 || ntohs(tc
->th_sport
) == RTSP_CONTROL_PORT_NUMBER_2
)
1043 AliasHandleRtspOut(pip
, link
, maxpacketsize
);
1044 else if (ntohs(tc
->th_dport
) == PPTP_CONTROL_PORT_NUMBER
1045 || ntohs(tc
->th_sport
) == PPTP_CONTROL_PORT_NUMBER
)
1046 AliasHandlePptpOut(pip
, link
);
1048 /* Adjust TCP checksum since source port is being aliased */
1049 /* and source address is being altered */
1050 accumulate
= tc
->th_sport
;
1051 tc
->th_sport
= alias_port
;
1052 accumulate
-= tc
->th_sport
;
1053 accumulate
+= twowords(&pip
->ip_src
);
1054 accumulate
-= twowords(&alias_address
);
1056 /* Modify sequence number if necessary */
1057 if (GetAckModified(link
) == 1)
1061 delta
= GetDeltaSeqOut(pip
, link
);
1064 accumulate
+= twowords(&tc
->th_seq
);
1065 tc
->th_seq
= htonl(ntohl(tc
->th_seq
) + delta
);
1066 accumulate
-= twowords(&tc
->th_seq
);
1070 ADJUST_CHECKSUM(accumulate
, tc
->th_sum
);
1072 /* Change source address */
1073 accumulate
= twowords(&pip
->ip_src
);
1074 pip
->ip_src
= alias_address
;
1075 accumulate
-= twowords(&pip
->ip_src
);
1076 ADJUST_CHECKSUM(accumulate
, pip
->ip_sum
);
1078 return(PKT_ALIAS_OK
);
1080 return(PKT_ALIAS_IGNORED
);
1086 /* Fragment Handling
1091 The packet aliasing module has a limited ability for handling IP
1092 fragments. If the ICMP, TCP or UDP header is in the first fragment
1093 received, then the ID number of the IP packet is saved, and other
1094 fragments are identified according to their ID number and IP address
1095 they were sent from. Pointers to unresolved fragments can also be
1096 saved and recalled when a header fragment is seen.
1099 /* Local prototypes */
1100 static int FragmentIn(struct ip
*);
1101 static int FragmentOut(struct ip
*);
1105 FragmentIn(struct ip
*pip
)
1107 struct alias_link
*link
;
1109 link
= FindFragmentIn2(pip
->ip_src
, pip
->ip_dst
, pip
->ip_id
);
1112 struct in_addr original_address
;
1114 GetFragmentAddr(link
, &original_address
);
1115 DifferentialChecksum(&pip
->ip_sum
,
1116 (u_short
*) &original_address
,
1117 (u_short
*) &pip
->ip_dst
,
1119 pip
->ip_dst
= original_address
;
1121 return(PKT_ALIAS_OK
);
1123 return(PKT_ALIAS_UNRESOLVED_FRAGMENT
);
1128 FragmentOut(struct ip
*pip
)
1130 struct in_addr alias_address
;
1132 alias_address
= FindAliasAddress(pip
->ip_src
);
1133 DifferentialChecksum(&pip
->ip_sum
,
1134 (u_short
*) &alias_address
,
1135 (u_short
*) &pip
->ip_src
,
1137 pip
->ip_src
= alias_address
;
1139 return(PKT_ALIAS_OK
);
1147 /* Outside World Access
1149 PacketAliasSaveFragment()
1150 PacketAliasGetFragment()
1151 PacketAliasFragmentIn()
1156 (prototypes in alias.h)
1161 PacketAliasSaveFragment(char *ptr
)
1164 struct alias_link
*link
;
1167 pip
= (struct ip
*) ptr
;
1168 link
= AddFragmentPtrLink(pip
->ip_src
, pip
->ip_id
);
1169 iresult
= PKT_ALIAS_ERROR
;
1172 SetFragmentPtr(link
, ptr
);
1173 iresult
= PKT_ALIAS_OK
;
1180 PacketAliasGetFragment(char *ptr
)
1182 struct alias_link
*link
;
1186 pip
= (struct ip
*) ptr
;
1187 link
= FindFragmentPtr(pip
->ip_src
, pip
->ip_id
);
1190 GetFragmentPtr(link
, &fptr
);
1191 SetFragmentPtr(link
, NULL
);
1192 SetExpire(link
, 0); /* Deletes link */
1204 PacketAliasFragmentIn(char *ptr
, /* Points to correctly de-aliased
1206 char *ptr_fragment
/* Points to fragment which must
1213 pip
= (struct ip
*) ptr
;
1214 fpip
= (struct ip
*) ptr_fragment
;
1216 DifferentialChecksum(&fpip
->ip_sum
,
1217 (u_short
*) &pip
->ip_dst
,
1218 (u_short
*) &fpip
->ip_dst
,
1220 fpip
->ip_dst
= pip
->ip_dst
;
1225 PacketAliasIn(char *ptr
, int maxpacketsize
)
1227 struct in_addr alias_addr
;
1231 if (packetAliasMode
& PKT_ALIAS_REVERSE
) {
1232 packetAliasMode
&= ~PKT_ALIAS_REVERSE
;
1233 iresult
= PacketAliasOut(ptr
, maxpacketsize
);
1234 packetAliasMode
|= PKT_ALIAS_REVERSE
;
1239 ClearCheckNewLink();
1240 pip
= (struct ip
*) ptr
;
1241 alias_addr
= pip
->ip_dst
;
1243 /* Defense against mangled packets */
1244 if (ntohs(pip
->ip_len
) > maxpacketsize
1245 || (pip
->ip_hl
<<2) > maxpacketsize
)
1246 return PKT_ALIAS_IGNORED
;
1248 iresult
= PKT_ALIAS_IGNORED
;
1249 if ( (ntohs(pip
->ip_off
) & IP_OFFMASK
) == 0 )
1254 iresult
= IcmpAliasIn(pip
);
1257 iresult
= UdpAliasIn(pip
);
1260 iresult
= TcpAliasIn(pip
);
1263 if (packetAliasMode
& PKT_ALIAS_PROXY_ONLY
||
1264 AliasHandlePptpGreIn(pip
) == 0)
1265 iresult
= PKT_ALIAS_OK
;
1267 iresult
= ProtoAliasIn(pip
);
1270 iresult
= ProtoAliasIn(pip
);
1274 if (ntohs(pip
->ip_off
) & IP_MF
)
1276 struct alias_link
*link
;
1278 link
= FindFragmentIn1(pip
->ip_src
, alias_addr
, pip
->ip_id
);
1281 iresult
= PKT_ALIAS_FOUND_HEADER_FRAGMENT
;
1282 SetFragmentAddr(link
, pip
->ip_dst
);
1286 iresult
= PKT_ALIAS_ERROR
;
1292 iresult
= FragmentIn(pip
);
1300 /* Unregistered address ranges */
1302 /* 10.0.0.0 -> 10.255.255.255 */
1303 #define UNREG_ADDR_A_LOWER 0x0a000000
1304 #define UNREG_ADDR_A_UPPER 0x0affffff
1306 /* 172.16.0.0 -> 172.31.255.255 */
1307 #define UNREG_ADDR_B_LOWER 0xac100000
1308 #define UNREG_ADDR_B_UPPER 0xac1fffff
1310 /* 192.168.0.0 -> 192.168.255.255 */
1311 #define UNREG_ADDR_C_LOWER 0xc0a80000
1312 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1315 PacketAliasOut(char *ptr
, /* valid IP packet */
1316 int maxpacketsize
/* How much the packet data may grow
1317 (FTP and IRC inline changes) */
1321 struct in_addr addr_save
;
1324 if (packetAliasMode
& PKT_ALIAS_REVERSE
) {
1325 packetAliasMode
&= ~PKT_ALIAS_REVERSE
;
1326 iresult
= PacketAliasIn(ptr
, maxpacketsize
);
1327 packetAliasMode
|= PKT_ALIAS_REVERSE
;
1332 ClearCheckNewLink();
1333 pip
= (struct ip
*) ptr
;
1335 /* Defense against mangled packets */
1336 if (ntohs(pip
->ip_len
) > maxpacketsize
1337 || (pip
->ip_hl
<<2) > maxpacketsize
)
1338 return PKT_ALIAS_IGNORED
;
1340 addr_save
= GetDefaultAliasAddress();
1341 if (packetAliasMode
& PKT_ALIAS_UNREGISTERED_ONLY
)
1347 addr
= ntohl(pip
->ip_src
.s_addr
);
1348 if (addr
>= UNREG_ADDR_C_LOWER
&& addr
<= UNREG_ADDR_C_UPPER
)
1350 else if (addr
>= UNREG_ADDR_B_LOWER
&& addr
<= UNREG_ADDR_B_UPPER
)
1352 else if (addr
>= UNREG_ADDR_A_LOWER
&& addr
<= UNREG_ADDR_A_UPPER
)
1357 SetDefaultAliasAddress(pip
->ip_src
);
1361 iresult
= PKT_ALIAS_IGNORED
;
1362 if ((ntohs(pip
->ip_off
) & IP_OFFMASK
) == 0)
1367 iresult
= IcmpAliasOut(pip
);
1370 iresult
= UdpAliasOut(pip
);
1373 iresult
= TcpAliasOut(pip
, maxpacketsize
);
1376 if (AliasHandlePptpGreOut(pip
) == 0)
1377 iresult
= PKT_ALIAS_OK
;
1379 iresult
= ProtoAliasOut(pip
);
1382 iresult
= ProtoAliasOut(pip
);
1388 iresult
= FragmentOut(pip
);
1391 SetDefaultAliasAddress(addr_save
);
1396 PacketUnaliasOut(char *ptr
, /* valid IP packet */
1397 int maxpacketsize
/* for error checking */
1404 struct alias_link
*link
;
1405 int iresult
= PKT_ALIAS_IGNORED
;
1407 pip
= (struct ip
*) ptr
;
1409 /* Defense against mangled packets */
1410 if (ntohs(pip
->ip_len
) > maxpacketsize
1411 || (pip
->ip_hl
<<2) > maxpacketsize
)
1414 ud
= (struct udphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
1415 tc
= (struct tcphdr
*) ud
;
1416 ic
= (struct icmp
*) ud
;
1419 if (pip
->ip_p
== IPPROTO_UDP
)
1420 link
= FindUdpTcpIn(pip
->ip_dst
, pip
->ip_src
,
1421 ud
->uh_dport
, ud
->uh_sport
,
1423 else if (pip
->ip_p
== IPPROTO_TCP
)
1424 link
= FindUdpTcpIn(pip
->ip_dst
, pip
->ip_src
,
1425 tc
->th_dport
, tc
->th_sport
,
1427 else if (pip
->ip_p
== IPPROTO_ICMP
)
1428 link
= FindIcmpIn(pip
->ip_dst
, pip
->ip_src
, ic
->icmp_id
, 0);
1432 /* Change it from an aliased packet to an unaliased packet */
1435 if (pip
->ip_p
== IPPROTO_UDP
|| pip
->ip_p
== IPPROTO_TCP
)
1438 struct in_addr original_address
;
1439 u_short original_port
;
1441 original_address
= GetOriginalAddress(link
);
1442 original_port
= GetOriginalPort(link
);
1444 /* Adjust TCP/UDP checksum */
1445 accumulate
= twowords(&pip
->ip_src
);
1446 accumulate
-= twowords(&original_address
);
1448 if (pip
->ip_p
== IPPROTO_UDP
) {
1449 accumulate
+= ud
->uh_sport
;
1450 accumulate
-= original_port
;
1451 ADJUST_CHECKSUM(accumulate
, ud
->uh_sum
);
1453 accumulate
+= tc
->th_sport
;
1454 accumulate
-= original_port
;
1455 ADJUST_CHECKSUM(accumulate
, tc
->th_sum
);
1458 /* Adjust IP checksum */
1459 DifferentialChecksum(&pip
->ip_sum
,
1460 (u_short
*) &original_address
,
1461 (u_short
*) &pip
->ip_src
,
1464 /* Un-alias source address and port number */
1465 pip
->ip_src
= original_address
;
1466 if (pip
->ip_p
== IPPROTO_UDP
)
1467 ud
->uh_sport
= original_port
;
1469 tc
->th_sport
= original_port
;
1471 iresult
= PKT_ALIAS_OK
;
1473 } else if (pip
->ip_p
== IPPROTO_ICMP
) {
1476 struct in_addr original_address
;
1477 u_short original_id
;
1479 original_address
= GetOriginalAddress(link
);
1480 original_id
= GetOriginalPort(link
);
1482 /* Adjust ICMP checksum */
1483 accumulate
= twowords(&pip
->ip_src
);
1484 accumulate
-= twowords(&original_address
);
1485 accumulate
+= ic
->icmp_id
;
1486 accumulate
-= original_id
;
1487 ADJUST_CHECKSUM(accumulate
, ic
->icmp_cksum
);
1489 /* Adjust IP checksum */
1490 DifferentialChecksum(&pip
->ip_sum
,
1491 (u_short
*) &original_address
,
1492 (u_short
*) &pip
->ip_src
,
1495 /* Un-alias source address and port number */
1496 pip
->ip_src
= original_address
;
1497 ic
->icmp_id
= original_id
;
1499 iresult
= PKT_ALIAS_OK
;