xref: /freebsd/sys/netinet/libalias/alias.c (revision ebbd4fa8c8427d3dd847ba33c45c996e0500e6ff)
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 
921         alias_address = GetAliasAddress(link);
922         original_address = GetOriginalAddress(link);
923         proxy_address = GetProxyAddress(link);
924         alias_port = tc->th_dport;
925         tc->th_dport = GetOriginalPort(link);
926         proxy_port = GetProxyPort(link);
927 
928 /* Adjust TCP checksum since destination port is being unaliased */
929 /* and destination port is being altered.                        */
930         accumulate  = alias_port;
931         accumulate -= tc->th_dport;
932         sptr = (u_short *) &alias_address;
933         accumulate += *sptr++;
934         accumulate += *sptr;
935         sptr = (u_short *) &original_address;
936         accumulate -= *sptr++;
937         accumulate -= *sptr;
938 
939 /* If this is a proxy, then modify the TCP source port and
940    checksum accumulation */
941         if (proxy_port != 0)
942         {
943             accumulate += tc->th_sport;
944             tc->th_sport = proxy_port;
945             accumulate -= tc->th_sport;
946 
947             sptr = (u_short *) &pip->ip_src;
948             accumulate += *sptr++;
949             accumulate += *sptr;
950             sptr = (u_short *) &proxy_address;
951             accumulate -= *sptr++;
952             accumulate -= *sptr;
953         }
954 
955 /* See if ACK number needs to be modified */
956         if (GetAckModified(link) == 1)
957         {
958             int delta;
959 
960             delta = GetDeltaAckIn(pip, link);
961             if (delta != 0)
962             {
963                 sptr = (u_short *) &tc->th_ack;
964                 accumulate += *sptr++;
965                 accumulate += *sptr;
966                 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
967                 sptr = (u_short *) &tc->th_ack;
968                 accumulate -= *sptr++;
969                 accumulate -= *sptr;
970             }
971         }
972 
973         ADJUST_CHECKSUM(accumulate, tc->th_sum);
974 
975 /* Restore original IP address */
976         sptr = (u_short *) &pip->ip_dst;
977         accumulate  = *sptr++;
978         accumulate += *sptr;
979         pip->ip_dst = original_address;
980         sptr = (u_short *) &pip->ip_dst;
981         accumulate -= *sptr++;
982         accumulate -= *sptr;
983 
984 /* If this is a transparent proxy packet, then modify the source
985    address */
986         if (proxy_address.s_addr != 0)
987         {
988             sptr = (u_short *) &pip->ip_src;
989             accumulate += *sptr++;
990             accumulate += *sptr;
991             pip->ip_src = proxy_address;
992             sptr = (u_short *) &pip->ip_src;
993             accumulate -= *sptr++;
994             accumulate -= *sptr;
995         }
996 
997         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
998 
999 /* Monitor TCP connection state */
1000         TcpMonitorIn(pip, link);
1001 
1002         return(PKT_ALIAS_OK);
1003     }
1004     return(PKT_ALIAS_IGNORED);
1005 }
1006 
1007 static int
1008 TcpAliasOut(struct ip *pip, int maxpacketsize)
1009 {
1010     int proxy_type;
1011     u_short dest_port;
1012     u_short proxy_server_port;
1013     struct in_addr dest_address;
1014     struct in_addr proxy_server_address;
1015     struct tcphdr *tc;
1016     struct alias_link *link;
1017 
1018     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1019 
1020     proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1021 
1022     if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1023         return PKT_ALIAS_OK;
1024 
1025 /* If this is a transparent proxy, save original destination,
1026    then alter the destination and adjust checksums */
1027     dest_port = tc->th_dport;
1028     dest_address = pip->ip_dst;
1029     if (proxy_type != 0)
1030     {
1031         int accumulate;
1032         u_short *sptr;
1033 
1034         accumulate = tc->th_dport;
1035         tc->th_dport = proxy_server_port;
1036         accumulate -= tc->th_dport;
1037 
1038         sptr = (u_short *) &(pip->ip_dst);
1039         accumulate += *sptr++;
1040         accumulate += *sptr;
1041         sptr = (u_short *) &proxy_server_address;
1042         accumulate -= *sptr++;
1043         accumulate -= *sptr;
1044 
1045         ADJUST_CHECKSUM(accumulate, tc->th_sum);
1046 
1047         sptr = (u_short *) &(pip->ip_dst);
1048         accumulate  = *sptr++;
1049         accumulate += *sptr;
1050         pip->ip_dst = proxy_server_address;
1051         sptr = (u_short *) &(pip->ip_dst);
1052         accumulate -= *sptr++;
1053         accumulate -= *sptr;
1054 
1055         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1056     }
1057 
1058     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1059                          tc->th_sport, tc->th_dport,
1060                          IPPROTO_TCP, 1);
1061     if (link !=NULL)
1062     {
1063         u_short alias_port;
1064         struct in_addr alias_address;
1065         int accumulate;
1066         u_short *sptr;
1067 
1068 /* Save original destination address, if this is a proxy packet.
1069    Also modify packet to include destination encoding.  This may
1070    change the size of IP header. */
1071         if (proxy_type != 0)
1072         {
1073             SetProxyPort(link, dest_port);
1074             SetProxyAddress(link, dest_address);
1075             ProxyModify(link, pip, maxpacketsize, proxy_type);
1076             tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1077         }
1078 
1079 /* Get alias address and port */
1080         alias_port = GetAliasPort(link);
1081         alias_address = GetAliasAddress(link);
1082 
1083 /* Monitor TCP connection state */
1084         TcpMonitorOut(pip, link);
1085 
1086 /* Special processing for IP encoding protocols */
1087         if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1088          || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1089             AliasHandleFtpOut(pip, link, maxpacketsize);
1090         else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1091          || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1092             AliasHandleIrcOut(pip, link, maxpacketsize);
1093         else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1094          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1095          || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1096          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1097             AliasHandleRtspOut(pip, link, maxpacketsize);
1098         else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1099          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1100             AliasHandlePptpOut(pip, link);
1101 
1102 /* Adjust TCP checksum since source port is being aliased */
1103 /* and source address is being altered                    */
1104         accumulate  = tc->th_sport;
1105         tc->th_sport = alias_port;
1106         accumulate -= tc->th_sport;
1107 
1108         sptr = (u_short *) &(pip->ip_src);
1109         accumulate += *sptr++;
1110         accumulate += *sptr;
1111         sptr = (u_short *) &alias_address;
1112         accumulate -= *sptr++;
1113         accumulate -= *sptr;
1114 
1115 /* Modify sequence number if necessary */
1116         if (GetAckModified(link) == 1)
1117         {
1118             int delta;
1119 
1120             delta = GetDeltaSeqOut(pip, link);
1121             if (delta != 0)
1122             {
1123                 sptr = (u_short *) &tc->th_seq;
1124                 accumulate += *sptr++;
1125                 accumulate += *sptr;
1126                 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1127                 sptr = (u_short *) &tc->th_seq;
1128                 accumulate -= *sptr++;
1129                 accumulate -= *sptr;
1130             }
1131         }
1132 
1133         ADJUST_CHECKSUM(accumulate, tc->th_sum);
1134 
1135 /* Change source address */
1136         sptr = (u_short *) &(pip->ip_src);
1137         accumulate  = *sptr++;
1138         accumulate += *sptr;
1139         pip->ip_src = alias_address;
1140         sptr = (u_short *) &(pip->ip_src);
1141         accumulate -= *sptr++;
1142         accumulate -= *sptr;
1143 
1144         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1145 
1146         return(PKT_ALIAS_OK);
1147     }
1148     return(PKT_ALIAS_IGNORED);
1149 }
1150 
1151 
1152 
1153 
1154 /* Fragment Handling
1155 
1156     FragmentIn()
1157     FragmentOut()
1158 
1159 The packet aliasing module has a limited ability for handling IP
1160 fragments.  If the ICMP, TCP or UDP header is in the first fragment
1161 received, then the ID number of the IP packet is saved, and other
1162 fragments are identified according to their ID number and IP address
1163 they were sent from.  Pointers to unresolved fragments can also be
1164 saved and recalled when a header fragment is seen.
1165 */
1166 
1167 /* Local prototypes */
1168 static int FragmentIn(struct ip *);
1169 static int FragmentOut(struct ip *);
1170 
1171 
1172 static int
1173 FragmentIn(struct ip *pip)
1174 {
1175     struct alias_link *link;
1176 
1177     link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1178     if (link != NULL)
1179     {
1180         struct in_addr original_address;
1181 
1182         GetFragmentAddr(link, &original_address);
1183         DifferentialChecksum(&pip->ip_sum,
1184                              (u_short *) &original_address,
1185                              (u_short *) &pip->ip_dst,
1186                              2);
1187         pip->ip_dst = original_address;
1188 
1189         return(PKT_ALIAS_OK);
1190     }
1191     return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1192 }
1193 
1194 
1195 static int
1196 FragmentOut(struct ip *pip)
1197 {
1198     struct in_addr alias_address;
1199 
1200     alias_address = FindAliasAddress(pip->ip_src);
1201     DifferentialChecksum(&pip->ip_sum,
1202                          (u_short *) &alias_address,
1203                          (u_short *) &pip->ip_src,
1204                           2);
1205     pip->ip_src = alias_address;
1206 
1207     return(PKT_ALIAS_OK);
1208 }
1209 
1210 
1211 
1212 
1213 
1214 
1215 /* Outside World Access
1216 
1217         PacketAliasSaveFragment()
1218         PacketAliasGetFragment()
1219         PacketAliasFragmentIn()
1220         PacketAliasIn()
1221         PacketAliasOut()
1222         PacketUnaliasOut()
1223 
1224 (prototypes in alias.h)
1225 */
1226 
1227 
1228 int
1229 PacketAliasSaveFragment(char *ptr)
1230 {
1231     int iresult;
1232     struct alias_link *link;
1233     struct ip *pip;
1234 
1235     pip = (struct ip *) ptr;
1236     link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1237     iresult = PKT_ALIAS_ERROR;
1238     if (link != NULL)
1239     {
1240         SetFragmentPtr(link, ptr);
1241         iresult = PKT_ALIAS_OK;
1242     }
1243     return(iresult);
1244 }
1245 
1246 
1247 char *
1248 PacketAliasGetFragment(char *ptr)
1249 {
1250     struct alias_link *link;
1251     char *fptr;
1252     struct ip *pip;
1253 
1254     pip = (struct ip *) ptr;
1255     link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1256     if (link != NULL)
1257     {
1258         GetFragmentPtr(link, &fptr);
1259         SetFragmentPtr(link, NULL);
1260         SetExpire(link, 0); /* Deletes link */
1261 
1262         return(fptr);
1263     }
1264     else
1265     {
1266         return(NULL);
1267     }
1268 }
1269 
1270 
1271 void
1272 PacketAliasFragmentIn(char *ptr,          /* Points to correctly de-aliased
1273                                              header fragment */
1274                       char *ptr_fragment  /* Points to fragment which must
1275                                              be de-aliased   */
1276                      )
1277 {
1278     struct ip *pip;
1279     struct ip *fpip;
1280 
1281     pip = (struct ip *) ptr;
1282     fpip = (struct ip *) ptr_fragment;
1283 
1284     DifferentialChecksum(&fpip->ip_sum,
1285                          (u_short *) &pip->ip_dst,
1286                          (u_short *) &fpip->ip_dst,
1287                          2);
1288     fpip->ip_dst = pip->ip_dst;
1289 }
1290 
1291 
1292 int
1293 PacketAliasIn(char *ptr, int maxpacketsize)
1294 {
1295     struct in_addr alias_addr;
1296     struct ip *pip;
1297     int iresult;
1298 
1299     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1300         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1301         iresult = PacketAliasOut(ptr, maxpacketsize);
1302         packetAliasMode |= PKT_ALIAS_REVERSE;
1303         return iresult;
1304     }
1305 
1306     HouseKeeping();
1307     ClearCheckNewLink();
1308     pip = (struct ip *) ptr;
1309     alias_addr = pip->ip_dst;
1310 
1311     /* Defense against mangled packets */
1312     if (ntohs(pip->ip_len) > maxpacketsize
1313      || (pip->ip_hl<<2) > maxpacketsize)
1314         return PKT_ALIAS_IGNORED;
1315 
1316     iresult = PKT_ALIAS_IGNORED;
1317     if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1318     {
1319         switch (pip->ip_p)
1320         {
1321             case IPPROTO_ICMP:
1322                 iresult = IcmpAliasIn(pip);
1323                 break;
1324             case IPPROTO_UDP:
1325                 iresult = UdpAliasIn(pip);
1326                 break;
1327             case IPPROTO_TCP:
1328                 iresult = TcpAliasIn(pip);
1329                 break;
1330             case IPPROTO_GRE:
1331 		if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1332 		    AliasHandlePptpGreIn(pip) == 0)
1333 		    iresult = PKT_ALIAS_OK;
1334 		else
1335 		    iresult = ProtoAliasIn(pip);
1336 		break;
1337 	    default:
1338 		iresult = ProtoAliasIn(pip);
1339                 break;
1340         }
1341 
1342         if (ntohs(pip->ip_off) & IP_MF)
1343         {
1344             struct alias_link *link;
1345 
1346             link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1347             if (link != NULL)
1348             {
1349                 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1350                 SetFragmentAddr(link, pip->ip_dst);
1351             }
1352             else
1353             {
1354                 iresult = PKT_ALIAS_ERROR;
1355             }
1356         }
1357     }
1358     else
1359     {
1360         iresult = FragmentIn(pip);
1361     }
1362 
1363     return(iresult);
1364 }
1365 
1366 
1367 
1368 /* Unregistered address ranges */
1369 
1370 /* 10.0.0.0   ->   10.255.255.255 */
1371 #define UNREG_ADDR_A_LOWER 0x0a000000
1372 #define UNREG_ADDR_A_UPPER 0x0affffff
1373 
1374 /* 172.16.0.0  ->  172.31.255.255 */
1375 #define UNREG_ADDR_B_LOWER 0xac100000
1376 #define UNREG_ADDR_B_UPPER 0xac1fffff
1377 
1378 /* 192.168.0.0 -> 192.168.255.255 */
1379 #define UNREG_ADDR_C_LOWER 0xc0a80000
1380 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1381 
1382 int
1383 PacketAliasOut(char *ptr,           /* valid IP packet */
1384                int  maxpacketsize   /* How much the packet data may grow
1385                                        (FTP and IRC inline changes) */
1386               )
1387 {
1388     int iresult;
1389     struct in_addr addr_save;
1390     struct ip *pip;
1391 
1392     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1393         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1394         iresult = PacketAliasIn(ptr, maxpacketsize);
1395         packetAliasMode |= PKT_ALIAS_REVERSE;
1396         return iresult;
1397     }
1398 
1399     HouseKeeping();
1400     ClearCheckNewLink();
1401     pip = (struct ip *) ptr;
1402 
1403     /* Defense against mangled packets */
1404     if (ntohs(pip->ip_len) > maxpacketsize
1405      || (pip->ip_hl<<2) > maxpacketsize)
1406         return PKT_ALIAS_IGNORED;
1407 
1408     addr_save = GetDefaultAliasAddress();
1409     if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1410     {
1411         u_long addr;
1412         int iclass;
1413 
1414         iclass = 0;
1415         addr = ntohl(pip->ip_src.s_addr);
1416         if      (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1417             iclass = 3;
1418         else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1419             iclass = 2;
1420         else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1421             iclass = 1;
1422 
1423         if (iclass == 0)
1424         {
1425             SetDefaultAliasAddress(pip->ip_src);
1426         }
1427     }
1428 
1429     iresult = PKT_ALIAS_IGNORED;
1430     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1431     {
1432         switch (pip->ip_p)
1433         {
1434             case IPPROTO_ICMP:
1435                 iresult = IcmpAliasOut(pip);
1436                 break;
1437             case IPPROTO_UDP:
1438                 iresult = UdpAliasOut(pip);
1439                 break;
1440             case IPPROTO_TCP:
1441                 iresult = TcpAliasOut(pip, maxpacketsize);
1442                 break;
1443 	    case IPPROTO_GRE:
1444 		if (AliasHandlePptpGreOut(pip) == 0)
1445 		    iresult = PKT_ALIAS_OK;
1446 		else
1447 		    iresult = ProtoAliasOut(pip);
1448 		break;
1449 	    default:
1450 		iresult = ProtoAliasOut(pip);
1451                 break;
1452         }
1453     }
1454     else
1455     {
1456         iresult = FragmentOut(pip);
1457     }
1458 
1459     SetDefaultAliasAddress(addr_save);
1460     return(iresult);
1461 }
1462 
1463 int
1464 PacketUnaliasOut(char *ptr,           /* valid IP packet */
1465                  int  maxpacketsize   /* for error checking */
1466                 )
1467 {
1468     struct ip		*pip;
1469     struct icmp 	*ic;
1470     struct udphdr	*ud;
1471     struct tcphdr 	*tc;
1472     struct alias_link 	*link;
1473     int 		iresult = PKT_ALIAS_IGNORED;
1474 
1475     pip = (struct ip *) ptr;
1476 
1477     /* Defense against mangled packets */
1478     if (ntohs(pip->ip_len) > maxpacketsize
1479      || (pip->ip_hl<<2) > maxpacketsize)
1480         return(iresult);
1481 
1482     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1483     tc = (struct tcphdr *) ud;
1484     ic = (struct icmp *) ud;
1485 
1486     /* Find a link */
1487     if (pip->ip_p == IPPROTO_UDP)
1488         link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1489                             ud->uh_dport, ud->uh_sport,
1490                             IPPROTO_UDP, 0);
1491     else if (pip->ip_p == IPPROTO_TCP)
1492         link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1493                             tc->th_dport, tc->th_sport,
1494                             IPPROTO_TCP, 0);
1495     else if (pip->ip_p == IPPROTO_ICMP)
1496         link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1497     else
1498         link = NULL;
1499 
1500     /* Change it from an aliased packet to an unaliased packet */
1501     if (link != NULL)
1502     {
1503         if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1504         {
1505             u_short        *sptr;
1506             int 	   accumulate;
1507             struct in_addr original_address;
1508             u_short        original_port;
1509 
1510             original_address = GetOriginalAddress(link);
1511             original_port = GetOriginalPort(link);
1512 
1513             /* Adjust TCP/UDP checksum */
1514             sptr = (u_short *) &(pip->ip_src);
1515             accumulate  = *sptr++;
1516             accumulate += *sptr;
1517             sptr = (u_short *) &original_address;
1518             accumulate -= *sptr++;
1519             accumulate -= *sptr;
1520 
1521             if (pip->ip_p == IPPROTO_UDP) {
1522                 accumulate += ud->uh_sport;
1523                 accumulate -= original_port;
1524                 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1525 	    } else {
1526                 accumulate += tc->th_sport;
1527                 accumulate -= original_port;
1528                 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1529 	    }
1530 
1531             /* Adjust IP checksum */
1532             DifferentialChecksum(&pip->ip_sum,
1533                                  (u_short *) &original_address,
1534                                  (u_short *) &pip->ip_src,
1535                                  2);
1536 
1537             /* Un-alias source address and port number */
1538             pip->ip_src = original_address;
1539             if (pip->ip_p == IPPROTO_UDP)
1540                 ud->uh_sport = original_port;
1541 	    else
1542                 tc->th_sport = original_port;
1543 
1544 	    iresult = PKT_ALIAS_OK;
1545 
1546         } else if (pip->ip_p == IPPROTO_ICMP) {
1547 
1548             u_short        *sptr;
1549             int            accumulate;
1550             struct in_addr original_address;
1551             u_short        original_id;
1552 
1553             original_address = GetOriginalAddress(link);
1554             original_id = GetOriginalPort(link);
1555 
1556             /* Adjust ICMP checksum */
1557             sptr = (u_short *) &(pip->ip_src);
1558             accumulate  = *sptr++;
1559             accumulate += *sptr;
1560             sptr = (u_short *) &original_address;
1561             accumulate -= *sptr++;
1562             accumulate -= *sptr;
1563             accumulate += ic->icmp_id;
1564             accumulate -= original_id;
1565             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1566 
1567             /* Adjust IP checksum */
1568             DifferentialChecksum(&pip->ip_sum,
1569                                  (u_short *) &original_address,
1570                                  (u_short *) &pip->ip_src,
1571                                  2);
1572 
1573             /* Un-alias source address and port number */
1574             pip->ip_src = original_address;
1575             ic->icmp_id = original_id;
1576 
1577 	    iresult = PKT_ALIAS_OK;
1578         }
1579     }
1580     return(iresult);
1581 
1582 }
1583