Add __attribute__((__noreturn__)) to various function prototypes in usr.bin/.
[dragonfly.git] / lib / libalias / alias.c
blob2b8fd826d33c4e605d937dd1b42ecf4828479db8
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 $
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
53 connections.)
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
80 from aliasing host.
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
86 differential).
88 Version 2.1 May 1997 (cjm)
89 - Added support for outgoing ICMP error
90 messages.
91 - Added two functions PacketAliasIn2()
92 and PacketAliasOut2() for dynamic address
93 control (e.g. round-robin allocation of
94 incoming packets).
96 Version 2.2 July 1997 (cjm)
97 - Rationalized API function names to begin
98 with "PacketAlias..."
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>
124 #include <stdio.h>
126 #include "alias_local.h"
127 #include "alias.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
140 static __inline int
141 twowords(void *p)
143 uint8_t *c = p;
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];
148 #else
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];
151 #endif
152 return (s1 + s2);
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
163 a timeout period.
166 /* Local prototypes */
167 static void TcpMonitorIn(struct ip *, struct alias_link *);
169 static void TcpMonitorOut(struct ip *, struct alias_link *);
172 static void
173 TcpMonitorIn(struct ip *pip, struct alias_link *link)
175 struct tcphdr *tc;
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);
186 break;
187 case ALIAS_TCP_STATE_CONNECTED:
188 if (tc->th_flags & (TH_FIN | TH_RST))
189 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
190 break;
194 static void
195 TcpMonitorOut(struct ip *pip, struct alias_link *link)
197 struct tcphdr *tc;
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);
208 break;
209 case ALIAS_TCP_STATE_CONNECTED:
210 if (tc->th_flags & (TH_FIN | TH_RST))
211 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
212 break;
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
240 packet.
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 *);
279 static int
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;
287 struct icmp *ic;
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);
293 if (link != NULL)
295 u_short original_id;
296 int accumulate;
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);
325 static int
326 IcmpAliasIn2(struct ip *pip)
329 Alias incoming ICMP error messages containing
330 IP header and first 64 bits of datagram.
332 struct ip *ip;
333 struct icmp *ic, *ic2;
334 struct udphdr *ud;
335 struct tcphdr *tc;
336 struct alias_link *link;
338 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
339 ip = &ic->icmp_ip;
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,
348 IPPROTO_UDP, 0);
349 else if (ip->ip_p == IPPROTO_TCP)
350 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
351 tc->th_dport, tc->th_sport,
352 IPPROTO_TCP, 0);
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);
356 else
357 link = NULL;
358 } else
359 link = NULL;
361 if (link != NULL)
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;
399 u_short original_id;
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);
433 static int
434 IcmpAliasIn(struct ip *pip)
436 int iresult;
437 struct icmp *ic;
439 /* Return if proxy-only mode is enabled */
440 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
441 return PKT_ALIAS_OK;
443 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
445 iresult = PKT_ALIAS_IGNORED;
446 switch (ic->icmp_type)
448 case ICMP_ECHOREPLY:
449 case ICMP_TSTAMPREPLY:
450 if (ic->icmp_code == 0)
452 iresult = IcmpAliasIn1(pip);
454 break;
455 case ICMP_UNREACH:
456 case ICMP_SOURCEQUENCH:
457 case ICMP_TIMXCEED:
458 case ICMP_PARAMPROB:
459 iresult = IcmpAliasIn2(pip);
460 break;
461 case ICMP_ECHO:
462 case ICMP_TSTAMP:
463 iresult = IcmpAliasIn1(pip);
464 break;
466 return(iresult);
470 static int
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;
478 struct icmp *ic;
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);
484 if (link != NULL)
486 u_short alias_id;
487 int accumulate;
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);
517 static int
518 IcmpAliasOut2(struct ip *pip)
521 Alias outgoing ICMP error messages containing
522 IP header and first 64 bits of datagram.
524 struct ip *ip;
525 struct icmp *ic, *ic2;
526 struct udphdr *ud;
527 struct tcphdr *tc;
528 struct alias_link *link;
530 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
531 ip = &ic->icmp_ip;
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,
540 IPPROTO_UDP, 0);
541 else if (ip->ip_p == IPPROTO_TCP)
542 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
543 tc->th_dport, tc->th_sport,
544 IPPROTO_TCP, 0);
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);
548 else
549 link = NULL;
550 } else
551 link = NULL;
553 if (link != NULL)
555 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
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 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)
590 int accumulate;
591 struct in_addr alias_address;
592 u_short alias_id;
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);
627 static int
628 IcmpAliasOut(struct ip *pip)
630 int iresult;
631 struct icmp *ic;
633 /* Return if proxy-only mode is enabled */
634 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
635 return PKT_ALIAS_OK;
637 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
639 iresult = PKT_ALIAS_IGNORED;
640 switch (ic->icmp_type)
642 case ICMP_ECHO:
643 case ICMP_TSTAMP:
644 if (ic->icmp_code == 0)
646 iresult = IcmpAliasOut1(pip);
648 break;
649 case ICMP_UNREACH:
650 case ICMP_SOURCEQUENCH:
651 case ICMP_TIMXCEED:
652 case ICMP_PARAMPROB:
653 iresult = IcmpAliasOut2(pip);
654 break;
655 case ICMP_ECHOREPLY:
656 case ICMP_TSTAMPREPLY:
657 iresult = IcmpAliasOut1(pip);
659 return(iresult);
664 static int
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
671 machine.
673 struct alias_link *link;
675 /* Return if proxy-only mode is enabled */
676 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
677 return PKT_ALIAS_OK;
679 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
680 if (link != NULL)
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);
699 static int
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)
711 return PKT_ALIAS_OK;
713 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
714 if (link != NULL)
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);
733 static int
734 UdpAliasIn(struct ip *pip)
736 struct udphdr *ud;
737 struct alias_link *link;
739 /* Return if proxy-only mode is enabled */
740 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
741 return PKT_ALIAS_OK;
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,
747 IPPROTO_UDP, 1);
748 if (link != NULL)
750 struct in_addr alias_address;
751 struct in_addr original_address;
752 u_short alias_port;
753 int accumulate;
754 int r = 0;
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. */
775 if (ud->uh_sum != 0)
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.
794 if (r < 0)
795 return(PKT_ALIAS_IGNORED);
796 else
797 return(PKT_ALIAS_OK);
799 return(PKT_ALIAS_IGNORED);
802 static int
803 UdpAliasOut(struct ip *pip)
805 struct udphdr *ud;
806 struct alias_link *link;
808 /* Return if proxy-only mode is enabled */
809 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
810 return PKT_ALIAS_OK;
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,
816 IPPROTO_UDP, 1);
817 if (link != NULL)
819 u_short alias_port;
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 */
847 if (ud->uh_sum != 0)
849 int accumulate;
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);
875 static int
876 TcpAliasIn(struct ip *pip)
878 struct tcphdr *tc;
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,
885 IPPROTO_TCP,
886 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
887 if (link != NULL)
889 struct in_addr alias_address;
890 struct in_addr original_address;
891 struct in_addr proxy_address;
892 u_short alias_port;
893 u_short proxy_port;
894 int accumulate;
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 */
917 if (proxy_port != 0)
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)
929 int delta;
931 delta = GetDeltaAckIn(pip, link);
932 if (delta != 0)
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
948 address */
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);
966 static int
967 TcpAliasOut(struct ip *pip, int maxpacketsize)
969 int proxy_type;
970 u_short dest_port;
971 u_short proxy_server_port;
972 struct in_addr dest_address;
973 struct in_addr proxy_server_address;
974 struct tcphdr *tc;
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))
982 return PKT_ALIAS_OK;
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;
988 if (proxy_type != 0)
990 int accumulate;
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,
1007 IPPROTO_TCP, 1);
1008 if (link !=NULL)
1010 u_short alias_port;
1011 struct in_addr alias_address;
1012 int accumulate;
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)
1059 int delta;
1061 delta = GetDeltaSeqOut(pip, link);
1062 if (delta != 0)
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
1088 FragmentIn()
1089 FragmentOut()
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 *);
1104 static int
1105 FragmentIn(struct ip *pip)
1107 struct alias_link *link;
1109 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1110 if (link != NULL)
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);
1127 static int
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()
1152 PacketAliasIn()
1153 PacketAliasOut()
1154 PacketUnaliasOut()
1156 (prototypes in alias.h)
1161 PacketAliasSaveFragment(char *ptr)
1163 int iresult;
1164 struct alias_link *link;
1165 struct ip *pip;
1167 pip = (struct ip *) ptr;
1168 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1169 iresult = PKT_ALIAS_ERROR;
1170 if (link != NULL)
1172 SetFragmentPtr(link, ptr);
1173 iresult = PKT_ALIAS_OK;
1175 return(iresult);
1179 char *
1180 PacketAliasGetFragment(char *ptr)
1182 struct alias_link *link;
1183 char *fptr;
1184 struct ip *pip;
1186 pip = (struct ip *) ptr;
1187 link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1188 if (link != NULL)
1190 GetFragmentPtr(link, &fptr);
1191 SetFragmentPtr(link, NULL);
1192 SetExpire(link, 0); /* Deletes link */
1194 return(fptr);
1196 else
1198 return(NULL);
1203 void
1204 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased
1205 header fragment */
1206 char *ptr_fragment /* Points to fragment which must
1207 be de-aliased */
1210 struct ip *pip;
1211 struct ip *fpip;
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;
1228 struct ip *pip;
1229 int iresult;
1231 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1232 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1233 iresult = PacketAliasOut(ptr, maxpacketsize);
1234 packetAliasMode |= PKT_ALIAS_REVERSE;
1235 return iresult;
1238 HouseKeeping();
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 )
1251 switch (pip->ip_p)
1253 case IPPROTO_ICMP:
1254 iresult = IcmpAliasIn(pip);
1255 break;
1256 case IPPROTO_UDP:
1257 iresult = UdpAliasIn(pip);
1258 break;
1259 case IPPROTO_TCP:
1260 iresult = TcpAliasIn(pip);
1261 break;
1262 case IPPROTO_GRE:
1263 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1264 AliasHandlePptpGreIn(pip) == 0)
1265 iresult = PKT_ALIAS_OK;
1266 else
1267 iresult = ProtoAliasIn(pip);
1268 break;
1269 default:
1270 iresult = ProtoAliasIn(pip);
1271 break;
1274 if (ntohs(pip->ip_off) & IP_MF)
1276 struct alias_link *link;
1278 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1279 if (link != NULL)
1281 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1282 SetFragmentAddr(link, pip->ip_dst);
1284 else
1286 iresult = PKT_ALIAS_ERROR;
1290 else
1292 iresult = FragmentIn(pip);
1295 return(iresult);
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) */
1320 int iresult;
1321 struct in_addr addr_save;
1322 struct ip *pip;
1324 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1325 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1326 iresult = PacketAliasIn(ptr, maxpacketsize);
1327 packetAliasMode |= PKT_ALIAS_REVERSE;
1328 return iresult;
1331 HouseKeeping();
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)
1343 u_long addr;
1344 int iclass;
1346 iclass = 0;
1347 addr = ntohl(pip->ip_src.s_addr);
1348 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1349 iclass = 3;
1350 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1351 iclass = 2;
1352 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1353 iclass = 1;
1355 if (iclass == 0)
1357 SetDefaultAliasAddress(pip->ip_src);
1361 iresult = PKT_ALIAS_IGNORED;
1362 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1364 switch (pip->ip_p)
1366 case IPPROTO_ICMP:
1367 iresult = IcmpAliasOut(pip);
1368 break;
1369 case IPPROTO_UDP:
1370 iresult = UdpAliasOut(pip);
1371 break;
1372 case IPPROTO_TCP:
1373 iresult = TcpAliasOut(pip, maxpacketsize);
1374 break;
1375 case IPPROTO_GRE:
1376 if (AliasHandlePptpGreOut(pip) == 0)
1377 iresult = PKT_ALIAS_OK;
1378 else
1379 iresult = ProtoAliasOut(pip);
1380 break;
1381 default:
1382 iresult = ProtoAliasOut(pip);
1383 break;
1386 else
1388 iresult = FragmentOut(pip);
1391 SetDefaultAliasAddress(addr_save);
1392 return(iresult);
1396 PacketUnaliasOut(char *ptr, /* valid IP packet */
1397 int maxpacketsize /* for error checking */
1400 struct ip *pip;
1401 struct icmp *ic;
1402 struct udphdr *ud;
1403 struct tcphdr *tc;
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)
1412 return(iresult);
1414 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1415 tc = (struct tcphdr *) ud;
1416 ic = (struct icmp *) ud;
1418 /* Find a link */
1419 if (pip->ip_p == IPPROTO_UDP)
1420 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1421 ud->uh_dport, ud->uh_sport,
1422 IPPROTO_UDP, 0);
1423 else if (pip->ip_p == IPPROTO_TCP)
1424 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1425 tc->th_dport, tc->th_sport,
1426 IPPROTO_TCP, 0);
1427 else if (pip->ip_p == IPPROTO_ICMP)
1428 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1429 else
1430 link = NULL;
1432 /* Change it from an aliased packet to an unaliased packet */
1433 if (link != NULL)
1435 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1437 int accumulate;
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);
1452 } else {
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;
1468 else
1469 tc->th_sport = original_port;
1471 iresult = PKT_ALIAS_OK;
1473 } else if (pip->ip_p == IPPROTO_ICMP) {
1475 int accumulate;
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;
1502 return(iresult);