xref: /freebsd/sys/netinet/libalias/alias.c (revision 0986ab12e44caea472245845f9a89ced4f137d73)
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 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 /*
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.
39 
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.
48 
49     Version 1.0 August, 1996  (cjm)
50 
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.)
55 
56     Version 1.2 September 7, 1996 (cjm)
57         Fragment handling error in alias_db.c corrected.
58         (Tom Torrance helped fix this problem.)
59 
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.
69 
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.)
73 
74     Version 1.6 September 18, 1996 (cjm)
75         Simplified ICMP aliasing scheme.  Should now support
76         traceroute from Win95 as well as FreeBSD.
77 
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).
88 
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).
96 
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.
102 
103     Version 2.3 Dec 1998 (dillon)
104 	- Major bounds checking additions, see FreeBSD/CVS
105 
106     Version 3.1 May, 2000 (salander)
107 	- Added hooks to handle PPTP.
108 
109     Version 3.2 July, 2000 (salander and satoh)
110 	- Added PacketUnaliasOut routine.
111 	- Added hooks to handle RTSP/RTP.
112 
113     See HISTORY file for additional revisions.
114 */
115 
116 #include <sys/types.h>
117 
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>
124 
125 #include <stdio.h>
126 
127 #include "alias_local.h"
128 #include "alias.h"
129 
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
140 
141 
142 
143 
144 /* TCP Handling Routines
145 
146     TcpMonitorIn()  -- These routines monitor TCP connections, and
147     TcpMonitorOut()    delete a link when a connection is closed.
148 
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.
153 */
154 
155 /* Local prototypes */
156 static void TcpMonitorIn(struct ip *, struct alias_link *);
157 
158 static void TcpMonitorOut(struct ip *, struct alias_link *);
159 
160 
161 static void
162 TcpMonitorIn(struct ip *pip, struct alias_link *link)
163 {
164     struct tcphdr *tc;
165 
166     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
167 
168     switch (GetStateIn(link))
169     {
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;
180     }
181 }
182 
183 static void
184 TcpMonitorOut(struct ip *pip, struct alias_link *link)
185 {
186     struct tcphdr *tc;
187 
188     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
189 
190     switch (GetStateOut(link))
191     {
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;
202     }
203 }
204 
205 
206 
207 
208 
209 /* Protocol Specific Packet Aliasing Routines
210 
211     IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
212     IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
213     ProtoAliasIn(), ProtoAliasOut()
214     UdpAliasIn(), UdpAliasOut()
215     TcpAliasIn(), TcpAliasOut()
216 
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.
222 
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.
226 
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.
230 
231 ICMP error messages are handled by looking at the IP fragment
232 in the data section of the message.
233 
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).
239 
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.
243 
244 All packets go through the aliasing mechanism, whether they come from
245 the gateway machine or other machines on a local area network.
246 */
247 
248 
249 /* Local prototypes */
250 static int IcmpAliasIn1(struct ip *);
251 static int IcmpAliasIn2(struct ip *);
252 static int IcmpAliasIn (struct ip *);
253 
254 static int IcmpAliasOut1(struct ip *);
255 static int IcmpAliasOut2(struct ip *);
256 static int IcmpAliasOut (struct ip *);
257 
258 static int ProtoAliasIn(struct ip *);
259 static int ProtoAliasOut(struct ip *);
260 
261 static int UdpAliasOut(struct ip *);
262 static int UdpAliasIn (struct ip *);
263 
264 static int TcpAliasOut(struct ip *, int);
265 static int TcpAliasIn (struct ip *);
266 
267 
268 static int
269 IcmpAliasIn1(struct ip *pip)
270 {
271 /*
272     De-alias incoming echo and timestamp replies.
273     Alias incoming echo and timestamp requests.
274 */
275     struct alias_link *link;
276     struct icmp *ic;
277 
278     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
279 
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)
283     {
284         u_short original_id;
285         int accumulate;
286 
287         original_id = GetOriginalPort(link);
288 
289 /* Adjust ICMP checksum */
290         accumulate  = ic->icmp_id;
291         accumulate -= original_id;
292         ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
293 
294 /* Put original sequence number back in */
295         ic->icmp_id = original_id;
296 
297 /* Put original address back into IP header */
298         {
299             struct in_addr original_address;
300 
301             original_address = GetOriginalAddress(link);
302             DifferentialChecksum(&pip->ip_sum,
303                                  (u_short *) &original_address,
304                                  (u_short *) &pip->ip_dst,
305                                  2);
306             pip->ip_dst = original_address;
307         }
308 
309         return(PKT_ALIAS_OK);
310     }
311     return(PKT_ALIAS_IGNORED);
312 }
313 
314 static int
315 IcmpAliasIn2(struct ip *pip)
316 {
317 /*
318     Alias incoming ICMP error messages containing
319     IP header and first 64 bits of datagram.
320 */
321     struct ip *ip;
322     struct icmp *ic, *ic2;
323     struct udphdr *ud;
324     struct tcphdr *tc;
325     struct alias_link *link;
326 
327     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
328     ip = &ic->icmp_ip;
329 
330     ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
331     tc = (struct tcphdr *) ud;
332     ic2 = (struct icmp *) ud;
333 
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;
349 
350     if (link != NULL)
351     {
352         if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
353         {
354             u_short *sptr;
355             int accumulate, accumulate2;
356             struct in_addr original_address;
357             u_short original_port;
358 
359             original_address = GetOriginalAddress(link);
360             original_port = GetOriginalPort(link);
361 
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);
376 
377 /* Un-alias address in IP header */
378             DifferentialChecksum(&pip->ip_sum,
379                                  (u_short *) &original_address,
380                                  (u_short *) &pip->ip_dst,
381                                  2);
382             pip->ip_dst = original_address;
383 
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;
388         }
389         else if (ip->ip_p == IPPROTO_ICMP)
390         {
391             u_short *sptr;
392             int accumulate, accumulate2;
393             struct in_addr original_address;
394             u_short original_id;
395 
396             original_address = GetOriginalAddress(link);
397             original_id = GetOriginalPort(link);
398 
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);
413 
414 /* Un-alias address in IP header */
415             DifferentialChecksum(&pip->ip_sum,
416                                  (u_short *) &original_address,
417                                  (u_short *) &pip->ip_dst,
418                                  2);
419             pip->ip_dst = original_address;
420 
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;
425         }
426         return(PKT_ALIAS_OK);
427     }
428     return(PKT_ALIAS_IGNORED);
429 }
430 
431 
432 static int
433 IcmpAliasIn(struct ip *pip)
434 {
435     int iresult;
436     struct icmp *ic;
437 
438 /* Return if proxy-only mode is enabled */
439     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
440         return PKT_ALIAS_OK;
441 
442     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
443 
444     iresult = PKT_ALIAS_IGNORED;
445     switch (ic->icmp_type)
446     {
447         case ICMP_ECHOREPLY:
448         case ICMP_TSTAMPREPLY:
449             if (ic->icmp_code == 0)
450             {
451                 iresult = IcmpAliasIn1(pip);
452             }
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;
464     }
465     return(iresult);
466 }
467 
468 
469 static int
470 IcmpAliasOut1(struct ip *pip)
471 {
472 /*
473     Alias outgoing echo and timestamp requests.
474     De-alias outgoing echo and timestamp replies.
475 */
476     struct alias_link *link;
477     struct icmp *ic;
478 
479     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
480 
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)
484     {
485         u_short alias_id;
486         int accumulate;
487 
488         alias_id = GetAliasPort(link);
489 
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);
494 
495 /* Alias sequence number */
496         ic->icmp_id = alias_id;
497 
498 /* Change source address */
499         {
500             struct in_addr alias_address;
501 
502             alias_address = GetAliasAddress(link);
503             DifferentialChecksum(&pip->ip_sum,
504                                  (u_short *) &alias_address,
505                                  (u_short *) &pip->ip_src,
506                                  2);
507             pip->ip_src = alias_address;
508         }
509 
510         return(PKT_ALIAS_OK);
511     }
512     return(PKT_ALIAS_IGNORED);
513 }
514 
515 
516 static int
517 IcmpAliasOut2(struct ip *pip)
518 {
519 /*
520     Alias outgoing ICMP error messages containing
521     IP header and first 64 bits of datagram.
522 */
523     struct ip *ip;
524     struct icmp *ic, *ic2;
525     struct udphdr *ud;
526     struct tcphdr *tc;
527     struct alias_link *link;
528 
529     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
530     ip = &ic->icmp_ip;
531 
532     ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
533     tc = (struct tcphdr *) ud;
534     ic2 = (struct icmp *) ud;
535 
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;
551 
552     if (link != NULL)
553     {
554         if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
555         {
556             u_short *sptr;
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             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);
574 
575 /*
576  * Alias address in IP header if it comes from the host
577  * the original TCP/UDP packet was destined for.
578  */
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,
583 				     2);
584 		pip->ip_src = alias_address;
585 	    }
586 
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;
591         }
592         else if (ip->ip_p == IPPROTO_ICMP)
593         {
594             u_short *sptr;
595             int accumulate;
596             struct in_addr alias_address;
597             u_short alias_id;
598 
599             alias_address = GetAliasAddress(link);
600             alias_id = GetAliasPort(link);
601 
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);
612 
613 /*
614  * Alias address in IP header if it comes from the host
615  * the original ICMP message was destined for.
616  */
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,
621 				     2);
622 		pip->ip_src = alias_address;
623 	    }
624 
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;
629         }
630         return(PKT_ALIAS_OK);
631     }
632     return(PKT_ALIAS_IGNORED);
633 }
634 
635 
636 static int
637 IcmpAliasOut(struct ip *pip)
638 {
639     int iresult;
640     struct icmp *ic;
641 
642 /* Return if proxy-only mode is enabled */
643     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
644         return PKT_ALIAS_OK;
645 
646     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
647 
648     iresult = PKT_ALIAS_IGNORED;
649     switch (ic->icmp_type)
650     {
651         case ICMP_ECHO:
652         case ICMP_TSTAMP:
653             if (ic->icmp_code == 0)
654             {
655                 iresult = IcmpAliasOut1(pip);
656             }
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);
667     }
668     return(iresult);
669 }
670 
671 
672 
673 static int
674 ProtoAliasIn(struct ip *pip)
675 {
676 /*
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.
681 */
682     struct alias_link *link;
683 
684 /* Return if proxy-only mode is enabled */
685     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
686         return PKT_ALIAS_OK;
687 
688     link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
689     if (link != NULL)
690     {
691         struct in_addr original_address;
692 
693         original_address = GetOriginalAddress(link);
694 
695 /* Restore original IP address */
696         DifferentialChecksum(&pip->ip_sum,
697                              (u_short *) &original_address,
698                              (u_short *) &pip->ip_dst,
699                              2);
700         pip->ip_dst = original_address;
701 
702 	return(PKT_ALIAS_OK);
703     }
704     return(PKT_ALIAS_IGNORED);
705 }
706 
707 
708 static int
709 ProtoAliasOut(struct ip *pip)
710 {
711 /*
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.
715 */
716     struct alias_link *link;
717 
718 /* Return if proxy-only mode is enabled */
719     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
720         return PKT_ALIAS_OK;
721 
722     link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
723     if (link != NULL)
724     {
725         struct in_addr alias_address;
726 
727         alias_address = GetAliasAddress(link);
728 
729 /* Change source address */
730         DifferentialChecksum(&pip->ip_sum,
731                              (u_short *) &alias_address,
732                              (u_short *) &pip->ip_src,
733                              2);
734         pip->ip_src = alias_address;
735 
736         return(PKT_ALIAS_OK);
737     }
738     return(PKT_ALIAS_IGNORED);
739 }
740 
741 
742 static int
743 UdpAliasIn(struct ip *pip)
744 {
745     struct udphdr *ud;
746     struct alias_link *link;
747 
748 /* Return if proxy-only mode is enabled */
749     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
750         return PKT_ALIAS_OK;
751 
752     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
753 
754     link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
755                         ud->uh_sport, ud->uh_dport,
756                         IPPROTO_UDP, 1);
757     if (link != NULL)
758     {
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;
765 
766         alias_address = GetAliasAddress(link);
767         original_address = GetOriginalAddress(link);
768         alias_port = ud->uh_dport;
769         ud->uh_dport = GetOriginalPort(link);
770 
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);
782 
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)
786         {
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);
796         }
797 
798 /* Restore original IP address */
799         DifferentialChecksum(&pip->ip_sum,
800                              (u_short *) &original_address,
801                              (u_short *) &pip->ip_dst,
802                              2);
803         pip->ip_dst = original_address;
804 
805 	/*
806 	 * If we cannot figure out the packet, ignore it.
807 	 */
808 	if (r < 0)
809 	    return(PKT_ALIAS_IGNORED);
810 	else
811 	    return(PKT_ALIAS_OK);
812     }
813     return(PKT_ALIAS_IGNORED);
814 }
815 
816 static int
817 UdpAliasOut(struct ip *pip)
818 {
819     struct udphdr *ud;
820     struct alias_link *link;
821 
822 /* Return if proxy-only mode is enabled */
823     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
824         return PKT_ALIAS_OK;
825 
826     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
827 
828     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
829                          ud->uh_sport, ud->uh_dport,
830                          IPPROTO_UDP, 1);
831     if (link != NULL)
832     {
833         u_short alias_port;
834         struct in_addr alias_address;
835 
836         alias_address = GetAliasAddress(link);
837         alias_port = GetAliasPort(link);
838 
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);
850 /*
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.
854  */
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);
858 
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)
862         {
863             int accumulate;
864             u_short *sptr;
865 
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);
875         }
876 
877 /* Put alias port in UDP header */
878         ud->uh_sport = alias_port;
879 
880 /* Change source address */
881         DifferentialChecksum(&pip->ip_sum,
882                              (u_short *) &alias_address,
883                              (u_short *) &pip->ip_src,
884                              2);
885         pip->ip_src = alias_address;
886 
887         return(PKT_ALIAS_OK);
888     }
889     return(PKT_ALIAS_IGNORED);
890 }
891 
892 
893 
894 static int
895 TcpAliasIn(struct ip *pip)
896 {
897     struct tcphdr *tc;
898     struct alias_link *link;
899 
900     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
901 
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)
907     {
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;
915 
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);
920         else if (skinnyPort != 0 && (ntohs(tc->th_dport) == skinnyPort
921          || ntohs(tc->th_sport) == skinnyPort))
922             AliasHandleSkinny(pip, link);
923 
924         alias_address = GetAliasAddress(link);
925         original_address = GetOriginalAddress(link);
926         proxy_address = GetProxyAddress(link);
927         alias_port = tc->th_dport;
928         tc->th_dport = GetOriginalPort(link);
929         proxy_port = GetProxyPort(link);
930 
931 /* Adjust TCP checksum since destination port is being unaliased */
932 /* and destination port is being altered.                        */
933         accumulate  = alias_port;
934         accumulate -= tc->th_dport;
935         sptr = (u_short *) &alias_address;
936         accumulate += *sptr++;
937         accumulate += *sptr;
938         sptr = (u_short *) &original_address;
939         accumulate -= *sptr++;
940         accumulate -= *sptr;
941 
942 /* If this is a proxy, then modify the TCP source port and
943    checksum accumulation */
944         if (proxy_port != 0)
945         {
946             accumulate += tc->th_sport;
947             tc->th_sport = proxy_port;
948             accumulate -= tc->th_sport;
949 
950             sptr = (u_short *) &pip->ip_src;
951             accumulate += *sptr++;
952             accumulate += *sptr;
953             sptr = (u_short *) &proxy_address;
954             accumulate -= *sptr++;
955             accumulate -= *sptr;
956         }
957 
958 /* See if ACK number needs to be modified */
959         if (GetAckModified(link) == 1)
960         {
961             int delta;
962 
963             delta = GetDeltaAckIn(pip, link);
964             if (delta != 0)
965             {
966                 sptr = (u_short *) &tc->th_ack;
967                 accumulate += *sptr++;
968                 accumulate += *sptr;
969                 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
970                 sptr = (u_short *) &tc->th_ack;
971                 accumulate -= *sptr++;
972                 accumulate -= *sptr;
973             }
974         }
975 
976         ADJUST_CHECKSUM(accumulate, tc->th_sum);
977 
978 /* Restore original IP address */
979         sptr = (u_short *) &pip->ip_dst;
980         accumulate  = *sptr++;
981         accumulate += *sptr;
982         pip->ip_dst = original_address;
983         sptr = (u_short *) &pip->ip_dst;
984         accumulate -= *sptr++;
985         accumulate -= *sptr;
986 
987 /* If this is a transparent proxy packet, then modify the source
988    address */
989         if (proxy_address.s_addr != 0)
990         {
991             sptr = (u_short *) &pip->ip_src;
992             accumulate += *sptr++;
993             accumulate += *sptr;
994             pip->ip_src = proxy_address;
995             sptr = (u_short *) &pip->ip_src;
996             accumulate -= *sptr++;
997             accumulate -= *sptr;
998         }
999 
1000         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1001 
1002 /* Monitor TCP connection state */
1003         TcpMonitorIn(pip, link);
1004 
1005         return(PKT_ALIAS_OK);
1006     }
1007     return(PKT_ALIAS_IGNORED);
1008 }
1009 
1010 static int
1011 TcpAliasOut(struct ip *pip, int maxpacketsize)
1012 {
1013     int proxy_type;
1014     u_short dest_port;
1015     u_short proxy_server_port;
1016     struct in_addr dest_address;
1017     struct in_addr proxy_server_address;
1018     struct tcphdr *tc;
1019     struct alias_link *link;
1020 
1021     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1022 
1023     proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1024 
1025     if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1026         return PKT_ALIAS_OK;
1027 
1028 /* If this is a transparent proxy, save original destination,
1029    then alter the destination and adjust checksums */
1030     dest_port = tc->th_dport;
1031     dest_address = pip->ip_dst;
1032     if (proxy_type != 0)
1033     {
1034         int accumulate;
1035         u_short *sptr;
1036 
1037         accumulate = tc->th_dport;
1038         tc->th_dport = proxy_server_port;
1039         accumulate -= tc->th_dport;
1040 
1041         sptr = (u_short *) &(pip->ip_dst);
1042         accumulate += *sptr++;
1043         accumulate += *sptr;
1044         sptr = (u_short *) &proxy_server_address;
1045         accumulate -= *sptr++;
1046         accumulate -= *sptr;
1047 
1048         ADJUST_CHECKSUM(accumulate, tc->th_sum);
1049 
1050         sptr = (u_short *) &(pip->ip_dst);
1051         accumulate  = *sptr++;
1052         accumulate += *sptr;
1053         pip->ip_dst = proxy_server_address;
1054         sptr = (u_short *) &(pip->ip_dst);
1055         accumulate -= *sptr++;
1056         accumulate -= *sptr;
1057 
1058         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1059     }
1060 
1061     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1062                          tc->th_sport, tc->th_dport,
1063                          IPPROTO_TCP, 1);
1064     if (link !=NULL)
1065     {
1066         u_short alias_port;
1067         struct in_addr alias_address;
1068         int accumulate;
1069         u_short *sptr;
1070 
1071 /* Save original destination address, if this is a proxy packet.
1072    Also modify packet to include destination encoding.  This may
1073    change the size of IP header. */
1074         if (proxy_type != 0)
1075         {
1076             SetProxyPort(link, dest_port);
1077             SetProxyAddress(link, dest_address);
1078             ProxyModify(link, pip, maxpacketsize, proxy_type);
1079             tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1080         }
1081 
1082 /* Get alias address and port */
1083         alias_port = GetAliasPort(link);
1084         alias_address = GetAliasAddress(link);
1085 
1086 /* Monitor TCP connection state */
1087         TcpMonitorOut(pip, link);
1088 
1089 /* Special processing for IP encoding protocols */
1090         if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1091          || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1092             AliasHandleFtpOut(pip, link, maxpacketsize);
1093         else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1094          || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1095             AliasHandleIrcOut(pip, link, maxpacketsize);
1096         else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1097          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1098          || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1099          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1100             AliasHandleRtspOut(pip, link, maxpacketsize);
1101         else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1102          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1103             AliasHandlePptpOut(pip, link);
1104         else if (skinnyPort != 0 && (ntohs(tc->th_sport) == skinnyPort
1105          || ntohs(tc->th_dport) == skinnyPort))
1106             AliasHandleSkinny(pip, link);
1107 
1108 /* Adjust TCP checksum since source port is being aliased */
1109 /* and source address is being altered                    */
1110         accumulate  = tc->th_sport;
1111         tc->th_sport = alias_port;
1112         accumulate -= tc->th_sport;
1113 
1114         sptr = (u_short *) &(pip->ip_src);
1115         accumulate += *sptr++;
1116         accumulate += *sptr;
1117         sptr = (u_short *) &alias_address;
1118         accumulate -= *sptr++;
1119         accumulate -= *sptr;
1120 
1121 /* Modify sequence number if necessary */
1122         if (GetAckModified(link) == 1)
1123         {
1124             int delta;
1125 
1126             delta = GetDeltaSeqOut(pip, link);
1127             if (delta != 0)
1128             {
1129                 sptr = (u_short *) &tc->th_seq;
1130                 accumulate += *sptr++;
1131                 accumulate += *sptr;
1132                 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1133                 sptr = (u_short *) &tc->th_seq;
1134                 accumulate -= *sptr++;
1135                 accumulate -= *sptr;
1136             }
1137         }
1138 
1139         ADJUST_CHECKSUM(accumulate, tc->th_sum);
1140 
1141 /* Change source address */
1142         sptr = (u_short *) &(pip->ip_src);
1143         accumulate  = *sptr++;
1144         accumulate += *sptr;
1145         pip->ip_src = alias_address;
1146         sptr = (u_short *) &(pip->ip_src);
1147         accumulate -= *sptr++;
1148         accumulate -= *sptr;
1149 
1150         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1151 
1152         return(PKT_ALIAS_OK);
1153     }
1154     return(PKT_ALIAS_IGNORED);
1155 }
1156 
1157 
1158 
1159 
1160 /* Fragment Handling
1161 
1162     FragmentIn()
1163     FragmentOut()
1164 
1165 The packet aliasing module has a limited ability for handling IP
1166 fragments.  If the ICMP, TCP or UDP header is in the first fragment
1167 received, then the ID number of the IP packet is saved, and other
1168 fragments are identified according to their ID number and IP address
1169 they were sent from.  Pointers to unresolved fragments can also be
1170 saved and recalled when a header fragment is seen.
1171 */
1172 
1173 /* Local prototypes */
1174 static int FragmentIn(struct ip *);
1175 static int FragmentOut(struct ip *);
1176 
1177 
1178 static int
1179 FragmentIn(struct ip *pip)
1180 {
1181     struct alias_link *link;
1182 
1183     link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1184     if (link != NULL)
1185     {
1186         struct in_addr original_address;
1187 
1188         GetFragmentAddr(link, &original_address);
1189         DifferentialChecksum(&pip->ip_sum,
1190                              (u_short *) &original_address,
1191                              (u_short *) &pip->ip_dst,
1192                              2);
1193         pip->ip_dst = original_address;
1194 
1195         return(PKT_ALIAS_OK);
1196     }
1197     return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1198 }
1199 
1200 
1201 static int
1202 FragmentOut(struct ip *pip)
1203 {
1204     struct in_addr alias_address;
1205 
1206     alias_address = FindAliasAddress(pip->ip_src);
1207     DifferentialChecksum(&pip->ip_sum,
1208                          (u_short *) &alias_address,
1209                          (u_short *) &pip->ip_src,
1210                           2);
1211     pip->ip_src = alias_address;
1212 
1213     return(PKT_ALIAS_OK);
1214 }
1215 
1216 
1217 
1218 
1219 
1220 
1221 /* Outside World Access
1222 
1223         PacketAliasSaveFragment()
1224         PacketAliasGetFragment()
1225         PacketAliasFragmentIn()
1226         PacketAliasIn()
1227         PacketAliasOut()
1228         PacketUnaliasOut()
1229 
1230 (prototypes in alias.h)
1231 */
1232 
1233 
1234 int
1235 PacketAliasSaveFragment(char *ptr)
1236 {
1237     int iresult;
1238     struct alias_link *link;
1239     struct ip *pip;
1240 
1241     pip = (struct ip *) ptr;
1242     link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1243     iresult = PKT_ALIAS_ERROR;
1244     if (link != NULL)
1245     {
1246         SetFragmentPtr(link, ptr);
1247         iresult = PKT_ALIAS_OK;
1248     }
1249     return(iresult);
1250 }
1251 
1252 
1253 char *
1254 PacketAliasGetFragment(char *ptr)
1255 {
1256     struct alias_link *link;
1257     char *fptr;
1258     struct ip *pip;
1259 
1260     pip = (struct ip *) ptr;
1261     link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1262     if (link != NULL)
1263     {
1264         GetFragmentPtr(link, &fptr);
1265         SetFragmentPtr(link, NULL);
1266         SetExpire(link, 0); /* Deletes link */
1267 
1268         return(fptr);
1269     }
1270     else
1271     {
1272         return(NULL);
1273     }
1274 }
1275 
1276 
1277 void
1278 PacketAliasFragmentIn(char *ptr,          /* Points to correctly de-aliased
1279                                              header fragment */
1280                       char *ptr_fragment  /* Points to fragment which must
1281                                              be de-aliased   */
1282                      )
1283 {
1284     struct ip *pip;
1285     struct ip *fpip;
1286 
1287     pip = (struct ip *) ptr;
1288     fpip = (struct ip *) ptr_fragment;
1289 
1290     DifferentialChecksum(&fpip->ip_sum,
1291                          (u_short *) &pip->ip_dst,
1292                          (u_short *) &fpip->ip_dst,
1293                          2);
1294     fpip->ip_dst = pip->ip_dst;
1295 }
1296 
1297 
1298 int
1299 PacketAliasIn(char *ptr, int maxpacketsize)
1300 {
1301     struct in_addr alias_addr;
1302     struct ip *pip;
1303     int iresult;
1304 
1305     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1306         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1307         iresult = PacketAliasOut(ptr, maxpacketsize);
1308         packetAliasMode |= PKT_ALIAS_REVERSE;
1309         return iresult;
1310     }
1311 
1312     HouseKeeping();
1313     ClearCheckNewLink();
1314     pip = (struct ip *) ptr;
1315     alias_addr = pip->ip_dst;
1316 
1317     /* Defense against mangled packets */
1318     if (ntohs(pip->ip_len) > maxpacketsize
1319      || (pip->ip_hl<<2) > maxpacketsize)
1320         return PKT_ALIAS_IGNORED;
1321 
1322     iresult = PKT_ALIAS_IGNORED;
1323     if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1324     {
1325         switch (pip->ip_p)
1326         {
1327             case IPPROTO_ICMP:
1328                 iresult = IcmpAliasIn(pip);
1329                 break;
1330             case IPPROTO_UDP:
1331                 iresult = UdpAliasIn(pip);
1332                 break;
1333             case IPPROTO_TCP:
1334                 iresult = TcpAliasIn(pip);
1335                 break;
1336             case IPPROTO_GRE:
1337 		if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1338 		    AliasHandlePptpGreIn(pip) == 0)
1339 		    iresult = PKT_ALIAS_OK;
1340 		else
1341 		    iresult = ProtoAliasIn(pip);
1342 		break;
1343 	    default:
1344 		iresult = ProtoAliasIn(pip);
1345                 break;
1346         }
1347 
1348         if (ntohs(pip->ip_off) & IP_MF)
1349         {
1350             struct alias_link *link;
1351 
1352             link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1353             if (link != NULL)
1354             {
1355                 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1356                 SetFragmentAddr(link, pip->ip_dst);
1357             }
1358             else
1359             {
1360                 iresult = PKT_ALIAS_ERROR;
1361             }
1362         }
1363     }
1364     else
1365     {
1366         iresult = FragmentIn(pip);
1367     }
1368 
1369     return(iresult);
1370 }
1371 
1372 
1373 
1374 /* Unregistered address ranges */
1375 
1376 /* 10.0.0.0   ->   10.255.255.255 */
1377 #define UNREG_ADDR_A_LOWER 0x0a000000
1378 #define UNREG_ADDR_A_UPPER 0x0affffff
1379 
1380 /* 172.16.0.0  ->  172.31.255.255 */
1381 #define UNREG_ADDR_B_LOWER 0xac100000
1382 #define UNREG_ADDR_B_UPPER 0xac1fffff
1383 
1384 /* 192.168.0.0 -> 192.168.255.255 */
1385 #define UNREG_ADDR_C_LOWER 0xc0a80000
1386 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1387 
1388 int
1389 PacketAliasOut(char *ptr,           /* valid IP packet */
1390                int  maxpacketsize   /* How much the packet data may grow
1391                                        (FTP and IRC inline changes) */
1392               )
1393 {
1394     int iresult;
1395     struct in_addr addr_save;
1396     struct ip *pip;
1397 
1398     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1399         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1400         iresult = PacketAliasIn(ptr, maxpacketsize);
1401         packetAliasMode |= PKT_ALIAS_REVERSE;
1402         return iresult;
1403     }
1404 
1405     HouseKeeping();
1406     ClearCheckNewLink();
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 PKT_ALIAS_IGNORED;
1413 
1414     addr_save = GetDefaultAliasAddress();
1415     if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1416     {
1417         u_long addr;
1418         int iclass;
1419 
1420         iclass = 0;
1421         addr = ntohl(pip->ip_src.s_addr);
1422         if      (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1423             iclass = 3;
1424         else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1425             iclass = 2;
1426         else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1427             iclass = 1;
1428 
1429         if (iclass == 0)
1430         {
1431             SetDefaultAliasAddress(pip->ip_src);
1432         }
1433     }
1434     else if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
1435     {
1436         SetDefaultAliasAddress(pip->ip_src);
1437     }
1438 
1439     iresult = PKT_ALIAS_IGNORED;
1440     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1441     {
1442         switch (pip->ip_p)
1443         {
1444             case IPPROTO_ICMP:
1445                 iresult = IcmpAliasOut(pip);
1446                 break;
1447             case IPPROTO_UDP:
1448                 iresult = UdpAliasOut(pip);
1449                 break;
1450             case IPPROTO_TCP:
1451                 iresult = TcpAliasOut(pip, maxpacketsize);
1452                 break;
1453 	    case IPPROTO_GRE:
1454 		if (AliasHandlePptpGreOut(pip) == 0)
1455 		    iresult = PKT_ALIAS_OK;
1456 		else
1457 		    iresult = ProtoAliasOut(pip);
1458 		break;
1459 	    default:
1460 		iresult = ProtoAliasOut(pip);
1461                 break;
1462         }
1463     }
1464     else
1465     {
1466         iresult = FragmentOut(pip);
1467     }
1468 
1469     SetDefaultAliasAddress(addr_save);
1470     return(iresult);
1471 }
1472 
1473 int
1474 PacketUnaliasOut(char *ptr,           /* valid IP packet */
1475                  int  maxpacketsize   /* for error checking */
1476                 )
1477 {
1478     struct ip		*pip;
1479     struct icmp 	*ic;
1480     struct udphdr	*ud;
1481     struct tcphdr 	*tc;
1482     struct alias_link 	*link;
1483     int 		iresult = PKT_ALIAS_IGNORED;
1484 
1485     pip = (struct ip *) ptr;
1486 
1487     /* Defense against mangled packets */
1488     if (ntohs(pip->ip_len) > maxpacketsize
1489      || (pip->ip_hl<<2) > maxpacketsize)
1490         return(iresult);
1491 
1492     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1493     tc = (struct tcphdr *) ud;
1494     ic = (struct icmp *) ud;
1495 
1496     /* Find a link */
1497     if (pip->ip_p == IPPROTO_UDP)
1498         link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1499                             ud->uh_dport, ud->uh_sport,
1500                             IPPROTO_UDP, 0);
1501     else if (pip->ip_p == IPPROTO_TCP)
1502         link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1503                             tc->th_dport, tc->th_sport,
1504                             IPPROTO_TCP, 0);
1505     else if (pip->ip_p == IPPROTO_ICMP)
1506         link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1507     else
1508         link = NULL;
1509 
1510     /* Change it from an aliased packet to an unaliased packet */
1511     if (link != NULL)
1512     {
1513         if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1514         {
1515             u_short        *sptr;
1516             int 	   accumulate;
1517             struct in_addr original_address;
1518             u_short        original_port;
1519 
1520             original_address = GetOriginalAddress(link);
1521             original_port = GetOriginalPort(link);
1522 
1523             /* Adjust TCP/UDP checksum */
1524             sptr = (u_short *) &(pip->ip_src);
1525             accumulate  = *sptr++;
1526             accumulate += *sptr;
1527             sptr = (u_short *) &original_address;
1528             accumulate -= *sptr++;
1529             accumulate -= *sptr;
1530 
1531             if (pip->ip_p == IPPROTO_UDP) {
1532                 accumulate += ud->uh_sport;
1533                 accumulate -= original_port;
1534                 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1535 	    } else {
1536                 accumulate += tc->th_sport;
1537                 accumulate -= original_port;
1538                 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1539 	    }
1540 
1541             /* Adjust IP checksum */
1542             DifferentialChecksum(&pip->ip_sum,
1543                                  (u_short *) &original_address,
1544                                  (u_short *) &pip->ip_src,
1545                                  2);
1546 
1547             /* Un-alias source address and port number */
1548             pip->ip_src = original_address;
1549             if (pip->ip_p == IPPROTO_UDP)
1550                 ud->uh_sport = original_port;
1551 	    else
1552                 tc->th_sport = original_port;
1553 
1554 	    iresult = PKT_ALIAS_OK;
1555 
1556         } else if (pip->ip_p == IPPROTO_ICMP) {
1557 
1558             u_short        *sptr;
1559             int            accumulate;
1560             struct in_addr original_address;
1561             u_short        original_id;
1562 
1563             original_address = GetOriginalAddress(link);
1564             original_id = GetOriginalPort(link);
1565 
1566             /* Adjust ICMP checksum */
1567             sptr = (u_short *) &(pip->ip_src);
1568             accumulate  = *sptr++;
1569             accumulate += *sptr;
1570             sptr = (u_short *) &original_address;
1571             accumulate -= *sptr++;
1572             accumulate -= *sptr;
1573             accumulate += ic->icmp_id;
1574             accumulate -= original_id;
1575             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1576 
1577             /* Adjust IP checksum */
1578             DifferentialChecksum(&pip->ip_sum,
1579                                  (u_short *) &original_address,
1580                                  (u_short *) &pip->ip_src,
1581                                  2);
1582 
1583             /* Un-alias source address and port number */
1584             pip->ip_src = original_address;
1585             ic->icmp_id = original_id;
1586 
1587 	    iresult = PKT_ALIAS_OK;
1588         }
1589     }
1590     return(iresult);
1591 
1592 }
1593