xref: /dragonfly/lib/libalias/alias.c (revision d4ef6694)
1 /* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
2 
3 /*-
4  * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5  * All rights reserved.
6  *
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.
15  *
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.
27  *
28  * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.11 2002/07/25 12:31:37 ru Exp $
29  */
30 
31 /*
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.
38 
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.
47 
48     Version 1.0 August, 1996  (cjm)
49 
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.)
54 
55     Version 1.2 September 7, 1996 (cjm)
56         Fragment handling error in alias_db.c corrected.
57         (Tom Torrance helped fix this problem.)
58 
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.
68 
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.)
72 
73     Version 1.6 September 18, 1996 (cjm)
74         Simplified ICMP aliasing scheme.  Should now support
75         traceroute from Win95 as well as FreeBSD.
76 
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).
87 
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).
95 
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.
101 
102     Version 2.3 Dec 1998 (dillon)
103 	- Major bounds checking additions, see FreeBSD/CVS
104 
105     Version 3.1 May, 2000 (salander)
106 	- Added hooks to handle PPTP.
107 
108     Version 3.2 July, 2000 (salander and satoh)
109 	- Added PacketUnaliasOut routine.
110 	- Added hooks to handle RTSP/RTP.
111 
112     See HISTORY file for additional revisions.
113 */
114 
115 #include <sys/param.h>
116 
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>
123 
124 #include <stdio.h>
125 
126 #include "alias_local.h"
127 #include "alias.h"
128 
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
139 
140 static __inline int
141 twowords(void *p)
142 {
143     uint8_t *c = p;
144 
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);
153 }
154 
155 /* TCP Handling Routines
156 
157     TcpMonitorIn()  -- These routines monitor TCP connections, and
158     TcpMonitorOut()    delete a link when a connection is closed.
159 
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.
164 */
165 
166 /* Local prototypes */
167 static void TcpMonitorIn(struct ip *, struct alias_link *);
168 
169 static void TcpMonitorOut(struct ip *, struct alias_link *);
170 
171 
172 static void
173 TcpMonitorIn(struct ip *pip, struct alias_link *link)
174 {
175     struct tcphdr *tc;
176 
177     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
178 
179     switch (GetStateIn(link))
180     {
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;
191     }
192 }
193 
194 static void
195 TcpMonitorOut(struct ip *pip, struct alias_link *link)
196 {
197     struct tcphdr *tc;
198 
199     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
200 
201     switch (GetStateOut(link))
202     {
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;
213     }
214 }
215 
216 
217 
218 
219 
220 /* Protocol Specific Packet Aliasing Routines
221 
222     IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
223     IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
224     ProtoAliasIn(), ProtoAliasOut()
225     UdpAliasIn(), UdpAliasOut()
226     TcpAliasIn(), TcpAliasOut()
227 
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.
233 
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.
237 
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.
241 
242 ICMP error messages are handled by looking at the IP fragment
243 in the data section of the message.
244 
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).
250 
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.
254 
255 All packets go through the aliasing mechanism, whether they come from
256 the gateway machine or other machines on a local area network.
257 */
258 
259 
260 /* Local prototypes */
261 static int IcmpAliasIn1(struct ip *);
262 static int IcmpAliasIn2(struct ip *);
263 static int IcmpAliasIn (struct ip *);
264 
265 static int IcmpAliasOut1(struct ip *);
266 static int IcmpAliasOut2(struct ip *);
267 static int IcmpAliasOut (struct ip *);
268 
269 static int ProtoAliasIn(struct ip *);
270 static int ProtoAliasOut(struct ip *);
271 
272 static int UdpAliasOut(struct ip *);
273 static int UdpAliasIn (struct ip *);
274 
275 static int TcpAliasOut(struct ip *, int);
276 static int TcpAliasIn (struct ip *);
277 
278 
279 static int
280 IcmpAliasIn1(struct ip *pip)
281 {
282 /*
283     De-alias incoming echo and timestamp replies.
284     Alias incoming echo and timestamp requests.
285 */
286     struct alias_link *link;
287     struct icmp *ic;
288 
289     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
290 
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)
294     {
295         u_short original_id;
296         int accumulate;
297 
298         original_id = GetOriginalPort(link);
299 
300 /* Adjust ICMP checksum */
301         accumulate  = ic->icmp_id;
302         accumulate -= original_id;
303         ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
304 
305 /* Put original sequence number back in */
306         ic->icmp_id = original_id;
307 
308 /* Put original address back into IP header */
309         {
310             struct in_addr original_address;
311 
312             original_address = GetOriginalAddress(link);
313             DifferentialChecksum(&pip->ip_sum,
314                                  (u_short *) &original_address,
315                                  (u_short *) &pip->ip_dst,
316                                  2);
317             pip->ip_dst = original_address;
318         }
319 
320         return(PKT_ALIAS_OK);
321     }
322     return(PKT_ALIAS_IGNORED);
323 }
324 
325 static int
326 IcmpAliasIn2(struct ip *pip)
327 {
328 /*
329     Alias incoming ICMP error messages containing
330     IP header and first 64 bits of datagram.
331 */
332     struct ip *ip;
333     struct icmp *ic, *ic2;
334     struct udphdr *ud;
335     struct tcphdr *tc;
336     struct alias_link *link;
337 
338     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
339     ip = &ic->icmp_ip;
340 
341     ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
342     tc = (struct tcphdr *) ud;
343     ic2 = (struct icmp *) ud;
344 
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;
360 
361     if (link != NULL)
362     {
363         if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
364         {
365             int accumulate, accumulate2;
366             struct in_addr original_address;
367             u_short original_port;
368 
369             original_address = GetOriginalAddress(link);
370             original_port = GetOriginalPort(link);
371 
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);
382 
383 /* Un-alias address in IP header */
384             DifferentialChecksum(&pip->ip_sum,
385                                  (u_short *) &original_address,
386                                  (u_short *) &pip->ip_dst,
387                                  2);
388             pip->ip_dst = original_address;
389 
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;
394         }
395         else if (ip->ip_p == IPPROTO_ICMP)
396         {
397             int accumulate, accumulate2;
398             struct in_addr original_address;
399             u_short original_id;
400 
401             original_address = GetOriginalAddress(link);
402             original_id = GetOriginalPort(link);
403 
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);
414 
415 /* Un-alias address in IP header */
416             DifferentialChecksum(&pip->ip_sum,
417                                  (u_short *) &original_address,
418                                  (u_short *) &pip->ip_dst,
419                                  2);
420             pip->ip_dst = original_address;
421 
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;
426         }
427         return(PKT_ALIAS_OK);
428     }
429     return(PKT_ALIAS_IGNORED);
430 }
431 
432 
433 static int
434 IcmpAliasIn(struct ip *pip)
435 {
436     int iresult;
437     struct icmp *ic;
438 
439 /* Return if proxy-only mode is enabled */
440     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
441         return PKT_ALIAS_OK;
442 
443     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
444 
445     iresult = PKT_ALIAS_IGNORED;
446     switch (ic->icmp_type)
447     {
448         case ICMP_ECHOREPLY:
449         case ICMP_TSTAMPREPLY:
450             if (ic->icmp_code == 0)
451             {
452                 iresult = IcmpAliasIn1(pip);
453             }
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;
465     }
466     return(iresult);
467 }
468 
469 
470 static int
471 IcmpAliasOut1(struct ip *pip)
472 {
473 /*
474     Alias outgoing echo and timestamp requests.
475     De-alias outgoing echo and timestamp replies.
476 */
477     struct alias_link *link;
478     struct icmp *ic;
479 
480     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
481 
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)
485     {
486         u_short alias_id;
487         int accumulate;
488 
489         alias_id = GetAliasPort(link);
490 
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);
495 
496 /* Alias sequence number */
497         ic->icmp_id = alias_id;
498 
499 /* Change source address */
500         {
501             struct in_addr alias_address;
502 
503             alias_address = GetAliasAddress(link);
504             DifferentialChecksum(&pip->ip_sum,
505                                  (u_short *) &alias_address,
506                                  (u_short *) &pip->ip_src,
507                                  2);
508             pip->ip_src = alias_address;
509         }
510 
511         return(PKT_ALIAS_OK);
512     }
513     return(PKT_ALIAS_IGNORED);
514 }
515 
516 
517 static int
518 IcmpAliasOut2(struct ip *pip)
519 {
520 /*
521     Alias outgoing ICMP error messages containing
522     IP header and first 64 bits of datagram.
523 */
524     struct ip *ip;
525     struct icmp *ic, *ic2;
526     struct udphdr *ud;
527     struct tcphdr *tc;
528     struct alias_link *link;
529 
530     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
531     ip = &ic->icmp_ip;
532 
533     ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
534     tc = (struct tcphdr *) ud;
535     ic2 = (struct icmp *) ud;
536 
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;
552 
553     if (link != NULL)
554     {
555         if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
556         {
557             int accumulate;
558             struct in_addr alias_address;
559             u_short alias_port;
560 
561             alias_address = GetAliasAddress(link);
562             alias_port = GetAliasPort(link);
563 
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);
570 
571 /*
572  * Alias address in IP header if it comes from the host
573  * the original TCP/UDP packet was destined for.
574  */
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,
579 				     2);
580 		pip->ip_src = alias_address;
581 	    }
582 
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;
587         }
588         else if (ip->ip_p == IPPROTO_ICMP)
589         {
590             int accumulate;
591             struct in_addr alias_address;
592             u_short alias_id;
593 
594             alias_address = GetAliasAddress(link);
595             alias_id = GetAliasPort(link);
596 
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);
603 
604 /*
605  * Alias address in IP header if it comes from the host
606  * the original ICMP message was destined for.
607  */
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,
612 				     2);
613 		pip->ip_src = alias_address;
614 	    }
615 
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;
620         }
621         return(PKT_ALIAS_OK);
622     }
623     return(PKT_ALIAS_IGNORED);
624 }
625 
626 
627 static int
628 IcmpAliasOut(struct ip *pip)
629 {
630     int iresult;
631     struct icmp *ic;
632 
633 /* Return if proxy-only mode is enabled */
634     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
635         return PKT_ALIAS_OK;
636 
637     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
638 
639     iresult = PKT_ALIAS_IGNORED;
640     switch (ic->icmp_type)
641     {
642         case ICMP_ECHO:
643         case ICMP_TSTAMP:
644             if (ic->icmp_code == 0)
645             {
646                 iresult = IcmpAliasOut1(pip);
647             }
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);
658     }
659     return(iresult);
660 }
661 
662 
663 
664 static int
665 ProtoAliasIn(struct ip *pip)
666 {
667 /*
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.
672 */
673     struct alias_link *link;
674 
675 /* Return if proxy-only mode is enabled */
676     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
677         return PKT_ALIAS_OK;
678 
679     link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
680     if (link != NULL)
681     {
682         struct in_addr original_address;
683 
684         original_address = GetOriginalAddress(link);
685 
686 /* Restore original IP address */
687         DifferentialChecksum(&pip->ip_sum,
688                              (u_short *) &original_address,
689                              (u_short *) &pip->ip_dst,
690                              2);
691         pip->ip_dst = original_address;
692 
693 	return(PKT_ALIAS_OK);
694     }
695     return(PKT_ALIAS_IGNORED);
696 }
697 
698 
699 static int
700 ProtoAliasOut(struct ip *pip)
701 {
702 /*
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.
706 */
707     struct alias_link *link;
708 
709 /* Return if proxy-only mode is enabled */
710     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
711         return PKT_ALIAS_OK;
712 
713     link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
714     if (link != NULL)
715     {
716         struct in_addr alias_address;
717 
718         alias_address = GetAliasAddress(link);
719 
720 /* Change source address */
721         DifferentialChecksum(&pip->ip_sum,
722                              (u_short *) &alias_address,
723                              (u_short *) &pip->ip_src,
724                              2);
725         pip->ip_src = alias_address;
726 
727         return(PKT_ALIAS_OK);
728     }
729     return(PKT_ALIAS_IGNORED);
730 }
731 
732 
733 static int
734 UdpAliasIn(struct ip *pip)
735 {
736     struct udphdr *ud;
737     struct alias_link *link;
738 
739 /* Return if proxy-only mode is enabled */
740     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
741         return PKT_ALIAS_OK;
742 
743     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
744 
745     link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
746                         ud->uh_sport, ud->uh_dport,
747                         IPPROTO_UDP, 1);
748     if (link != NULL)
749     {
750         struct in_addr alias_address;
751         struct in_addr original_address;
752         u_short alias_port;
753         int accumulate;
754 	int r = 0;
755 
756         alias_address = GetAliasAddress(link);
757         original_address = GetOriginalAddress(link);
758         alias_port = ud->uh_dport;
759         ud->uh_dport = GetOriginalPort(link);
760 
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);
772 
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)
776         {
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);
782         }
783 
784 /* Restore original IP address */
785         DifferentialChecksum(&pip->ip_sum,
786                              (u_short *) &original_address,
787                              (u_short *) &pip->ip_dst,
788                              2);
789         pip->ip_dst = original_address;
790 
791 	/*
792 	 * If we cannot figure out the packet, ignore it.
793 	 */
794 	if (r < 0)
795 	    return(PKT_ALIAS_IGNORED);
796 	else
797 	    return(PKT_ALIAS_OK);
798     }
799     return(PKT_ALIAS_IGNORED);
800 }
801 
802 static int
803 UdpAliasOut(struct ip *pip)
804 {
805     struct udphdr *ud;
806     struct alias_link *link;
807 
808 /* Return if proxy-only mode is enabled */
809     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
810         return PKT_ALIAS_OK;
811 
812     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
813 
814     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
815                          ud->uh_sport, ud->uh_dport,
816                          IPPROTO_UDP, 1);
817     if (link != NULL)
818     {
819         u_short alias_port;
820         struct in_addr alias_address;
821 
822         alias_address = GetAliasAddress(link);
823         alias_port = GetAliasPort(link);
824 
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);
836 /*
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.
840  */
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);
844 
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)
848         {
849             int accumulate;
850 
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);
856         }
857 
858 /* Put alias port in UDP header */
859         ud->uh_sport = alias_port;
860 
861 /* Change source address */
862         DifferentialChecksum(&pip->ip_sum,
863                              (u_short *) &alias_address,
864                              (u_short *) &pip->ip_src,
865                              2);
866         pip->ip_src = alias_address;
867 
868         return(PKT_ALIAS_OK);
869     }
870     return(PKT_ALIAS_IGNORED);
871 }
872 
873 
874 
875 static int
876 TcpAliasIn(struct ip *pip)
877 {
878     struct tcphdr *tc;
879     struct alias_link *link;
880 
881     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
882 
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)
888     {
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;
895 
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);
900 
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);
907 
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);
914 
915 /* If this is a proxy, then modify the TCP source port and
916    checksum accumulation */
917         if (proxy_port != 0)
918         {
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);
924         }
925 
926 /* See if ACK number needs to be modified */
927         if (GetAckModified(link) == 1)
928         {
929             int delta;
930 
931             delta = GetDeltaAckIn(pip, link);
932             if (delta != 0)
933             {
934                 accumulate += twowords(&tc->th_ack);
935                 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
936                 accumulate -= twowords(&tc->th_ack);
937             }
938         }
939 
940         ADJUST_CHECKSUM(accumulate, tc->th_sum);
941 
942 /* Restore original IP address */
943         accumulate  = twowords(&pip->ip_dst);
944         pip->ip_dst = original_address;
945         accumulate -= twowords(&pip->ip_dst);
946 
947 /* If this is a transparent proxy packet, then modify the source
948    address */
949         if (proxy_address.s_addr != 0)
950         {
951 	  accumulate += twowords(&pip->ip_src);
952 	  pip->ip_src = proxy_address;
953 	  accumulate -= twowords(&pip->ip_src);
954         }
955 
956         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
957 
958 /* Monitor TCP connection state */
959         TcpMonitorIn(pip, link);
960 
961         return(PKT_ALIAS_OK);
962     }
963     return(PKT_ALIAS_IGNORED);
964 }
965 
966 static int
967 TcpAliasOut(struct ip *pip, int maxpacketsize)
968 {
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;
976 
977     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
978 
979     proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
980 
981     if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
982         return PKT_ALIAS_OK;
983 
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)
989     {
990         int accumulate;
991 
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);
998 
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);
1003     }
1004 
1005     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1006                          tc->th_sport, tc->th_dport,
1007                          IPPROTO_TCP, 1);
1008     if (link !=NULL)
1009     {
1010         u_short alias_port;
1011         struct in_addr alias_address;
1012         int accumulate;
1013 
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)
1018         {
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));
1023         }
1024 
1025 /* Get alias address and port */
1026         alias_port = GetAliasPort(link);
1027         alias_address = GetAliasAddress(link);
1028 
1029 /* Monitor TCP connection state */
1030         TcpMonitorOut(pip, link);
1031 
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);
1047 
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);
1055 
1056 /* Modify sequence number if necessary */
1057         if (GetAckModified(link) == 1)
1058         {
1059             int delta;
1060 
1061             delta = GetDeltaSeqOut(pip, link);
1062             if (delta != 0)
1063             {
1064                 accumulate += twowords(&tc->th_seq);
1065                 tc->th_seq  = htonl(ntohl(tc->th_seq) + delta);
1066                 accumulate -= twowords(&tc->th_seq);
1067             }
1068         }
1069 
1070         ADJUST_CHECKSUM(accumulate, tc->th_sum);
1071 
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);
1077 
1078         return(PKT_ALIAS_OK);
1079     }
1080     return(PKT_ALIAS_IGNORED);
1081 }
1082 
1083 
1084 
1085 
1086 /* Fragment Handling
1087 
1088     FragmentIn()
1089     FragmentOut()
1090 
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.
1097 */
1098 
1099 /* Local prototypes */
1100 static int FragmentIn(struct ip *);
1101 static int FragmentOut(struct ip *);
1102 
1103 
1104 static int
1105 FragmentIn(struct ip *pip)
1106 {
1107     struct alias_link *link;
1108 
1109     link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1110     if (link != NULL)
1111     {
1112         struct in_addr original_address;
1113 
1114         GetFragmentAddr(link, &original_address);
1115         DifferentialChecksum(&pip->ip_sum,
1116                              (u_short *) &original_address,
1117                              (u_short *) &pip->ip_dst,
1118                              2);
1119         pip->ip_dst = original_address;
1120 
1121         return(PKT_ALIAS_OK);
1122     }
1123     return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1124 }
1125 
1126 
1127 static int
1128 FragmentOut(struct ip *pip)
1129 {
1130     struct in_addr alias_address;
1131 
1132     alias_address = FindAliasAddress(pip->ip_src);
1133     DifferentialChecksum(&pip->ip_sum,
1134                          (u_short *) &alias_address,
1135                          (u_short *) &pip->ip_src,
1136                           2);
1137     pip->ip_src = alias_address;
1138 
1139     return(PKT_ALIAS_OK);
1140 }
1141 
1142 
1143 
1144 
1145 
1146 
1147 /* Outside World Access
1148 
1149         PacketAliasSaveFragment()
1150         PacketAliasGetFragment()
1151         PacketAliasFragmentIn()
1152         PacketAliasIn()
1153         PacketAliasOut()
1154         PacketUnaliasOut()
1155 
1156 (prototypes in alias.h)
1157 */
1158 
1159 
1160 int
1161 PacketAliasSaveFragment(char *ptr)
1162 {
1163     int iresult;
1164     struct alias_link *link;
1165     struct ip *pip;
1166 
1167     pip = (struct ip *) ptr;
1168     link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1169     iresult = PKT_ALIAS_ERROR;
1170     if (link != NULL)
1171     {
1172         SetFragmentPtr(link, ptr);
1173         iresult = PKT_ALIAS_OK;
1174     }
1175     return(iresult);
1176 }
1177 
1178 
1179 char *
1180 PacketAliasGetFragment(char *ptr)
1181 {
1182     struct alias_link *link;
1183     char *fptr;
1184     struct ip *pip;
1185 
1186     pip = (struct ip *) ptr;
1187     link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1188     if (link != NULL)
1189     {
1190         GetFragmentPtr(link, &fptr);
1191         SetFragmentPtr(link, NULL);
1192         SetExpire(link, 0); /* Deletes link */
1193 
1194         return(fptr);
1195     }
1196     else
1197     {
1198         return(NULL);
1199     }
1200 }
1201 
1202 
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   */
1208                      )
1209 {
1210     struct ip *pip;
1211     struct ip *fpip;
1212 
1213     pip = (struct ip *) ptr;
1214     fpip = (struct ip *) ptr_fragment;
1215 
1216     DifferentialChecksum(&fpip->ip_sum,
1217                          (u_short *) &pip->ip_dst,
1218                          (u_short *) &fpip->ip_dst,
1219                          2);
1220     fpip->ip_dst = pip->ip_dst;
1221 }
1222 
1223 
1224 int
1225 PacketAliasIn(char *ptr, int maxpacketsize)
1226 {
1227     struct in_addr alias_addr;
1228     struct ip *pip;
1229     int iresult;
1230 
1231     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1232         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1233         iresult = PacketAliasOut(ptr, maxpacketsize);
1234         packetAliasMode |= PKT_ALIAS_REVERSE;
1235         return iresult;
1236     }
1237 
1238     HouseKeeping();
1239     ClearCheckNewLink();
1240     pip = (struct ip *) ptr;
1241     alias_addr = pip->ip_dst;
1242 
1243     /* Defense against mangled packets */
1244     if (ntohs(pip->ip_len) > maxpacketsize
1245      || (pip->ip_hl<<2) > maxpacketsize)
1246         return PKT_ALIAS_IGNORED;
1247 
1248     iresult = PKT_ALIAS_IGNORED;
1249     if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1250     {
1251         switch (pip->ip_p)
1252         {
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;
1272         }
1273 
1274         if (ntohs(pip->ip_off) & IP_MF)
1275         {
1276             struct alias_link *link;
1277 
1278             link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1279             if (link != NULL)
1280             {
1281                 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1282                 SetFragmentAddr(link, pip->ip_dst);
1283             }
1284             else
1285             {
1286                 iresult = PKT_ALIAS_ERROR;
1287             }
1288         }
1289     }
1290     else
1291     {
1292         iresult = FragmentIn(pip);
1293     }
1294 
1295     return(iresult);
1296 }
1297 
1298 
1299 
1300 /* Unregistered address ranges */
1301 
1302 /* 10.0.0.0   ->   10.255.255.255 */
1303 #define UNREG_ADDR_A_LOWER 0x0a000000
1304 #define UNREG_ADDR_A_UPPER 0x0affffff
1305 
1306 /* 172.16.0.0  ->  172.31.255.255 */
1307 #define UNREG_ADDR_B_LOWER 0xac100000
1308 #define UNREG_ADDR_B_UPPER 0xac1fffff
1309 
1310 /* 192.168.0.0 -> 192.168.255.255 */
1311 #define UNREG_ADDR_C_LOWER 0xc0a80000
1312 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1313 
1314 int
1315 PacketAliasOut(char *ptr,           /* valid IP packet */
1316                int  maxpacketsize   /* How much the packet data may grow
1317                                        (FTP and IRC inline changes) */
1318               )
1319 {
1320     int iresult;
1321     struct in_addr addr_save;
1322     struct ip *pip;
1323 
1324     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1325         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1326         iresult = PacketAliasIn(ptr, maxpacketsize);
1327         packetAliasMode |= PKT_ALIAS_REVERSE;
1328         return iresult;
1329     }
1330 
1331     HouseKeeping();
1332     ClearCheckNewLink();
1333     pip = (struct ip *) ptr;
1334 
1335     /* Defense against mangled packets */
1336     if (ntohs(pip->ip_len) > maxpacketsize
1337      || (pip->ip_hl<<2) > maxpacketsize)
1338         return PKT_ALIAS_IGNORED;
1339 
1340     addr_save = GetDefaultAliasAddress();
1341     if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1342     {
1343         u_long addr;
1344         int iclass;
1345 
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;
1354 
1355         if (iclass == 0)
1356         {
1357             SetDefaultAliasAddress(pip->ip_src);
1358         }
1359     }
1360 
1361     iresult = PKT_ALIAS_IGNORED;
1362     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1363     {
1364         switch (pip->ip_p)
1365         {
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;
1384         }
1385     }
1386     else
1387     {
1388         iresult = FragmentOut(pip);
1389     }
1390 
1391     SetDefaultAliasAddress(addr_save);
1392     return(iresult);
1393 }
1394 
1395 int
1396 PacketUnaliasOut(char *ptr,           /* valid IP packet */
1397                  int  maxpacketsize   /* for error checking */
1398                 )
1399 {
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;
1406 
1407     pip = (struct ip *) ptr;
1408 
1409     /* Defense against mangled packets */
1410     if (ntohs(pip->ip_len) > maxpacketsize
1411      || (pip->ip_hl<<2) > maxpacketsize)
1412         return(iresult);
1413 
1414     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1415     tc = (struct tcphdr *) ud;
1416     ic = (struct icmp *) ud;
1417 
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;
1431 
1432     /* Change it from an aliased packet to an unaliased packet */
1433     if (link != NULL)
1434     {
1435         if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1436         {
1437             int 	   accumulate;
1438             struct in_addr original_address;
1439             u_short        original_port;
1440 
1441             original_address = GetOriginalAddress(link);
1442             original_port = GetOriginalPort(link);
1443 
1444             /* Adjust TCP/UDP checksum */
1445             accumulate  = twowords(&pip->ip_src);
1446             accumulate -= twowords(&original_address);
1447 
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);
1456 	    }
1457 
1458             /* Adjust IP checksum */
1459             DifferentialChecksum(&pip->ip_sum,
1460                                  (u_short *) &original_address,
1461                                  (u_short *) &pip->ip_src,
1462                                  2);
1463 
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;
1470 
1471 	    iresult = PKT_ALIAS_OK;
1472 
1473         } else if (pip->ip_p == IPPROTO_ICMP) {
1474 
1475             int            accumulate;
1476             struct in_addr original_address;
1477             u_short        original_id;
1478 
1479             original_address = GetOriginalAddress(link);
1480             original_id = GetOriginalPort(link);
1481 
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);
1488 
1489             /* Adjust IP checksum */
1490             DifferentialChecksum(&pip->ip_sum,
1491                                  (u_short *) &original_address,
1492                                  (u_short *) &pip->ip_src,
1493                                  2);
1494 
1495             /* Un-alias source address and port number */
1496             pip->ip_src = original_address;
1497             ic->icmp_id = original_id;
1498 
1499 	    iresult = PKT_ALIAS_OK;
1500         }
1501     }
1502     return(iresult);
1503 
1504 }
1505