2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
31 Alias.c provides supervisory control for the functions of the
32 packet aliasing software. It consists of routines to monitor
33 TCP connection state, protocol-specific aliasing routines,
34 fragment handling and the following outside world functional
35 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
36 PacketAliasIn and PacketAliasOut.
38 The other C program files are briefly described. The data
39 structure framework which holds information needed to translate
40 packets is encapsulated in alias_db.c. Data is accessed by
41 function calls, so other segments of the program need not know
42 about the underlying data structures. Alias_ftp.c contains
43 special code for modifying the ftp PORT command used to establish
44 data connections, while alias_irc.c does the same for IRC
45 DCC. Alias_util.c contains a few utility routines.
47 Version 1.0 August, 1996 (cjm)
49 Version 1.1 August 20, 1996 (cjm)
50 PPP host accepts incoming connections for ports 0 to 1023.
51 (Gary Roberts pointed out the need to handle incoming
54 Version 1.2 September 7, 1996 (cjm)
55 Fragment handling error in alias_db.c corrected.
56 (Tom Torrance helped fix this problem.)
58 Version 1.4 September 16, 1996 (cjm)
59 - A more generalized method for handling incoming
60 connections, without the 0-1023 restriction, is
61 implemented in alias_db.c
62 - Improved ICMP support in alias.c. Traceroute
63 packet streams can now be correctly aliased.
64 - TCP connection closing logic simplified in
65 alias.c and now allows for additional 1 minute
66 "grace period" after FIN or RST is observed.
68 Version 1.5 September 17, 1996 (cjm)
69 Corrected error in handling incoming UDP packets with 0 checksum.
70 (Tom Torrance helped fix this problem.)
72 Version 1.6 September 18, 1996 (cjm)
73 Simplified ICMP aliasing scheme. Should now support
74 traceroute from Win95 as well as FreeBSD.
76 Version 1.7 January 9, 1997 (cjm)
77 - Out-of-order fragment handling.
78 - IP checksum error fixed for ftp transfers
80 - Integer return codes added to all
81 aliasing/de-aliasing functions.
82 - Some obsolete comments cleaned up.
83 - Differential checksum computations for
84 IP header (TCP, UDP and ICMP were already
87 Version 2.1 May 1997 (cjm)
88 - Added support for outgoing ICMP error
90 - Added two functions PacketAliasIn2()
91 and PacketAliasOut2() for dynamic address
92 control (e.g. round-robin allocation of
95 Version 2.2 July 1997 (cjm)
96 - Rationalized API function names to begin
98 - Eliminated PacketAliasIn2() and
99 PacketAliasOut2() as poorly conceived.
101 Version 2.3 Dec 1998 (dillon)
102 - Major bounds checking additions, see FreeBSD/CVS
104 Version 3.1 May, 2000 (salander)
105 - Added hooks to handle PPTP.
107 Version 3.2 July, 2000 (salander and satoh)
108 - Added PacketUnaliasOut routine.
109 - Added hooks to handle RTSP/RTP.
111 See HISTORY file for additional revisions.
115 #include <sys/param.h>
117 #include <sys/types.h>
121 #include <netinet/in_systm.h>
122 #include <netinet/in.h>
123 #include <netinet/ip.h>
124 #include <netinet/ip_icmp.h>
125 #include <netinet/tcp.h>
126 #include <netinet/udp.h>
129 #include <netinet/libalias/alias.h>
130 #include <netinet/libalias/alias_local.h>
133 #include "alias_local.h"
136 #define NETBIOS_NS_PORT_NUMBER 137
137 #define NETBIOS_DGM_PORT_NUMBER 138
138 #define FTP_CONTROL_PORT_NUMBER 21
139 #define IRC_CONTROL_PORT_NUMBER_1 6667
140 #define IRC_CONTROL_PORT_NUMBER_2 6668
141 #define CUSEEME_PORT_NUMBER 7648
142 #define RTSP_CONTROL_PORT_NUMBER_1 554
143 #define RTSP_CONTROL_PORT_NUMBER_2 7070
144 #define TFTP_PORT_NUMBER 69
145 #define PPTP_CONTROL_PORT_NUMBER 1723
152 #if BYTE_ORDER == LITTLE_ENDIAN
153 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
154 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
156 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
157 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
162 /* TCP Handling Routines
164 TcpMonitorIn() -- These routines monitor TCP connections, and
165 TcpMonitorOut() delete a link when a connection is closed.
167 These routines look for SYN, FIN and RST flags to determine when TCP
168 connections open and close. When a TCP connection closes, the data
169 structure containing packet aliasing information is deleted after
173 /* Local prototypes */
174 static void TcpMonitorIn(struct ip *, struct alias_link *);
176 static void TcpMonitorOut(struct ip *, struct alias_link *);
180 TcpMonitorIn(struct ip *pip, struct alias_link *lnk)
184 tc = (struct tcphdr *)ip_next(pip);
186 switch (GetStateIn(lnk)) {
187 case ALIAS_TCP_STATE_NOT_CONNECTED:
188 if (tc->th_flags & TH_RST)
189 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
190 else if (tc->th_flags & TH_SYN)
191 SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED);
193 case ALIAS_TCP_STATE_CONNECTED:
194 if (tc->th_flags & (TH_FIN | TH_RST))
195 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
201 TcpMonitorOut(struct ip *pip, struct alias_link *lnk)
205 tc = (struct tcphdr *)ip_next(pip);
207 switch (GetStateOut(lnk)) {
208 case ALIAS_TCP_STATE_NOT_CONNECTED:
209 if (tc->th_flags & TH_RST)
210 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
211 else if (tc->th_flags & TH_SYN)
212 SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED);
214 case ALIAS_TCP_STATE_CONNECTED:
215 if (tc->th_flags & (TH_FIN | TH_RST))
216 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
225 /* Protocol Specific Packet Aliasing Routines
227 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
228 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
229 ProtoAliasIn(), ProtoAliasOut()
230 UdpAliasIn(), UdpAliasOut()
231 TcpAliasIn(), TcpAliasOut()
233 These routines handle protocol specific details of packet aliasing.
234 One may observe a certain amount of repetitive arithmetic in these
235 functions, the purpose of which is to compute a revised checksum
236 without actually summing over the entire data packet, which could be
237 unnecessarily time consuming.
239 The purpose of the packet aliasing routines is to replace the source
240 address of the outgoing packet and then correctly put it back for
241 any incoming packets. For TCP and UDP, ports are also re-mapped.
243 For ICMP echo/timestamp requests and replies, the following scheme
244 is used: the ID number is replaced by an alias for the outgoing
247 ICMP error messages are handled by looking at the IP fragment
248 in the data section of the message.
250 For TCP and UDP protocols, a port number is chosen for an outgoing
251 packet, and then incoming packets are identified by IP address and
252 port numbers. For TCP packets, there is additional logic in the event
253 that sequence and ACK numbers have been altered (as in the case for
254 FTP data port commands).
256 The port numbers used by the packet aliasing module are not true
257 ports in the Unix sense. No sockets are actually bound to ports.
258 They are more correctly thought of as placeholders.
260 All packets go through the aliasing mechanism, whether they come from
261 the gateway machine or other machines on a local area network.
265 /* Local prototypes */
266 static int IcmpAliasIn1(struct libalias *, struct ip *);
267 static int IcmpAliasIn2(struct libalias *, struct ip *);
268 static int IcmpAliasIn(struct libalias *, struct ip *);
270 static int IcmpAliasOut1(struct libalias *, struct ip *, int create);
271 static int IcmpAliasOut2(struct libalias *, struct ip *);
272 static int IcmpAliasOut(struct libalias *, struct ip *, int create);
274 static int ProtoAliasIn(struct libalias *, struct ip *);
275 static int ProtoAliasOut(struct libalias *, struct ip *, int create);
277 static int UdpAliasIn(struct libalias *, struct ip *);
278 static int UdpAliasOut(struct libalias *, struct ip *, int create);
280 static int TcpAliasIn(struct libalias *, struct ip *);
281 static int TcpAliasOut(struct libalias *, struct ip *, int, int create);
285 IcmpAliasIn1(struct libalias *la, struct ip *pip)
288 De-alias incoming echo and timestamp replies.
289 Alias incoming echo and timestamp requests.
291 struct alias_link *lnk;
294 ic = (struct icmp *)ip_next(pip);
296 /* Get source address from ICMP data field and restore original data */
297 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
302 original_id = GetOriginalPort(lnk);
304 /* Adjust ICMP checksum */
305 accumulate = ic->icmp_id;
306 accumulate -= original_id;
307 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
309 /* Put original sequence number back in */
310 ic->icmp_id = original_id;
312 /* Put original address back into IP header */
314 struct in_addr original_address;
316 original_address = GetOriginalAddress(lnk);
317 DifferentialChecksum(&pip->ip_sum,
318 &original_address, &pip->ip_dst, 2);
319 pip->ip_dst = original_address;
322 return (PKT_ALIAS_OK);
324 return (PKT_ALIAS_IGNORED);
328 IcmpAliasIn2(struct libalias *la, struct ip *pip)
331 Alias incoming ICMP error messages containing
332 IP header and first 64 bits of datagram.
335 struct icmp *ic, *ic2;
338 struct alias_link *lnk;
340 ic = (struct icmp *)ip_next(pip);
343 ud = (struct udphdr *)ip_next(ip);
344 tc = (struct tcphdr *)ip_next(ip);
345 ic2 = (struct icmp *)ip_next(ip);
347 if (ip->ip_p == IPPROTO_UDP)
348 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
349 ud->uh_dport, ud->uh_sport,
351 else if (ip->ip_p == IPPROTO_TCP)
352 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
353 tc->th_dport, tc->th_sport,
355 else if (ip->ip_p == IPPROTO_ICMP) {
356 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
357 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
364 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
365 int accumulate, accumulate2;
366 struct in_addr original_address;
367 u_short original_port;
369 original_address = GetOriginalAddress(lnk);
370 original_port = GetOriginalPort(lnk);
372 /* Adjust ICMP checksum */
373 accumulate = twowords(&ip->ip_src);
374 accumulate -= twowords(&original_address);
375 accumulate += ud->uh_sport;
376 accumulate -= original_port;
377 accumulate2 = accumulate;
378 accumulate2 += ip->ip_sum;
379 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
380 accumulate2 -= ip->ip_sum;
381 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
383 /* Un-alias address in IP header */
384 DifferentialChecksum(&pip->ip_sum,
385 &original_address, &pip->ip_dst, 2);
386 pip->ip_dst = original_address;
388 /* Un-alias address and port number of original IP packet
389 fragment contained in ICMP data section */
390 ip->ip_src = original_address;
391 ud->uh_sport = original_port;
392 } else if (ip->ip_p == IPPROTO_ICMP) {
393 int accumulate, accumulate2;
394 struct in_addr original_address;
397 original_address = GetOriginalAddress(lnk);
398 original_id = GetOriginalPort(lnk);
400 /* Adjust ICMP checksum */
401 accumulate = twowords(&ip->ip_src);
402 accumulate -= twowords(&original_address);
403 accumulate += ic2->icmp_id;
404 accumulate -= original_id;
405 accumulate2 = accumulate;
406 accumulate2 += ip->ip_sum;
407 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
408 accumulate2 -= ip->ip_sum;
409 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
411 /* Un-alias address in IP header */
412 DifferentialChecksum(&pip->ip_sum,
413 &original_address, &pip->ip_dst, 2);
414 pip->ip_dst = original_address;
416 /* Un-alias address of original IP packet and sequence number of
417 embedded ICMP datagram */
418 ip->ip_src = original_address;
419 ic2->icmp_id = original_id;
421 return (PKT_ALIAS_OK);
423 return (PKT_ALIAS_IGNORED);
428 IcmpAliasIn(struct libalias *la, struct ip *pip)
433 /* Return if proxy-only mode is enabled */
434 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
435 return (PKT_ALIAS_OK);
437 ic = (struct icmp *)ip_next(pip);
439 iresult = PKT_ALIAS_IGNORED;
440 switch (ic->icmp_type) {
442 case ICMP_TSTAMPREPLY:
443 if (ic->icmp_code == 0) {
444 iresult = IcmpAliasIn1(la, pip);
448 case ICMP_SOURCEQUENCH:
451 iresult = IcmpAliasIn2(la, pip);
455 iresult = IcmpAliasIn1(la, pip);
463 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
466 Alias outgoing echo and timestamp requests.
467 De-alias outgoing echo and timestamp replies.
469 struct alias_link *lnk;
472 ic = (struct icmp *)ip_next(pip);
474 /* Save overwritten data for when echo packet returns */
475 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create);
480 alias_id = GetAliasPort(lnk);
482 /* Since data field is being modified, adjust ICMP checksum */
483 accumulate = ic->icmp_id;
484 accumulate -= alias_id;
485 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
487 /* Alias sequence number */
488 ic->icmp_id = alias_id;
490 /* Change source address */
492 struct in_addr alias_address;
494 alias_address = GetAliasAddress(lnk);
495 DifferentialChecksum(&pip->ip_sum,
496 &alias_address, &pip->ip_src, 2);
497 pip->ip_src = alias_address;
500 return (PKT_ALIAS_OK);
502 return (PKT_ALIAS_IGNORED);
507 IcmpAliasOut2(struct libalias *la, struct ip *pip)
510 Alias outgoing ICMP error messages containing
511 IP header and first 64 bits of datagram.
514 struct icmp *ic, *ic2;
517 struct alias_link *lnk;
519 ic = (struct icmp *)ip_next(pip);
522 ud = (struct udphdr *)ip_next(ip);
523 tc = (struct tcphdr *)ip_next(ip);
524 ic2 = (struct icmp *)ip_next(ip);
526 if (ip->ip_p == IPPROTO_UDP)
527 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
528 ud->uh_dport, ud->uh_sport,
530 else if (ip->ip_p == IPPROTO_TCP)
531 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
532 tc->th_dport, tc->th_sport,
534 else if (ip->ip_p == IPPROTO_ICMP) {
535 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
536 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
543 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
545 struct in_addr alias_address;
548 alias_address = GetAliasAddress(lnk);
549 alias_port = GetAliasPort(lnk);
551 /* Adjust ICMP checksum */
552 accumulate = twowords(&ip->ip_dst);
553 accumulate -= twowords(&alias_address);
554 accumulate += ud->uh_dport;
555 accumulate -= alias_port;
556 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
559 * Alias address in IP header if it comes from the host
560 * the original TCP/UDP packet was destined for.
562 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
563 DifferentialChecksum(&pip->ip_sum,
564 &alias_address, &pip->ip_src, 2);
565 pip->ip_src = alias_address;
567 /* Alias address and port number of original IP packet
568 fragment contained in ICMP data section */
569 ip->ip_dst = alias_address;
570 ud->uh_dport = alias_port;
571 } else if (ip->ip_p == IPPROTO_ICMP) {
573 struct in_addr alias_address;
576 alias_address = GetAliasAddress(lnk);
577 alias_id = GetAliasPort(lnk);
579 /* Adjust ICMP checksum */
580 accumulate = twowords(&ip->ip_dst);
581 accumulate -= twowords(&alias_address);
582 accumulate += ic2->icmp_id;
583 accumulate -= alias_id;
584 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
587 * Alias address in IP header if it comes from the host
588 * the original ICMP message was destined for.
590 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
591 DifferentialChecksum(&pip->ip_sum,
592 &alias_address, &pip->ip_src, 2);
593 pip->ip_src = alias_address;
595 /* Alias address of original IP packet and sequence number of
596 embedded ICMP datagram */
597 ip->ip_dst = alias_address;
598 ic2->icmp_id = alias_id;
600 return (PKT_ALIAS_OK);
602 return (PKT_ALIAS_IGNORED);
607 IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
614 /* Return if proxy-only mode is enabled */
615 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
616 return (PKT_ALIAS_OK);
618 ic = (struct icmp *)ip_next(pip);
620 iresult = PKT_ALIAS_IGNORED;
621 switch (ic->icmp_type) {
624 if (ic->icmp_code == 0) {
625 iresult = IcmpAliasOut1(la, pip, create);
629 case ICMP_SOURCEQUENCH:
632 iresult = IcmpAliasOut2(la, pip);
635 case ICMP_TSTAMPREPLY:
636 iresult = IcmpAliasOut1(la, pip, create);
644 ProtoAliasIn(struct libalias *la, struct ip *pip)
647 Handle incoming IP packets. The
648 only thing which is done in this case is to alias
649 the dest IP address of the packet to our inside
652 struct alias_link *lnk;
654 /* Return if proxy-only mode is enabled */
655 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
656 return (PKT_ALIAS_OK);
658 lnk = FindProtoIn(la, pip->ip_src, pip->ip_dst, pip->ip_p);
660 struct in_addr original_address;
662 original_address = GetOriginalAddress(lnk);
664 /* Restore original IP address */
665 DifferentialChecksum(&pip->ip_sum,
666 &original_address, &pip->ip_dst, 2);
667 pip->ip_dst = original_address;
669 return (PKT_ALIAS_OK);
671 return (PKT_ALIAS_IGNORED);
676 ProtoAliasOut(struct libalias *la, struct ip *pip, int create)
679 Handle outgoing IP packets. The
680 only thing which is done in this case is to alias
681 the source IP address of the packet.
683 struct alias_link *lnk;
687 /* Return if proxy-only mode is enabled */
688 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
689 return (PKT_ALIAS_OK);
691 lnk = FindProtoOut(la, pip->ip_src, pip->ip_dst, pip->ip_p);
693 struct in_addr alias_address;
695 alias_address = GetAliasAddress(lnk);
697 /* Change source address */
698 DifferentialChecksum(&pip->ip_sum,
699 &alias_address, &pip->ip_src, 2);
700 pip->ip_src = alias_address;
702 return (PKT_ALIAS_OK);
704 return (PKT_ALIAS_IGNORED);
709 UdpAliasIn(struct libalias *la, struct ip *pip)
712 struct alias_link *lnk;
714 /* Return if proxy-only mode is enabled */
715 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
716 return (PKT_ALIAS_OK);
718 ud = (struct udphdr *)ip_next(pip);
720 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
721 ud->uh_sport, ud->uh_dport,
724 struct in_addr alias_address;
725 struct in_addr original_address;
730 alias_address = GetAliasAddress(lnk);
731 original_address = GetOriginalAddress(lnk);
732 alias_port = ud->uh_dport;
733 ud->uh_dport = GetOriginalPort(lnk);
735 /* Special processing for IP encoding protocols */
736 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
737 AliasHandleCUSeeMeIn(la, pip, original_address);
738 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
739 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
740 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
741 r = AliasHandleUdpNbt(la, pip, lnk, &original_address, ud->uh_dport);
742 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
743 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
744 r = AliasHandleUdpNbtNS(la, pip, lnk, &alias_address, &alias_port,
745 &original_address, &ud->uh_dport);
747 /* If UDP checksum is not zero, then adjust since destination port */
748 /* is being unaliased and destination address is being altered. */
749 if (ud->uh_sum != 0) {
750 accumulate = alias_port;
751 accumulate -= ud->uh_dport;
752 accumulate += twowords(&alias_address);
753 accumulate -= twowords(&original_address);
754 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
756 /* Restore original IP address */
757 DifferentialChecksum(&pip->ip_sum,
758 &original_address, &pip->ip_dst, 2);
759 pip->ip_dst = original_address;
762 * If we cannot figure out the packet, ignore it.
765 return (PKT_ALIAS_IGNORED);
767 return (PKT_ALIAS_OK);
769 return (PKT_ALIAS_IGNORED);
773 UdpAliasOut(struct libalias *la, struct ip *pip, int create)
776 struct alias_link *lnk;
778 /* Return if proxy-only mode is enabled */
779 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
780 return (PKT_ALIAS_OK);
782 ud = (struct udphdr *)ip_next(pip);
784 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
785 ud->uh_sport, ud->uh_dport,
786 IPPROTO_UDP, create);
789 struct in_addr alias_address;
791 alias_address = GetAliasAddress(lnk);
792 alias_port = GetAliasPort(lnk);
794 /* Special processing for IP encoding protocols */
795 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
796 AliasHandleCUSeeMeOut(la, pip, lnk);
797 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
798 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
799 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
800 AliasHandleUdpNbt(la, pip, lnk, &alias_address, alias_port);
801 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
802 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
803 AliasHandleUdpNbtNS(la, pip, lnk, &pip->ip_src, &ud->uh_sport,
804 &alias_address, &alias_port);
806 * We don't know in advance what TID the TFTP server will choose,
807 * so we create a wilcard link (destination port is unspecified)
808 * that will match any TID from a given destination.
810 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
811 FindRtspOut(la, pip->ip_src, pip->ip_dst,
812 ud->uh_sport, alias_port, IPPROTO_UDP);
814 /* If UDP checksum is not zero, adjust since source port is */
815 /* being aliased and source address is being altered */
816 if (ud->uh_sum != 0) {
819 accumulate = ud->uh_sport;
820 accumulate -= alias_port;
821 accumulate += twowords(&pip->ip_src);
822 accumulate -= twowords(&alias_address);
823 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
825 /* Put alias port in UDP header */
826 ud->uh_sport = alias_port;
828 /* Change source address */
829 DifferentialChecksum(&pip->ip_sum,
830 &alias_address, &pip->ip_src, 2);
831 pip->ip_src = alias_address;
833 return (PKT_ALIAS_OK);
835 return (PKT_ALIAS_IGNORED);
841 TcpAliasIn(struct libalias *la, struct ip *pip)
844 struct alias_link *lnk;
846 tc = (struct tcphdr *)ip_next(pip);
848 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
849 tc->th_sport, tc->th_dport,
851 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
853 struct in_addr alias_address;
854 struct in_addr original_address;
855 struct in_addr proxy_address;
860 /* Special processing for IP encoding protocols */
861 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
862 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
863 AliasHandlePptpIn(la, pip, lnk);
864 else if (la->skinnyPort != 0 && (ntohs(tc->th_dport) == la->skinnyPort
865 || ntohs(tc->th_sport) == la->skinnyPort))
866 AliasHandleSkinny(la, pip, lnk);
868 alias_address = GetAliasAddress(lnk);
869 original_address = GetOriginalAddress(lnk);
870 proxy_address = GetProxyAddress(lnk);
871 alias_port = tc->th_dport;
872 tc->th_dport = GetOriginalPort(lnk);
873 proxy_port = GetProxyPort(lnk);
875 /* Adjust TCP checksum since destination port is being unaliased */
876 /* and destination port is being altered. */
877 accumulate = alias_port;
878 accumulate -= tc->th_dport;
879 accumulate += twowords(&alias_address);
880 accumulate -= twowords(&original_address);
882 /* If this is a proxy, then modify the TCP source port and
883 checksum accumulation */
884 if (proxy_port != 0) {
885 accumulate += tc->th_sport;
886 tc->th_sport = proxy_port;
887 accumulate -= tc->th_sport;
888 accumulate += twowords(&pip->ip_src);
889 accumulate -= twowords(&proxy_address);
891 /* See if ACK number needs to be modified */
892 if (GetAckModified(lnk) == 1) {
895 delta = GetDeltaAckIn(pip, lnk);
897 accumulate += twowords(&tc->th_ack);
898 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
899 accumulate -= twowords(&tc->th_ack);
902 ADJUST_CHECKSUM(accumulate, tc->th_sum);
904 /* Restore original IP address */
905 accumulate = twowords(&pip->ip_dst);
906 pip->ip_dst = original_address;
907 accumulate -= twowords(&pip->ip_dst);
909 /* If this is a transparent proxy packet, then modify the source
911 if (proxy_address.s_addr != 0) {
912 accumulate += twowords(&pip->ip_src);
913 pip->ip_src = proxy_address;
914 accumulate -= twowords(&pip->ip_src);
916 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
918 /* Monitor TCP connection state */
919 TcpMonitorIn(pip, lnk);
921 return (PKT_ALIAS_OK);
923 return (PKT_ALIAS_IGNORED);
927 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
931 u_short proxy_server_port;
932 struct in_addr dest_address;
933 struct in_addr proxy_server_address;
935 struct alias_link *lnk;
937 tc = (struct tcphdr *)ip_next(pip);
939 proxy_type = ProxyCheck(la, pip, &proxy_server_address, &proxy_server_port);
941 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
942 return (PKT_ALIAS_OK);
944 /* If this is a transparent proxy, save original destination,
945 then alter the destination and adjust checksums */
946 dest_port = tc->th_dport;
947 dest_address = pip->ip_dst;
948 if (proxy_type != 0) {
951 accumulate = tc->th_dport;
952 tc->th_dport = proxy_server_port;
953 accumulate -= tc->th_dport;
954 accumulate += twowords(&pip->ip_dst);
955 accumulate -= twowords(&proxy_server_address);
956 ADJUST_CHECKSUM(accumulate, tc->th_sum);
958 accumulate = twowords(&pip->ip_dst);
959 pip->ip_dst = proxy_server_address;
960 accumulate -= twowords(&pip->ip_dst);
961 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
963 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
964 tc->th_sport, tc->th_dport,
965 IPPROTO_TCP, create);
967 return (PKT_ALIAS_IGNORED);
970 struct in_addr alias_address;
973 /* Save original destination address, if this is a proxy packet.
974 Also modify packet to include destination encoding. This may
975 change the size of IP header. */
976 if (proxy_type != 0) {
977 SetProxyPort(lnk, dest_port);
978 SetProxyAddress(lnk, dest_address);
979 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
980 tc = (struct tcphdr *)ip_next(pip);
982 /* Get alias address and port */
983 alias_port = GetAliasPort(lnk);
984 alias_address = GetAliasAddress(lnk);
986 /* Monitor TCP connection state */
987 TcpMonitorOut(pip, lnk);
989 /* Special processing for IP encoding protocols */
990 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
991 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
992 AliasHandleFtpOut(la, pip, lnk, maxpacketsize);
993 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
994 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
995 AliasHandleIrcOut(la, pip, lnk, maxpacketsize);
996 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
997 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
998 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
999 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1000 AliasHandleRtspOut(la, pip, lnk, maxpacketsize);
1001 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1002 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1003 AliasHandlePptpOut(la, pip, lnk);
1004 else if (la->skinnyPort != 0 && (ntohs(tc->th_sport) == la->skinnyPort
1005 || ntohs(tc->th_dport) == la->skinnyPort))
1006 AliasHandleSkinny(la, pip, lnk);
1008 /* Adjust TCP checksum since source port is being aliased */
1009 /* and source address is being altered */
1010 accumulate = tc->th_sport;
1011 tc->th_sport = alias_port;
1012 accumulate -= tc->th_sport;
1013 accumulate += twowords(&pip->ip_src);
1014 accumulate -= twowords(&alias_address);
1016 /* Modify sequence number if necessary */
1017 if (GetAckModified(lnk) == 1) {
1020 delta = GetDeltaSeqOut(pip, lnk);
1022 accumulate += twowords(&tc->th_seq);
1023 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1024 accumulate -= twowords(&tc->th_seq);
1027 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1029 /* Change source address */
1030 accumulate = twowords(&pip->ip_src);
1031 pip->ip_src = alias_address;
1032 accumulate -= twowords(&pip->ip_src);
1033 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1035 return (PKT_ALIAS_OK);
1037 return (PKT_ALIAS_IGNORED);
1043 /* Fragment Handling
1048 The packet aliasing module has a limited ability for handling IP
1049 fragments. If the ICMP, TCP or UDP header is in the first fragment
1050 received, then the ID number of the IP packet is saved, and other
1051 fragments are identified according to their ID number and IP address
1052 they were sent from. Pointers to unresolved fragments can also be
1053 saved and recalled when a header fragment is seen.
1056 /* Local prototypes */
1057 static int FragmentIn(struct libalias *, struct ip *);
1058 static int FragmentOut(struct libalias *, struct ip *);
1062 FragmentIn(struct libalias *la, struct ip *pip)
1064 struct alias_link *lnk;
1066 lnk = FindFragmentIn2(la, pip->ip_src, pip->ip_dst, pip->ip_id);
1068 struct in_addr original_address;
1070 GetFragmentAddr(lnk, &original_address);
1071 DifferentialChecksum(&pip->ip_sum,
1072 &original_address, &pip->ip_dst, 2);
1073 pip->ip_dst = original_address;
1075 return (PKT_ALIAS_OK);
1077 return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1082 FragmentOut(struct libalias *la, struct ip *pip)
1084 struct in_addr alias_address;
1086 alias_address = FindAliasAddress(la, pip->ip_src);
1087 DifferentialChecksum(&pip->ip_sum,
1088 &alias_address, &pip->ip_src, 2);
1089 pip->ip_src = alias_address;
1091 return (PKT_ALIAS_OK);
1099 /* Outside World Access
1101 PacketAliasSaveFragment()
1102 PacketAliasGetFragment()
1103 PacketAliasFragmentIn()
1108 (prototypes in alias.h)
1113 LibAliasSaveFragment(struct libalias *la, char *ptr)
1116 struct alias_link *lnk;
1119 pip = (struct ip *)ptr;
1120 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1121 iresult = PKT_ALIAS_ERROR;
1123 SetFragmentPtr(lnk, ptr);
1124 iresult = PKT_ALIAS_OK;
1131 LibAliasGetFragment(struct libalias *la, char *ptr)
1133 struct alias_link *lnk;
1137 pip = (struct ip *)ptr;
1138 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1140 GetFragmentPtr(lnk, &fptr);
1141 SetFragmentPtr(lnk, NULL);
1142 SetExpire(lnk, 0); /* Deletes link */
1152 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
1155 char *ptr_fragment /* Points to fragment which must be
1163 pip = (struct ip *)ptr;
1164 fpip = (struct ip *)ptr_fragment;
1166 DifferentialChecksum(&fpip->ip_sum,
1167 &pip->ip_dst, &fpip->ip_dst, 2);
1168 fpip->ip_dst = pip->ip_dst;
1173 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1175 struct in_addr alias_addr;
1179 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1180 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1181 iresult = LibAliasOut(la, ptr, maxpacketsize);
1182 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1186 ClearCheckNewLink(la);
1187 pip = (struct ip *)ptr;
1188 alias_addr = pip->ip_dst;
1190 /* Defense against mangled packets */
1191 if (ntohs(pip->ip_len) > maxpacketsize
1192 || (pip->ip_hl << 2) > maxpacketsize)
1193 return (PKT_ALIAS_IGNORED);
1195 iresult = PKT_ALIAS_IGNORED;
1196 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1197 switch (pip->ip_p) {
1199 iresult = IcmpAliasIn(la, pip);
1202 iresult = UdpAliasIn(la, pip);
1205 iresult = TcpAliasIn(la, pip);
1208 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1209 AliasHandlePptpGreIn(la, pip) == 0)
1210 iresult = PKT_ALIAS_OK;
1212 iresult = ProtoAliasIn(la, pip);
1215 iresult = ProtoAliasIn(la, pip);
1219 if (ntohs(pip->ip_off) & IP_MF) {
1220 struct alias_link *lnk;
1222 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1224 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1225 SetFragmentAddr(lnk, pip->ip_dst);
1227 iresult = PKT_ALIAS_ERROR;
1231 iresult = FragmentIn(la, pip);
1239 /* Unregistered address ranges */
1241 /* 10.0.0.0 -> 10.255.255.255 */
1242 #define UNREG_ADDR_A_LOWER 0x0a000000
1243 #define UNREG_ADDR_A_UPPER 0x0affffff
1245 /* 172.16.0.0 -> 172.31.255.255 */
1246 #define UNREG_ADDR_B_LOWER 0xac100000
1247 #define UNREG_ADDR_B_UPPER 0xac1fffff
1249 /* 192.168.0.0 -> 192.168.255.255 */
1250 #define UNREG_ADDR_C_LOWER 0xc0a80000
1251 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1254 LibAliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1255 int maxpacketsize /* How much the packet data may grow (FTP
1256 * and IRC inline changes) */
1259 return (LibAliasOutTry(la, ptr, maxpacketsize, 1));
1263 LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */
1264 int maxpacketsize, /* How much the packet data may grow (FTP
1265 * and IRC inline changes) */
1266 int create /* Create new entries ? */
1270 struct in_addr addr_save;
1273 if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1274 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1275 iresult = LibAliasIn(la, ptr, maxpacketsize);
1276 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1280 ClearCheckNewLink(la);
1281 pip = (struct ip *)ptr;
1283 /* Defense against mangled packets */
1284 if (ntohs(pip->ip_len) > maxpacketsize
1285 || (pip->ip_hl << 2) > maxpacketsize)
1286 return (PKT_ALIAS_IGNORED);
1288 addr_save = GetDefaultAliasAddress(la);
1289 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) {
1294 addr = ntohl(pip->ip_src.s_addr);
1295 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1297 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1299 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1303 SetDefaultAliasAddress(la, pip->ip_src);
1305 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1306 SetDefaultAliasAddress(la, pip->ip_src);
1308 iresult = PKT_ALIAS_IGNORED;
1309 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1310 switch (pip->ip_p) {
1312 iresult = IcmpAliasOut(la, pip, create);
1315 iresult = UdpAliasOut(la, pip, create);
1318 iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1321 if (AliasHandlePptpGreOut(la, pip) == 0)
1322 iresult = PKT_ALIAS_OK;
1324 iresult = ProtoAliasOut(la, pip, create);
1327 iresult = ProtoAliasOut(la, pip, create);
1331 iresult = FragmentOut(la, pip);
1334 SetDefaultAliasAddress(la, addr_save);
1339 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
1340 int maxpacketsize /* for error checking */
1347 struct alias_link *lnk;
1348 int iresult = PKT_ALIAS_IGNORED;
1350 pip = (struct ip *)ptr;
1352 /* Defense against mangled packets */
1353 if (ntohs(pip->ip_len) > maxpacketsize
1354 || (pip->ip_hl << 2) > maxpacketsize)
1357 ud = (struct udphdr *)ip_next(pip);
1358 tc = (struct tcphdr *)ip_next(pip);
1359 ic = (struct icmp *)ip_next(pip);
1362 if (pip->ip_p == IPPROTO_UDP)
1363 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1364 ud->uh_dport, ud->uh_sport,
1366 else if (pip->ip_p == IPPROTO_TCP)
1367 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1368 tc->th_dport, tc->th_sport,
1370 else if (pip->ip_p == IPPROTO_ICMP)
1371 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1375 /* Change it from an aliased packet to an unaliased packet */
1377 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1379 struct in_addr original_address;
1380 u_short original_port;
1382 original_address = GetOriginalAddress(lnk);
1383 original_port = GetOriginalPort(lnk);
1385 /* Adjust TCP/UDP checksum */
1386 accumulate = twowords(&pip->ip_src);
1387 accumulate -= twowords(&original_address);
1389 if (pip->ip_p == IPPROTO_UDP) {
1390 accumulate += ud->uh_sport;
1391 accumulate -= original_port;
1392 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1394 accumulate += tc->th_sport;
1395 accumulate -= original_port;
1396 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1399 /* Adjust IP checksum */
1400 DifferentialChecksum(&pip->ip_sum,
1401 &original_address, &pip->ip_src, 2);
1403 /* Un-alias source address and port number */
1404 pip->ip_src = original_address;
1405 if (pip->ip_p == IPPROTO_UDP)
1406 ud->uh_sport = original_port;
1408 tc->th_sport = original_port;
1410 iresult = PKT_ALIAS_OK;
1412 } else if (pip->ip_p == IPPROTO_ICMP) {
1415 struct in_addr original_address;
1416 u_short original_id;
1418 original_address = GetOriginalAddress(lnk);
1419 original_id = GetOriginalPort(lnk);
1421 /* Adjust ICMP checksum */
1422 accumulate = twowords(&pip->ip_src);
1423 accumulate -= twowords(&original_address);
1424 accumulate += ic->icmp_id;
1425 accumulate -= original_id;
1426 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1428 /* Adjust IP checksum */
1429 DifferentialChecksum(&pip->ip_sum,
1430 &original_address, &pip->ip_src, 2);
1432 /* Un-alias source address and port number */
1433 pip->ip_src = original_address;
1434 ic->icmp_id = original_id;
1436 iresult = PKT_ALIAS_OK;