More minor IPI work.
[dragonfly/vkernel-mp.git] / lib / libalias / alias.c
blob3d2d95b439d7ed8780c8dda36f398ea99376b72e
1 /* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
3 /*-
4 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
26 * SUCH DAMAGE.
28 * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.11 2002/07/25 12:31:37 ru Exp $
29 * $DragonFly: src/lib/libalias/alias.c,v 1.3 2004/08/20 02:08:17 joerg Exp $
33 Alias.c provides supervisory control for the functions of the
34 packet aliasing software. It consists of routines to monitor
35 TCP connection state, protocol-specific aliasing routines,
36 fragment handling and the following outside world functional
37 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
38 PacketAliasIn and PacketAliasOut.
40 The other C program files are briefly described. The data
41 structure framework which holds information needed to translate
42 packets is encapsulated in alias_db.c. Data is accessed by
43 function calls, so other segments of the program need not know
44 about the underlying data structures. Alias_ftp.c contains
45 special code for modifying the ftp PORT command used to establish
46 data connections, while alias_irc.c does the same for IRC
47 DCC. Alias_util.c contains a few utility routines.
49 Version 1.0 August, 1996 (cjm)
51 Version 1.1 August 20, 1996 (cjm)
52 PPP host accepts incoming connections for ports 0 to 1023.
53 (Gary Roberts pointed out the need to handle incoming
54 connections.)
56 Version 1.2 September 7, 1996 (cjm)
57 Fragment handling error in alias_db.c corrected.
58 (Tom Torrance helped fix this problem.)
60 Version 1.4 September 16, 1996 (cjm)
61 - A more generalized method for handling incoming
62 connections, without the 0-1023 restriction, is
63 implemented in alias_db.c
64 - Improved ICMP support in alias.c. Traceroute
65 packet streams can now be correctly aliased.
66 - TCP connection closing logic simplified in
67 alias.c and now allows for additional 1 minute
68 "grace period" after FIN or RST is observed.
70 Version 1.5 September 17, 1996 (cjm)
71 Corrected error in handling incoming UDP packets with 0 checksum.
72 (Tom Torrance helped fix this problem.)
74 Version 1.6 September 18, 1996 (cjm)
75 Simplified ICMP aliasing scheme. Should now support
76 traceroute from Win95 as well as FreeBSD.
78 Version 1.7 January 9, 1997 (cjm)
79 - Out-of-order fragment handling.
80 - IP checksum error fixed for ftp transfers
81 from aliasing host.
82 - Integer return codes added to all
83 aliasing/de-aliasing functions.
84 - Some obsolete comments cleaned up.
85 - Differential checksum computations for
86 IP header (TCP, UDP and ICMP were already
87 differential).
89 Version 2.1 May 1997 (cjm)
90 - Added support for outgoing ICMP error
91 messages.
92 - Added two functions PacketAliasIn2()
93 and PacketAliasOut2() for dynamic address
94 control (e.g. round-robin allocation of
95 incoming packets).
97 Version 2.2 July 1997 (cjm)
98 - Rationalized API function names to begin
99 with "PacketAlias..."
100 - Eliminated PacketAliasIn2() and
101 PacketAliasOut2() as poorly conceived.
103 Version 2.3 Dec 1998 (dillon)
104 - Major bounds checking additions, see FreeBSD/CVS
106 Version 3.1 May, 2000 (salander)
107 - Added hooks to handle PPTP.
109 Version 3.2 July, 2000 (salander and satoh)
110 - Added PacketUnaliasOut routine.
111 - Added hooks to handle RTSP/RTP.
113 See HISTORY file for additional revisions.
116 #include <sys/param.h>
118 #include <netinet/in_systm.h>
119 #include <netinet/in.h>
120 #include <netinet/ip.h>
121 #include <netinet/ip_icmp.h>
122 #include <netinet/tcp.h>
123 #include <netinet/udp.h>
125 #include <stdio.h>
127 #include "alias_local.h"
128 #include "alias.h"
130 #define NETBIOS_NS_PORT_NUMBER 137
131 #define NETBIOS_DGM_PORT_NUMBER 138
132 #define FTP_CONTROL_PORT_NUMBER 21
133 #define IRC_CONTROL_PORT_NUMBER_1 6667
134 #define IRC_CONTROL_PORT_NUMBER_2 6668
135 #define CUSEEME_PORT_NUMBER 7648
136 #define RTSP_CONTROL_PORT_NUMBER_1 554
137 #define RTSP_CONTROL_PORT_NUMBER_2 7070
138 #define TFTP_PORT_NUMBER 69
139 #define PPTP_CONTROL_PORT_NUMBER 1723
144 /* TCP Handling Routines
146 TcpMonitorIn() -- These routines monitor TCP connections, and
147 TcpMonitorOut() delete a link when a connection is closed.
149 These routines look for SYN, FIN and RST flags to determine when TCP
150 connections open and close. When a TCP connection closes, the data
151 structure containing packet aliasing information is deleted after
152 a timeout period.
155 /* Local prototypes */
156 static void TcpMonitorIn(struct ip *, struct alias_link *);
158 static void TcpMonitorOut(struct ip *, struct alias_link *);
161 static void
162 TcpMonitorIn(struct ip *pip, struct alias_link *link)
164 struct tcphdr *tc;
166 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
168 switch (GetStateIn(link))
170 case ALIAS_TCP_STATE_NOT_CONNECTED:
171 if (tc->th_flags & TH_RST)
172 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
173 else if (tc->th_flags & TH_SYN)
174 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
175 break;
176 case ALIAS_TCP_STATE_CONNECTED:
177 if (tc->th_flags & (TH_FIN | TH_RST))
178 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
179 break;
183 static void
184 TcpMonitorOut(struct ip *pip, struct alias_link *link)
186 struct tcphdr *tc;
188 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
190 switch (GetStateOut(link))
192 case ALIAS_TCP_STATE_NOT_CONNECTED:
193 if (tc->th_flags & TH_RST)
194 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
195 else if (tc->th_flags & TH_SYN)
196 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
197 break;
198 case ALIAS_TCP_STATE_CONNECTED:
199 if (tc->th_flags & (TH_FIN | TH_RST))
200 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
201 break;
209 /* Protocol Specific Packet Aliasing Routines
211 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
212 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
213 ProtoAliasIn(), ProtoAliasOut()
214 UdpAliasIn(), UdpAliasOut()
215 TcpAliasIn(), TcpAliasOut()
217 These routines handle protocol specific details of packet aliasing.
218 One may observe a certain amount of repetitive arithmetic in these
219 functions, the purpose of which is to compute a revised checksum
220 without actually summing over the entire data packet, which could be
221 unnecessarily time consuming.
223 The purpose of the packet aliasing routines is to replace the source
224 address of the outgoing packet and then correctly put it back for
225 any incoming packets. For TCP and UDP, ports are also re-mapped.
227 For ICMP echo/timestamp requests and replies, the following scheme
228 is used: the ID number is replaced by an alias for the outgoing
229 packet.
231 ICMP error messages are handled by looking at the IP fragment
232 in the data section of the message.
234 For TCP and UDP protocols, a port number is chosen for an outgoing
235 packet, and then incoming packets are identified by IP address and
236 port numbers. For TCP packets, there is additional logic in the event
237 that sequence and ACK numbers have been altered (as in the case for
238 FTP data port commands).
240 The port numbers used by the packet aliasing module are not true
241 ports in the Unix sense. No sockets are actually bound to ports.
242 They are more correctly thought of as placeholders.
244 All packets go through the aliasing mechanism, whether they come from
245 the gateway machine or other machines on a local area network.
249 /* Local prototypes */
250 static int IcmpAliasIn1(struct ip *);
251 static int IcmpAliasIn2(struct ip *);
252 static int IcmpAliasIn (struct ip *);
254 static int IcmpAliasOut1(struct ip *);
255 static int IcmpAliasOut2(struct ip *);
256 static int IcmpAliasOut (struct ip *);
258 static int ProtoAliasIn(struct ip *);
259 static int ProtoAliasOut(struct ip *);
261 static int UdpAliasOut(struct ip *);
262 static int UdpAliasIn (struct ip *);
264 static int TcpAliasOut(struct ip *, int);
265 static int TcpAliasIn (struct ip *);
268 static int
269 IcmpAliasIn1(struct ip *pip)
272 De-alias incoming echo and timestamp replies.
273 Alias incoming echo and timestamp requests.
275 struct alias_link *link;
276 struct icmp *ic;
278 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
280 /* Get source address from ICMP data field and restore original data */
281 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
282 if (link != NULL)
284 u_short original_id;
285 int accumulate;
287 original_id = GetOriginalPort(link);
289 /* Adjust ICMP checksum */
290 accumulate = ic->icmp_id;
291 accumulate -= original_id;
292 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
294 /* Put original sequence number back in */
295 ic->icmp_id = original_id;
297 /* Put original address back into IP header */
299 struct in_addr original_address;
301 original_address = GetOriginalAddress(link);
302 DifferentialChecksum(&pip->ip_sum,
303 (u_short *) &original_address,
304 (u_short *) &pip->ip_dst,
306 pip->ip_dst = original_address;
309 return(PKT_ALIAS_OK);
311 return(PKT_ALIAS_IGNORED);
314 static int
315 IcmpAliasIn2(struct ip *pip)
318 Alias incoming ICMP error messages containing
319 IP header and first 64 bits of datagram.
321 struct ip *ip;
322 struct icmp *ic, *ic2;
323 struct udphdr *ud;
324 struct tcphdr *tc;
325 struct alias_link *link;
327 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
328 ip = &ic->icmp_ip;
330 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
331 tc = (struct tcphdr *) ud;
332 ic2 = (struct icmp *) ud;
334 if (ip->ip_p == IPPROTO_UDP)
335 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
336 ud->uh_dport, ud->uh_sport,
337 IPPROTO_UDP, 0);
338 else if (ip->ip_p == IPPROTO_TCP)
339 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
340 tc->th_dport, tc->th_sport,
341 IPPROTO_TCP, 0);
342 else if (ip->ip_p == IPPROTO_ICMP) {
343 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
344 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
345 else
346 link = NULL;
347 } else
348 link = NULL;
350 if (link != NULL)
352 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
354 u_short *sptr;
355 int accumulate, accumulate2;
356 struct in_addr original_address;
357 u_short original_port;
359 original_address = GetOriginalAddress(link);
360 original_port = GetOriginalPort(link);
362 /* Adjust ICMP checksum */
363 sptr = (u_short *) &(ip->ip_src);
364 accumulate = *sptr++;
365 accumulate += *sptr;
366 sptr = (u_short *) &original_address;
367 accumulate -= *sptr++;
368 accumulate -= *sptr;
369 accumulate += ud->uh_sport;
370 accumulate -= original_port;
371 accumulate2 = accumulate;
372 accumulate2 += ip->ip_sum;
373 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
374 accumulate2 -= ip->ip_sum;
375 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
377 /* Un-alias address in IP header */
378 DifferentialChecksum(&pip->ip_sum,
379 (u_short *) &original_address,
380 (u_short *) &pip->ip_dst,
382 pip->ip_dst = original_address;
384 /* Un-alias address and port number of original IP packet
385 fragment contained in ICMP data section */
386 ip->ip_src = original_address;
387 ud->uh_sport = original_port;
389 else if (ip->ip_p == IPPROTO_ICMP)
391 u_short *sptr;
392 int accumulate, accumulate2;
393 struct in_addr original_address;
394 u_short original_id;
396 original_address = GetOriginalAddress(link);
397 original_id = GetOriginalPort(link);
399 /* Adjust ICMP checksum */
400 sptr = (u_short *) &(ip->ip_src);
401 accumulate = *sptr++;
402 accumulate += *sptr;
403 sptr = (u_short *) &original_address;
404 accumulate -= *sptr++;
405 accumulate -= *sptr;
406 accumulate += ic2->icmp_id;
407 accumulate -= original_id;
408 accumulate2 = accumulate;
409 accumulate2 += ip->ip_sum;
410 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
411 accumulate2 -= ip->ip_sum;
412 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
414 /* Un-alias address in IP header */
415 DifferentialChecksum(&pip->ip_sum,
416 (u_short *) &original_address,
417 (u_short *) &pip->ip_dst,
419 pip->ip_dst = original_address;
421 /* Un-alias address of original IP packet and sequence number of
422 embedded ICMP datagram */
423 ip->ip_src = original_address;
424 ic2->icmp_id = original_id;
426 return(PKT_ALIAS_OK);
428 return(PKT_ALIAS_IGNORED);
432 static int
433 IcmpAliasIn(struct ip *pip)
435 int iresult;
436 struct icmp *ic;
438 /* Return if proxy-only mode is enabled */
439 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
440 return PKT_ALIAS_OK;
442 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
444 iresult = PKT_ALIAS_IGNORED;
445 switch (ic->icmp_type)
447 case ICMP_ECHOREPLY:
448 case ICMP_TSTAMPREPLY:
449 if (ic->icmp_code == 0)
451 iresult = IcmpAliasIn1(pip);
453 break;
454 case ICMP_UNREACH:
455 case ICMP_SOURCEQUENCH:
456 case ICMP_TIMXCEED:
457 case ICMP_PARAMPROB:
458 iresult = IcmpAliasIn2(pip);
459 break;
460 case ICMP_ECHO:
461 case ICMP_TSTAMP:
462 iresult = IcmpAliasIn1(pip);
463 break;
465 return(iresult);
469 static int
470 IcmpAliasOut1(struct ip *pip)
473 Alias outgoing echo and timestamp requests.
474 De-alias outgoing echo and timestamp replies.
476 struct alias_link *link;
477 struct icmp *ic;
479 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
481 /* Save overwritten data for when echo packet returns */
482 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
483 if (link != NULL)
485 u_short alias_id;
486 int accumulate;
488 alias_id = GetAliasPort(link);
490 /* Since data field is being modified, adjust ICMP checksum */
491 accumulate = ic->icmp_id;
492 accumulate -= alias_id;
493 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
495 /* Alias sequence number */
496 ic->icmp_id = alias_id;
498 /* Change source address */
500 struct in_addr alias_address;
502 alias_address = GetAliasAddress(link);
503 DifferentialChecksum(&pip->ip_sum,
504 (u_short *) &alias_address,
505 (u_short *) &pip->ip_src,
507 pip->ip_src = alias_address;
510 return(PKT_ALIAS_OK);
512 return(PKT_ALIAS_IGNORED);
516 static int
517 IcmpAliasOut2(struct ip *pip)
520 Alias outgoing ICMP error messages containing
521 IP header and first 64 bits of datagram.
523 struct ip *ip;
524 struct icmp *ic, *ic2;
525 struct udphdr *ud;
526 struct tcphdr *tc;
527 struct alias_link *link;
529 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
530 ip = &ic->icmp_ip;
532 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
533 tc = (struct tcphdr *) ud;
534 ic2 = (struct icmp *) ud;
536 if (ip->ip_p == IPPROTO_UDP)
537 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
538 ud->uh_dport, ud->uh_sport,
539 IPPROTO_UDP, 0);
540 else if (ip->ip_p == IPPROTO_TCP)
541 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
542 tc->th_dport, tc->th_sport,
543 IPPROTO_TCP, 0);
544 else if (ip->ip_p == IPPROTO_ICMP) {
545 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
546 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
547 else
548 link = NULL;
549 } else
550 link = NULL;
552 if (link != NULL)
554 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
556 u_short *sptr;
557 int accumulate;
558 struct in_addr alias_address;
559 u_short alias_port;
561 alias_address = GetAliasAddress(link);
562 alias_port = GetAliasPort(link);
564 /* Adjust ICMP checksum */
565 sptr = (u_short *) &(ip->ip_dst);
566 accumulate = *sptr++;
567 accumulate += *sptr;
568 sptr = (u_short *) &alias_address;
569 accumulate -= *sptr++;
570 accumulate -= *sptr;
571 accumulate += ud->uh_dport;
572 accumulate -= alias_port;
573 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
576 * Alias address in IP header if it comes from the host
577 * the original TCP/UDP packet was destined for.
579 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
580 DifferentialChecksum(&pip->ip_sum,
581 (u_short *) &alias_address,
582 (u_short *) &pip->ip_src,
584 pip->ip_src = alias_address;
587 /* Alias address and port number of original IP packet
588 fragment contained in ICMP data section */
589 ip->ip_dst = alias_address;
590 ud->uh_dport = alias_port;
592 else if (ip->ip_p == IPPROTO_ICMP)
594 u_short *sptr;
595 int accumulate;
596 struct in_addr alias_address;
597 u_short alias_id;
599 alias_address = GetAliasAddress(link);
600 alias_id = GetAliasPort(link);
602 /* Adjust ICMP checksum */
603 sptr = (u_short *) &(ip->ip_dst);
604 accumulate = *sptr++;
605 accumulate += *sptr;
606 sptr = (u_short *) &alias_address;
607 accumulate -= *sptr++;
608 accumulate -= *sptr;
609 accumulate += ic2->icmp_id;
610 accumulate -= alias_id;
611 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
614 * Alias address in IP header if it comes from the host
615 * the original ICMP message was destined for.
617 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
618 DifferentialChecksum(&pip->ip_sum,
619 (u_short *) &alias_address,
620 (u_short *) &pip->ip_src,
622 pip->ip_src = alias_address;
625 /* Alias address of original IP packet and sequence number of
626 embedded ICMP datagram */
627 ip->ip_dst = alias_address;
628 ic2->icmp_id = alias_id;
630 return(PKT_ALIAS_OK);
632 return(PKT_ALIAS_IGNORED);
636 static int
637 IcmpAliasOut(struct ip *pip)
639 int iresult;
640 struct icmp *ic;
642 /* Return if proxy-only mode is enabled */
643 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
644 return PKT_ALIAS_OK;
646 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
648 iresult = PKT_ALIAS_IGNORED;
649 switch (ic->icmp_type)
651 case ICMP_ECHO:
652 case ICMP_TSTAMP:
653 if (ic->icmp_code == 0)
655 iresult = IcmpAliasOut1(pip);
657 break;
658 case ICMP_UNREACH:
659 case ICMP_SOURCEQUENCH:
660 case ICMP_TIMXCEED:
661 case ICMP_PARAMPROB:
662 iresult = IcmpAliasOut2(pip);
663 break;
664 case ICMP_ECHOREPLY:
665 case ICMP_TSTAMPREPLY:
666 iresult = IcmpAliasOut1(pip);
668 return(iresult);
673 static int
674 ProtoAliasIn(struct ip *pip)
677 Handle incoming IP packets. The
678 only thing which is done in this case is to alias
679 the dest IP address of the packet to our inside
680 machine.
682 struct alias_link *link;
684 /* Return if proxy-only mode is enabled */
685 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
686 return PKT_ALIAS_OK;
688 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
689 if (link != NULL)
691 struct in_addr original_address;
693 original_address = GetOriginalAddress(link);
695 /* Restore original IP address */
696 DifferentialChecksum(&pip->ip_sum,
697 (u_short *) &original_address,
698 (u_short *) &pip->ip_dst,
700 pip->ip_dst = original_address;
702 return(PKT_ALIAS_OK);
704 return(PKT_ALIAS_IGNORED);
708 static int
709 ProtoAliasOut(struct ip *pip)
712 Handle outgoing IP packets. The
713 only thing which is done in this case is to alias
714 the source IP address of the packet.
716 struct alias_link *link;
718 /* Return if proxy-only mode is enabled */
719 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
720 return PKT_ALIAS_OK;
722 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
723 if (link != NULL)
725 struct in_addr alias_address;
727 alias_address = GetAliasAddress(link);
729 /* Change source address */
730 DifferentialChecksum(&pip->ip_sum,
731 (u_short *) &alias_address,
732 (u_short *) &pip->ip_src,
734 pip->ip_src = alias_address;
736 return(PKT_ALIAS_OK);
738 return(PKT_ALIAS_IGNORED);
742 static int
743 UdpAliasIn(struct ip *pip)
745 struct udphdr *ud;
746 struct alias_link *link;
748 /* Return if proxy-only mode is enabled */
749 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
750 return PKT_ALIAS_OK;
752 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
754 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
755 ud->uh_sport, ud->uh_dport,
756 IPPROTO_UDP, 1);
757 if (link != NULL)
759 struct in_addr alias_address;
760 struct in_addr original_address;
761 u_short alias_port;
762 int accumulate;
763 u_short *sptr;
764 int r = 0;
766 alias_address = GetAliasAddress(link);
767 original_address = GetOriginalAddress(link);
768 alias_port = ud->uh_dport;
769 ud->uh_dport = GetOriginalPort(link);
771 /* Special processing for IP encoding protocols */
772 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
773 AliasHandleCUSeeMeIn(pip, original_address);
774 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
775 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
776 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
777 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
778 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
779 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
780 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
781 &original_address, &ud->uh_dport);
783 /* If UDP checksum is not zero, then adjust since destination port */
784 /* is being unaliased and destination address is being altered. */
785 if (ud->uh_sum != 0)
787 accumulate = alias_port;
788 accumulate -= ud->uh_dport;
789 sptr = (u_short *) &alias_address;
790 accumulate += *sptr++;
791 accumulate += *sptr;
792 sptr = (u_short *) &original_address;
793 accumulate -= *sptr++;
794 accumulate -= *sptr;
795 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
798 /* Restore original IP address */
799 DifferentialChecksum(&pip->ip_sum,
800 (u_short *) &original_address,
801 (u_short *) &pip->ip_dst,
803 pip->ip_dst = original_address;
806 * If we cannot figure out the packet, ignore it.
808 if (r < 0)
809 return(PKT_ALIAS_IGNORED);
810 else
811 return(PKT_ALIAS_OK);
813 return(PKT_ALIAS_IGNORED);
816 static int
817 UdpAliasOut(struct ip *pip)
819 struct udphdr *ud;
820 struct alias_link *link;
822 /* Return if proxy-only mode is enabled */
823 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
824 return PKT_ALIAS_OK;
826 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
828 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
829 ud->uh_sport, ud->uh_dport,
830 IPPROTO_UDP, 1);
831 if (link != NULL)
833 u_short alias_port;
834 struct in_addr alias_address;
836 alias_address = GetAliasAddress(link);
837 alias_port = GetAliasPort(link);
839 /* Special processing for IP encoding protocols */
840 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
841 AliasHandleCUSeeMeOut(pip, link);
842 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
843 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
844 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
845 AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
846 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
847 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
848 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
849 &alias_address, &alias_port);
851 * We don't know in advance what TID the TFTP server will choose,
852 * so we create a wilcard link (destination port is unspecified)
853 * that will match any TID from a given destination.
855 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
856 FindRtspOut(pip->ip_src, pip->ip_dst,
857 ud->uh_sport, alias_port, IPPROTO_UDP);
859 /* If UDP checksum is not zero, adjust since source port is */
860 /* being aliased and source address is being altered */
861 if (ud->uh_sum != 0)
863 int accumulate;
864 u_short *sptr;
866 accumulate = ud->uh_sport;
867 accumulate -= alias_port;
868 sptr = (u_short *) &(pip->ip_src);
869 accumulate += *sptr++;
870 accumulate += *sptr;
871 sptr = (u_short *) &alias_address;
872 accumulate -= *sptr++;
873 accumulate -= *sptr;
874 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
877 /* Put alias port in UDP header */
878 ud->uh_sport = alias_port;
880 /* Change source address */
881 DifferentialChecksum(&pip->ip_sum,
882 (u_short *) &alias_address,
883 (u_short *) &pip->ip_src,
885 pip->ip_src = alias_address;
887 return(PKT_ALIAS_OK);
889 return(PKT_ALIAS_IGNORED);
894 static int
895 TcpAliasIn(struct ip *pip)
897 struct tcphdr *tc;
898 struct alias_link *link;
900 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
902 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
903 tc->th_sport, tc->th_dport,
904 IPPROTO_TCP,
905 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
906 if (link != NULL)
908 struct in_addr alias_address;
909 struct in_addr original_address;
910 struct in_addr proxy_address;
911 u_short alias_port;
912 u_short proxy_port;
913 int accumulate;
914 u_short *sptr;
916 /* Special processing for IP encoding protocols */
917 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
918 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
919 AliasHandlePptpIn(pip, link);
921 alias_address = GetAliasAddress(link);
922 original_address = GetOriginalAddress(link);
923 proxy_address = GetProxyAddress(link);
924 alias_port = tc->th_dport;
925 tc->th_dport = GetOriginalPort(link);
926 proxy_port = GetProxyPort(link);
928 /* Adjust TCP checksum since destination port is being unaliased */
929 /* and destination port is being altered. */
930 accumulate = alias_port;
931 accumulate -= tc->th_dport;
932 sptr = (u_short *) &alias_address;
933 accumulate += *sptr++;
934 accumulate += *sptr;
935 sptr = (u_short *) &original_address;
936 accumulate -= *sptr++;
937 accumulate -= *sptr;
939 /* If this is a proxy, then modify the TCP source port and
940 checksum accumulation */
941 if (proxy_port != 0)
943 accumulate += tc->th_sport;
944 tc->th_sport = proxy_port;
945 accumulate -= tc->th_sport;
947 sptr = (u_short *) &pip->ip_src;
948 accumulate += *sptr++;
949 accumulate += *sptr;
950 sptr = (u_short *) &proxy_address;
951 accumulate -= *sptr++;
952 accumulate -= *sptr;
955 /* See if ACK number needs to be modified */
956 if (GetAckModified(link) == 1)
958 int delta;
960 delta = GetDeltaAckIn(pip, link);
961 if (delta != 0)
963 sptr = (u_short *) &tc->th_ack;
964 accumulate += *sptr++;
965 accumulate += *sptr;
966 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
967 sptr = (u_short *) &tc->th_ack;
968 accumulate -= *sptr++;
969 accumulate -= *sptr;
973 ADJUST_CHECKSUM(accumulate, tc->th_sum);
975 /* Restore original IP address */
976 sptr = (u_short *) &pip->ip_dst;
977 accumulate = *sptr++;
978 accumulate += *sptr;
979 pip->ip_dst = original_address;
980 sptr = (u_short *) &pip->ip_dst;
981 accumulate -= *sptr++;
982 accumulate -= *sptr;
984 /* If this is a transparent proxy packet, then modify the source
985 address */
986 if (proxy_address.s_addr != 0)
988 sptr = (u_short *) &pip->ip_src;
989 accumulate += *sptr++;
990 accumulate += *sptr;
991 pip->ip_src = proxy_address;
992 sptr = (u_short *) &pip->ip_src;
993 accumulate -= *sptr++;
994 accumulate -= *sptr;
997 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
999 /* Monitor TCP connection state */
1000 TcpMonitorIn(pip, link);
1002 return(PKT_ALIAS_OK);
1004 return(PKT_ALIAS_IGNORED);
1007 static int
1008 TcpAliasOut(struct ip *pip, int maxpacketsize)
1010 int proxy_type;
1011 u_short dest_port;
1012 u_short proxy_server_port;
1013 struct in_addr dest_address;
1014 struct in_addr proxy_server_address;
1015 struct tcphdr *tc;
1016 struct alias_link *link;
1018 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1020 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1022 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1023 return PKT_ALIAS_OK;
1025 /* If this is a transparent proxy, save original destination,
1026 then alter the destination and adjust checksums */
1027 dest_port = tc->th_dport;
1028 dest_address = pip->ip_dst;
1029 if (proxy_type != 0)
1031 int accumulate;
1032 u_short *sptr;
1034 accumulate = tc->th_dport;
1035 tc->th_dport = proxy_server_port;
1036 accumulate -= tc->th_dport;
1038 sptr = (u_short *) &(pip->ip_dst);
1039 accumulate += *sptr++;
1040 accumulate += *sptr;
1041 sptr = (u_short *) &proxy_server_address;
1042 accumulate -= *sptr++;
1043 accumulate -= *sptr;
1045 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1047 sptr = (u_short *) &(pip->ip_dst);
1048 accumulate = *sptr++;
1049 accumulate += *sptr;
1050 pip->ip_dst = proxy_server_address;
1051 sptr = (u_short *) &(pip->ip_dst);
1052 accumulate -= *sptr++;
1053 accumulate -= *sptr;
1055 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1058 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1059 tc->th_sport, tc->th_dport,
1060 IPPROTO_TCP, 1);
1061 if (link !=NULL)
1063 u_short alias_port;
1064 struct in_addr alias_address;
1065 int accumulate;
1066 u_short *sptr;
1068 /* Save original destination address, if this is a proxy packet.
1069 Also modify packet to include destination encoding. This may
1070 change the size of IP header. */
1071 if (proxy_type != 0)
1073 SetProxyPort(link, dest_port);
1074 SetProxyAddress(link, dest_address);
1075 ProxyModify(link, pip, maxpacketsize, proxy_type);
1076 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1079 /* Get alias address and port */
1080 alias_port = GetAliasPort(link);
1081 alias_address = GetAliasAddress(link);
1083 /* Monitor TCP connection state */
1084 TcpMonitorOut(pip, link);
1086 /* Special processing for IP encoding protocols */
1087 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1088 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1089 AliasHandleFtpOut(pip, link, maxpacketsize);
1090 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1091 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1092 AliasHandleIrcOut(pip, link, maxpacketsize);
1093 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1094 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1095 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1096 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1097 AliasHandleRtspOut(pip, link, maxpacketsize);
1098 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1099 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1100 AliasHandlePptpOut(pip, link);
1102 /* Adjust TCP checksum since source port is being aliased */
1103 /* and source address is being altered */
1104 accumulate = tc->th_sport;
1105 tc->th_sport = alias_port;
1106 accumulate -= tc->th_sport;
1108 sptr = (u_short *) &(pip->ip_src);
1109 accumulate += *sptr++;
1110 accumulate += *sptr;
1111 sptr = (u_short *) &alias_address;
1112 accumulate -= *sptr++;
1113 accumulate -= *sptr;
1115 /* Modify sequence number if necessary */
1116 if (GetAckModified(link) == 1)
1118 int delta;
1120 delta = GetDeltaSeqOut(pip, link);
1121 if (delta != 0)
1123 sptr = (u_short *) &tc->th_seq;
1124 accumulate += *sptr++;
1125 accumulate += *sptr;
1126 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1127 sptr = (u_short *) &tc->th_seq;
1128 accumulate -= *sptr++;
1129 accumulate -= *sptr;
1133 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1135 /* Change source address */
1136 sptr = (u_short *) &(pip->ip_src);
1137 accumulate = *sptr++;
1138 accumulate += *sptr;
1139 pip->ip_src = alias_address;
1140 sptr = (u_short *) &(pip->ip_src);
1141 accumulate -= *sptr++;
1142 accumulate -= *sptr;
1144 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1146 return(PKT_ALIAS_OK);
1148 return(PKT_ALIAS_IGNORED);
1154 /* Fragment Handling
1156 FragmentIn()
1157 FragmentOut()
1159 The packet aliasing module has a limited ability for handling IP
1160 fragments. If the ICMP, TCP or UDP header is in the first fragment
1161 received, then the ID number of the IP packet is saved, and other
1162 fragments are identified according to their ID number and IP address
1163 they were sent from. Pointers to unresolved fragments can also be
1164 saved and recalled when a header fragment is seen.
1167 /* Local prototypes */
1168 static int FragmentIn(struct ip *);
1169 static int FragmentOut(struct ip *);
1172 static int
1173 FragmentIn(struct ip *pip)
1175 struct alias_link *link;
1177 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1178 if (link != NULL)
1180 struct in_addr original_address;
1182 GetFragmentAddr(link, &original_address);
1183 DifferentialChecksum(&pip->ip_sum,
1184 (u_short *) &original_address,
1185 (u_short *) &pip->ip_dst,
1187 pip->ip_dst = original_address;
1189 return(PKT_ALIAS_OK);
1191 return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1195 static int
1196 FragmentOut(struct ip *pip)
1198 struct in_addr alias_address;
1200 alias_address = FindAliasAddress(pip->ip_src);
1201 DifferentialChecksum(&pip->ip_sum,
1202 (u_short *) &alias_address,
1203 (u_short *) &pip->ip_src,
1205 pip->ip_src = alias_address;
1207 return(PKT_ALIAS_OK);
1215 /* Outside World Access
1217 PacketAliasSaveFragment()
1218 PacketAliasGetFragment()
1219 PacketAliasFragmentIn()
1220 PacketAliasIn()
1221 PacketAliasOut()
1222 PacketUnaliasOut()
1224 (prototypes in alias.h)
1229 PacketAliasSaveFragment(char *ptr)
1231 int iresult;
1232 struct alias_link *link;
1233 struct ip *pip;
1235 pip = (struct ip *) ptr;
1236 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1237 iresult = PKT_ALIAS_ERROR;
1238 if (link != NULL)
1240 SetFragmentPtr(link, ptr);
1241 iresult = PKT_ALIAS_OK;
1243 return(iresult);
1247 char *
1248 PacketAliasGetFragment(char *ptr)
1250 struct alias_link *link;
1251 char *fptr;
1252 struct ip *pip;
1254 pip = (struct ip *) ptr;
1255 link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1256 if (link != NULL)
1258 GetFragmentPtr(link, &fptr);
1259 SetFragmentPtr(link, NULL);
1260 SetExpire(link, 0); /* Deletes link */
1262 return(fptr);
1264 else
1266 return(NULL);
1271 void
1272 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased
1273 header fragment */
1274 char *ptr_fragment /* Points to fragment which must
1275 be de-aliased */
1278 struct ip *pip;
1279 struct ip *fpip;
1281 pip = (struct ip *) ptr;
1282 fpip = (struct ip *) ptr_fragment;
1284 DifferentialChecksum(&fpip->ip_sum,
1285 (u_short *) &pip->ip_dst,
1286 (u_short *) &fpip->ip_dst,
1288 fpip->ip_dst = pip->ip_dst;
1293 PacketAliasIn(char *ptr, int maxpacketsize)
1295 struct in_addr alias_addr;
1296 struct ip *pip;
1297 int iresult;
1299 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1300 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1301 iresult = PacketAliasOut(ptr, maxpacketsize);
1302 packetAliasMode |= PKT_ALIAS_REVERSE;
1303 return iresult;
1306 HouseKeeping();
1307 ClearCheckNewLink();
1308 pip = (struct ip *) ptr;
1309 alias_addr = pip->ip_dst;
1311 /* Defense against mangled packets */
1312 if (ntohs(pip->ip_len) > maxpacketsize
1313 || (pip->ip_hl<<2) > maxpacketsize)
1314 return PKT_ALIAS_IGNORED;
1316 iresult = PKT_ALIAS_IGNORED;
1317 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1319 switch (pip->ip_p)
1321 case IPPROTO_ICMP:
1322 iresult = IcmpAliasIn(pip);
1323 break;
1324 case IPPROTO_UDP:
1325 iresult = UdpAliasIn(pip);
1326 break;
1327 case IPPROTO_TCP:
1328 iresult = TcpAliasIn(pip);
1329 break;
1330 case IPPROTO_GRE:
1331 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1332 AliasHandlePptpGreIn(pip) == 0)
1333 iresult = PKT_ALIAS_OK;
1334 else
1335 iresult = ProtoAliasIn(pip);
1336 break;
1337 default:
1338 iresult = ProtoAliasIn(pip);
1339 break;
1342 if (ntohs(pip->ip_off) & IP_MF)
1344 struct alias_link *link;
1346 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1347 if (link != NULL)
1349 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1350 SetFragmentAddr(link, pip->ip_dst);
1352 else
1354 iresult = PKT_ALIAS_ERROR;
1358 else
1360 iresult = FragmentIn(pip);
1363 return(iresult);
1368 /* Unregistered address ranges */
1370 /* 10.0.0.0 -> 10.255.255.255 */
1371 #define UNREG_ADDR_A_LOWER 0x0a000000
1372 #define UNREG_ADDR_A_UPPER 0x0affffff
1374 /* 172.16.0.0 -> 172.31.255.255 */
1375 #define UNREG_ADDR_B_LOWER 0xac100000
1376 #define UNREG_ADDR_B_UPPER 0xac1fffff
1378 /* 192.168.0.0 -> 192.168.255.255 */
1379 #define UNREG_ADDR_C_LOWER 0xc0a80000
1380 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1383 PacketAliasOut(char *ptr, /* valid IP packet */
1384 int maxpacketsize /* How much the packet data may grow
1385 (FTP and IRC inline changes) */
1388 int iresult;
1389 struct in_addr addr_save;
1390 struct ip *pip;
1392 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1393 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1394 iresult = PacketAliasIn(ptr, maxpacketsize);
1395 packetAliasMode |= PKT_ALIAS_REVERSE;
1396 return iresult;
1399 HouseKeeping();
1400 ClearCheckNewLink();
1401 pip = (struct ip *) ptr;
1403 /* Defense against mangled packets */
1404 if (ntohs(pip->ip_len) > maxpacketsize
1405 || (pip->ip_hl<<2) > maxpacketsize)
1406 return PKT_ALIAS_IGNORED;
1408 addr_save = GetDefaultAliasAddress();
1409 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1411 u_long addr;
1412 int iclass;
1414 iclass = 0;
1415 addr = ntohl(pip->ip_src.s_addr);
1416 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1417 iclass = 3;
1418 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1419 iclass = 2;
1420 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1421 iclass = 1;
1423 if (iclass == 0)
1425 SetDefaultAliasAddress(pip->ip_src);
1429 iresult = PKT_ALIAS_IGNORED;
1430 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1432 switch (pip->ip_p)
1434 case IPPROTO_ICMP:
1435 iresult = IcmpAliasOut(pip);
1436 break;
1437 case IPPROTO_UDP:
1438 iresult = UdpAliasOut(pip);
1439 break;
1440 case IPPROTO_TCP:
1441 iresult = TcpAliasOut(pip, maxpacketsize);
1442 break;
1443 case IPPROTO_GRE:
1444 if (AliasHandlePptpGreOut(pip) == 0)
1445 iresult = PKT_ALIAS_OK;
1446 else
1447 iresult = ProtoAliasOut(pip);
1448 break;
1449 default:
1450 iresult = ProtoAliasOut(pip);
1451 break;
1454 else
1456 iresult = FragmentOut(pip);
1459 SetDefaultAliasAddress(addr_save);
1460 return(iresult);
1464 PacketUnaliasOut(char *ptr, /* valid IP packet */
1465 int maxpacketsize /* for error checking */
1468 struct ip *pip;
1469 struct icmp *ic;
1470 struct udphdr *ud;
1471 struct tcphdr *tc;
1472 struct alias_link *link;
1473 int iresult = PKT_ALIAS_IGNORED;
1475 pip = (struct ip *) ptr;
1477 /* Defense against mangled packets */
1478 if (ntohs(pip->ip_len) > maxpacketsize
1479 || (pip->ip_hl<<2) > maxpacketsize)
1480 return(iresult);
1482 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1483 tc = (struct tcphdr *) ud;
1484 ic = (struct icmp *) ud;
1486 /* Find a link */
1487 if (pip->ip_p == IPPROTO_UDP)
1488 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1489 ud->uh_dport, ud->uh_sport,
1490 IPPROTO_UDP, 0);
1491 else if (pip->ip_p == IPPROTO_TCP)
1492 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1493 tc->th_dport, tc->th_sport,
1494 IPPROTO_TCP, 0);
1495 else if (pip->ip_p == IPPROTO_ICMP)
1496 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1497 else
1498 link = NULL;
1500 /* Change it from an aliased packet to an unaliased packet */
1501 if (link != NULL)
1503 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1505 u_short *sptr;
1506 int accumulate;
1507 struct in_addr original_address;
1508 u_short original_port;
1510 original_address = GetOriginalAddress(link);
1511 original_port = GetOriginalPort(link);
1513 /* Adjust TCP/UDP checksum */
1514 sptr = (u_short *) &(pip->ip_src);
1515 accumulate = *sptr++;
1516 accumulate += *sptr;
1517 sptr = (u_short *) &original_address;
1518 accumulate -= *sptr++;
1519 accumulate -= *sptr;
1521 if (pip->ip_p == IPPROTO_UDP) {
1522 accumulate += ud->uh_sport;
1523 accumulate -= original_port;
1524 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1525 } else {
1526 accumulate += tc->th_sport;
1527 accumulate -= original_port;
1528 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1531 /* Adjust IP checksum */
1532 DifferentialChecksum(&pip->ip_sum,
1533 (u_short *) &original_address,
1534 (u_short *) &pip->ip_src,
1537 /* Un-alias source address and port number */
1538 pip->ip_src = original_address;
1539 if (pip->ip_p == IPPROTO_UDP)
1540 ud->uh_sport = original_port;
1541 else
1542 tc->th_sport = original_port;
1544 iresult = PKT_ALIAS_OK;
1546 } else if (pip->ip_p == IPPROTO_ICMP) {
1548 u_short *sptr;
1549 int accumulate;
1550 struct in_addr original_address;
1551 u_short original_id;
1553 original_address = GetOriginalAddress(link);
1554 original_id = GetOriginalPort(link);
1556 /* Adjust ICMP checksum */
1557 sptr = (u_short *) &(pip->ip_src);
1558 accumulate = *sptr++;
1559 accumulate += *sptr;
1560 sptr = (u_short *) &original_address;
1561 accumulate -= *sptr++;
1562 accumulate -= *sptr;
1563 accumulate += ic->icmp_id;
1564 accumulate -= original_id;
1565 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1567 /* Adjust IP checksum */
1568 DifferentialChecksum(&pip->ip_sum,
1569 (u_short *) &original_address,
1570 (u_short *) &pip->ip_src,
1573 /* Un-alias source address and port number */
1574 pip->ip_src = original_address;
1575 ic->icmp_id = original_id;
1577 iresult = PKT_ALIAS_OK;
1580 return(iresult);