Update files for OpenSSL-1.0.1d import.
[dragonfly.git] / lib / libalias / alias.c
1 /* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
2
3 /*-
4  * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.11 2002/07/25 12:31:37 ru Exp $
29  */
30
31 /*
32     Alias.c provides supervisory control for the functions of the
33     packet aliasing software.  It consists of routines to monitor
34     TCP connection state, protocol-specific aliasing routines,
35     fragment handling and the following outside world functional
36     interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
37     PacketAliasIn and PacketAliasOut.
38
39     The other C program files are briefly described. The data
40     structure framework which holds information needed to translate
41     packets is encapsulated in alias_db.c.  Data is accessed by
42     function calls, so other segments of the program need not know
43     about the underlying data structures.  Alias_ftp.c contains
44     special code for modifying the ftp PORT command used to establish
45     data connections, while alias_irc.c does the same for IRC
46     DCC. Alias_util.c contains a few utility routines.
47
48     Version 1.0 August, 1996  (cjm)
49
50     Version 1.1 August 20, 1996  (cjm)
51         PPP host accepts incoming connections for ports 0 to 1023.
52         (Gary Roberts pointed out the need to handle incoming
53          connections.)
54
55     Version 1.2 September 7, 1996 (cjm)
56         Fragment handling error in alias_db.c corrected.
57         (Tom Torrance helped fix this problem.)
58
59     Version 1.4 September 16, 1996 (cjm)
60         - A more generalized method for handling incoming
61           connections, without the 0-1023 restriction, is
62           implemented in alias_db.c
63         - Improved ICMP support in alias.c.  Traceroute
64           packet streams can now be correctly aliased.
65         - TCP connection closing logic simplified in
66           alias.c and now allows for additional 1 minute
67           "grace period" after FIN or RST is observed.
68
69     Version 1.5 September 17, 1996 (cjm)
70         Corrected error in handling incoming UDP packets with 0 checksum.
71         (Tom Torrance helped fix this problem.)
72
73     Version 1.6 September 18, 1996 (cjm)
74         Simplified ICMP aliasing scheme.  Should now support
75         traceroute from Win95 as well as FreeBSD.
76
77     Version 1.7 January 9, 1997 (cjm)
78         - Out-of-order fragment handling.
79         - IP checksum error fixed for ftp transfers
80           from aliasing host.
81         - Integer return codes added to all
82           aliasing/de-aliasing functions.
83         - Some obsolete comments cleaned up.
84         - Differential checksum computations for
85           IP header (TCP, UDP and ICMP were already
86           differential).
87
88     Version 2.1 May 1997 (cjm)
89         - Added support for outgoing ICMP error
90           messages.
91         - Added two functions PacketAliasIn2()
92           and PacketAliasOut2() for dynamic address
93           control (e.g. round-robin allocation of
94           incoming packets).
95
96     Version 2.2 July 1997 (cjm)
97         - Rationalized API function names to begin
98           with "PacketAlias..."
99         - Eliminated PacketAliasIn2() and
100           PacketAliasOut2() as poorly conceived.
101
102     Version 2.3 Dec 1998 (dillon)
103         - Major bounds checking additions, see FreeBSD/CVS
104
105     Version 3.1 May, 2000 (salander) 
106         - Added hooks to handle PPTP.
107
108     Version 3.2 July, 2000 (salander and satoh)
109         - Added PacketUnaliasOut routine.
110         - Added hooks to handle RTSP/RTP.
111
112     See HISTORY file for additional revisions.
113 */
114
115 #include <sys/param.h>
116
117 #include <netinet/in_systm.h>
118 #include <netinet/in.h>
119 #include <netinet/ip.h>
120 #include <netinet/ip_icmp.h>
121 #include <netinet/tcp.h>
122 #include <netinet/udp.h>
123
124 #include <stdio.h>
125
126 #include "alias_local.h"
127 #include "alias.h"
128
129 #define NETBIOS_NS_PORT_NUMBER 137
130 #define NETBIOS_DGM_PORT_NUMBER 138
131 #define FTP_CONTROL_PORT_NUMBER 21
132 #define IRC_CONTROL_PORT_NUMBER_1 6667
133 #define IRC_CONTROL_PORT_NUMBER_2 6668
134 #define CUSEEME_PORT_NUMBER 7648
135 #define RTSP_CONTROL_PORT_NUMBER_1 554
136 #define RTSP_CONTROL_PORT_NUMBER_2 7070
137 #define TFTP_PORT_NUMBER 69
138 #define PPTP_CONTROL_PORT_NUMBER 1723
139
140 static __inline int
141 twowords(void *p)
142 {
143     uint8_t *c = p;
144
145 #if BYTE_ORDER == LITTLE_ENDIAN
146     uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
147     uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
148 #else
149     uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
150     uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
151 #endif
152     return (s1 + s2);
153 }
154
155 /* TCP Handling Routines
156
157     TcpMonitorIn()  -- These routines monitor TCP connections, and
158     TcpMonitorOut()    delete a link when a connection is closed.
159
160 These routines look for SYN, FIN and RST flags to determine when TCP
161 connections open and close.  When a TCP connection closes, the data
162 structure containing packet aliasing information is deleted after
163 a timeout period.
164 */
165
166 /* Local prototypes */
167 static void TcpMonitorIn(struct ip *, struct alias_link *);
168
169 static void TcpMonitorOut(struct ip *, struct alias_link *);
170
171
172 static void
173 TcpMonitorIn(struct ip *pip, struct alias_link *link)
174 {
175     struct tcphdr *tc;
176
177     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
178
179     switch (GetStateIn(link))
180     {
181         case ALIAS_TCP_STATE_NOT_CONNECTED:
182             if (tc->th_flags & TH_RST)
183                 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
184             else if (tc->th_flags & TH_SYN)
185                 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
186             break;
187         case ALIAS_TCP_STATE_CONNECTED:
188             if (tc->th_flags & (TH_FIN | TH_RST))
189                 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
190             break;
191     }
192 }
193
194 static void
195 TcpMonitorOut(struct ip *pip, struct alias_link *link)
196 {
197     struct tcphdr *tc;
198
199     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
200      
201     switch (GetStateOut(link))
202     {
203         case ALIAS_TCP_STATE_NOT_CONNECTED:
204             if (tc->th_flags & TH_RST)
205                 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
206             else if (tc->th_flags & TH_SYN)
207                 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
208             break;
209         case ALIAS_TCP_STATE_CONNECTED:
210             if (tc->th_flags & (TH_FIN | TH_RST))
211                 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
212             break;
213     }
214 }
215
216
217
218
219
220 /* Protocol Specific Packet Aliasing Routines 
221
222     IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
223     IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
224     ProtoAliasIn(), ProtoAliasOut()
225     UdpAliasIn(), UdpAliasOut()
226     TcpAliasIn(), TcpAliasOut()
227
228 These routines handle protocol specific details of packet aliasing.
229 One may observe a certain amount of repetitive arithmetic in these
230 functions, the purpose of which is to compute a revised checksum
231 without actually summing over the entire data packet, which could be
232 unnecessarily time consuming.
233
234 The purpose of the packet aliasing routines is to replace the source
235 address of the outgoing packet and then correctly put it back for
236 any incoming packets.  For TCP and UDP, ports are also re-mapped.
237
238 For ICMP echo/timestamp requests and replies, the following scheme
239 is used: the ID number is replaced by an alias for the outgoing
240 packet.
241
242 ICMP error messages are handled by looking at the IP fragment
243 in the data section of the message.
244
245 For TCP and UDP protocols, a port number is chosen for an outgoing
246 packet, and then incoming packets are identified by IP address and
247 port numbers.  For TCP packets, there is additional logic in the event
248 that sequence and ACK numbers have been altered (as in the case for
249 FTP data port commands).
250
251 The port numbers used by the packet aliasing module are not true
252 ports in the Unix sense.  No sockets are actually bound to ports.
253 They are more correctly thought of as placeholders.
254
255 All packets go through the aliasing mechanism, whether they come from
256 the gateway machine or other machines on a local area network.
257 */
258
259
260 /* Local prototypes */
261 static int IcmpAliasIn1(struct ip *);
262 static int IcmpAliasIn2(struct ip *);
263 static int IcmpAliasIn (struct ip *);
264
265 static int IcmpAliasOut1(struct ip *);
266 static int IcmpAliasOut2(struct ip *);
267 static int IcmpAliasOut (struct ip *);
268
269 static int ProtoAliasIn(struct ip *);
270 static int ProtoAliasOut(struct ip *);
271
272 static int UdpAliasOut(struct ip *);
273 static int UdpAliasIn (struct ip *);
274
275 static int TcpAliasOut(struct ip *, int);
276 static int TcpAliasIn (struct ip *);
277
278
279 static int
280 IcmpAliasIn1(struct ip *pip)
281 {
282 /*
283     De-alias incoming echo and timestamp replies.
284     Alias incoming echo and timestamp requests.
285 */
286     struct alias_link *link;
287     struct icmp *ic;
288
289     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
290
291 /* Get source address from ICMP data field and restore original data */
292     link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
293     if (link != NULL)
294     {
295         u_short original_id;
296         int accumulate;
297
298         original_id = GetOriginalPort(link);
299
300 /* Adjust ICMP checksum */
301         accumulate  = ic->icmp_id;
302         accumulate -= original_id;
303         ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
304
305 /* Put original sequence number back in */
306         ic->icmp_id = original_id;
307
308 /* Put original address back into IP header */
309         {
310             struct in_addr original_address;
311
312             original_address = GetOriginalAddress(link);
313             DifferentialChecksum(&pip->ip_sum,
314                                  (u_short *) &original_address,
315                                  (u_short *) &pip->ip_dst,
316                                  2);
317             pip->ip_dst = original_address;
318         }
319
320         return(PKT_ALIAS_OK);
321     }
322     return(PKT_ALIAS_IGNORED);
323 }
324
325 static int
326 IcmpAliasIn2(struct ip *pip)
327 {
328 /*
329     Alias incoming ICMP error messages containing
330     IP header and first 64 bits of datagram.
331 */
332     struct ip *ip;
333     struct icmp *ic, *ic2;
334     struct udphdr *ud;
335     struct tcphdr *tc;
336     struct alias_link *link;
337
338     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
339     ip = &ic->icmp_ip;
340
341     ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
342     tc = (struct tcphdr *) ud;
343     ic2 = (struct icmp *) ud;
344
345     if (ip->ip_p == IPPROTO_UDP)
346         link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
347                             ud->uh_dport, ud->uh_sport,
348                             IPPROTO_UDP, 0);
349     else if (ip->ip_p == IPPROTO_TCP)
350         link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
351                             tc->th_dport, tc->th_sport,
352                             IPPROTO_TCP, 0);
353     else if (ip->ip_p == IPPROTO_ICMP) {
354         if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
355             link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
356         else
357             link = NULL;
358     } else
359         link = NULL;
360
361     if (link != NULL)
362     {
363         if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
364         {
365             int accumulate, accumulate2;
366             struct in_addr original_address;
367             u_short original_port;
368
369             original_address = GetOriginalAddress(link);
370             original_port = GetOriginalPort(link);
371     
372 /* Adjust ICMP checksum */
373             accumulate  = twowords(&ip->ip_src);
374             accumulate -= twowords(&original_address);
375             accumulate += ud->uh_sport;
376             accumulate -= original_port;
377             accumulate2 = accumulate;
378             accumulate2 += ip->ip_sum;
379             ADJUST_CHECKSUM(accumulate, ip->ip_sum);
380             accumulate2 -= ip->ip_sum;
381             ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
382
383 /* Un-alias address in IP header */
384             DifferentialChecksum(&pip->ip_sum,
385                                  (u_short *) &original_address,
386                                  (u_short *) &pip->ip_dst,
387                                  2);
388             pip->ip_dst = original_address;
389
390 /* Un-alias address and port number of original IP packet
391 fragment contained in ICMP data section */
392             ip->ip_src = original_address;
393             ud->uh_sport = original_port; 
394         }
395         else if (ip->ip_p == IPPROTO_ICMP)
396         {
397             int accumulate, accumulate2;
398             struct in_addr original_address;
399             u_short original_id;
400
401             original_address = GetOriginalAddress(link);
402             original_id = GetOriginalPort(link);
403
404 /* Adjust ICMP checksum */
405             accumulate  = twowords(&ip->ip_src);
406             accumulate -= twowords(&original_address);
407             accumulate += ic2->icmp_id;
408             accumulate -= original_id;
409             accumulate2 = accumulate;
410             accumulate2 += ip->ip_sum;
411             ADJUST_CHECKSUM(accumulate, ip->ip_sum);
412             accumulate2 -= ip->ip_sum;
413             ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
414
415 /* Un-alias address in IP header */
416             DifferentialChecksum(&pip->ip_sum,
417                                  (u_short *) &original_address,
418                                  (u_short *) &pip->ip_dst,
419                                  2);
420             pip->ip_dst = original_address;
421
422 /* Un-alias address of original IP packet and sequence number of 
423    embedded ICMP datagram */
424             ip->ip_src = original_address;
425             ic2->icmp_id = original_id;
426         }
427         return(PKT_ALIAS_OK);
428     }
429     return(PKT_ALIAS_IGNORED);
430 }
431
432
433 static int
434 IcmpAliasIn(struct ip *pip)
435 {
436     int iresult;
437     struct icmp *ic;
438
439 /* Return if proxy-only mode is enabled */
440     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
441         return PKT_ALIAS_OK;
442
443     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
444
445     iresult = PKT_ALIAS_IGNORED;
446     switch (ic->icmp_type)
447     {
448         case ICMP_ECHOREPLY:
449         case ICMP_TSTAMPREPLY:
450             if (ic->icmp_code == 0)
451             {
452                 iresult = IcmpAliasIn1(pip);
453             }
454             break;
455         case ICMP_UNREACH:
456         case ICMP_SOURCEQUENCH:
457         case ICMP_TIMXCEED:
458         case ICMP_PARAMPROB:
459             iresult = IcmpAliasIn2(pip);
460             break;
461         case ICMP_ECHO:
462         case ICMP_TSTAMP:
463             iresult = IcmpAliasIn1(pip);
464             break;
465     }
466     return(iresult);
467 }
468
469
470 static int
471 IcmpAliasOut1(struct ip *pip)
472 {
473 /*
474     Alias outgoing echo and timestamp requests.
475     De-alias outgoing echo and timestamp replies.
476 */
477     struct alias_link *link;
478     struct icmp *ic;
479
480     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
481
482 /* Save overwritten data for when echo packet returns */
483     link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
484     if (link != NULL)
485     {
486         u_short alias_id;
487         int accumulate;
488
489         alias_id = GetAliasPort(link);
490
491 /* Since data field is being modified, adjust ICMP checksum */
492         accumulate  = ic->icmp_id;
493         accumulate -= alias_id;
494         ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
495
496 /* Alias sequence number */
497         ic->icmp_id = alias_id;
498
499 /* Change source address */
500         {
501             struct in_addr alias_address;
502
503             alias_address = GetAliasAddress(link);
504             DifferentialChecksum(&pip->ip_sum,
505                                  (u_short *) &alias_address,
506                                  (u_short *) &pip->ip_src,
507                                  2);
508             pip->ip_src = alias_address;
509         }
510
511         return(PKT_ALIAS_OK);
512     }
513     return(PKT_ALIAS_IGNORED);
514 }
515
516
517 static int
518 IcmpAliasOut2(struct ip *pip)
519 {
520 /*
521     Alias outgoing ICMP error messages containing
522     IP header and first 64 bits of datagram.
523 */
524     struct ip *ip;
525     struct icmp *ic, *ic2;
526     struct udphdr *ud;
527     struct tcphdr *tc;
528     struct alias_link *link;
529
530     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
531     ip = &ic->icmp_ip;
532
533     ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
534     tc = (struct tcphdr *) ud;
535     ic2 = (struct icmp *) ud;
536
537     if (ip->ip_p == IPPROTO_UDP)
538         link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
539                             ud->uh_dport, ud->uh_sport,
540                             IPPROTO_UDP, 0);
541     else if (ip->ip_p == IPPROTO_TCP)
542         link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
543                             tc->th_dport, tc->th_sport,
544                             IPPROTO_TCP, 0);
545     else if (ip->ip_p == IPPROTO_ICMP) {
546         if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
547             link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
548         else
549             link = NULL;
550     } else
551         link = NULL;
552
553     if (link != NULL)
554     {
555         if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
556         {
557             int accumulate;
558             struct in_addr alias_address;
559             u_short alias_port;
560
561             alias_address = GetAliasAddress(link);
562             alias_port = GetAliasPort(link);
563     
564 /* Adjust ICMP checksum */
565             accumulate  = twowords(&ip->ip_dst);
566             accumulate -= twowords(&alias_address);
567             accumulate += ud->uh_dport;
568             accumulate -= alias_port;
569             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
570
571 /*
572  * Alias address in IP header if it comes from the host
573  * the original TCP/UDP packet was destined for.
574  */
575             if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
576                 DifferentialChecksum(&pip->ip_sum,
577                                      (u_short *) &alias_address,
578                                      (u_short *) &pip->ip_src,
579                                      2);
580                 pip->ip_src = alias_address;
581             }
582
583 /* Alias address and port number of original IP packet
584 fragment contained in ICMP data section */
585             ip->ip_dst = alias_address;
586             ud->uh_dport = alias_port; 
587         }
588         else if (ip->ip_p == IPPROTO_ICMP)
589         {
590             int accumulate;
591             struct in_addr alias_address;
592             u_short alias_id;
593
594             alias_address = GetAliasAddress(link);
595             alias_id = GetAliasPort(link);
596
597 /* Adjust ICMP checksum */
598             accumulate  = twowords(&ip->ip_dst);
599             accumulate -= twowords(&alias_address);
600             accumulate += ic2->icmp_id;
601             accumulate -= alias_id;
602             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
603
604 /*
605  * Alias address in IP header if it comes from the host
606  * the original ICMP message was destined for.
607  */
608             if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
609                 DifferentialChecksum(&pip->ip_sum,
610                                      (u_short *) &alias_address,
611                                      (u_short *) &pip->ip_src,
612                                      2);
613                 pip->ip_src = alias_address;
614             }
615
616 /* Alias address of original IP packet and sequence number of 
617    embedded ICMP datagram */
618             ip->ip_dst = alias_address;
619             ic2->icmp_id = alias_id;
620         }
621         return(PKT_ALIAS_OK);
622     }
623     return(PKT_ALIAS_IGNORED);
624 }
625
626
627 static int
628 IcmpAliasOut(struct ip *pip)
629 {
630     int iresult;
631     struct icmp *ic;
632
633 /* Return if proxy-only mode is enabled */
634     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
635         return PKT_ALIAS_OK;
636
637     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
638
639     iresult = PKT_ALIAS_IGNORED;
640     switch (ic->icmp_type)
641     {
642         case ICMP_ECHO:
643         case ICMP_TSTAMP:
644             if (ic->icmp_code == 0)
645             {
646                 iresult = IcmpAliasOut1(pip);
647             }
648             break;
649         case ICMP_UNREACH:
650         case ICMP_SOURCEQUENCH:
651         case ICMP_TIMXCEED:
652         case ICMP_PARAMPROB:
653             iresult = IcmpAliasOut2(pip);
654             break;
655         case ICMP_ECHOREPLY:
656         case ICMP_TSTAMPREPLY:
657             iresult = IcmpAliasOut1(pip);
658     }
659     return(iresult);
660 }
661
662
663
664 static int
665 ProtoAliasIn(struct ip *pip)
666 {
667 /*
668   Handle incoming IP packets. The
669   only thing which is done in this case is to alias
670   the dest IP address of the packet to our inside
671   machine.
672 */
673     struct alias_link *link;
674
675 /* Return if proxy-only mode is enabled */
676     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
677         return PKT_ALIAS_OK;
678
679     link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
680     if (link != NULL)
681     {
682         struct in_addr original_address;
683
684         original_address = GetOriginalAddress(link);
685
686 /* Restore original IP address */
687         DifferentialChecksum(&pip->ip_sum,
688                              (u_short *) &original_address,
689                              (u_short *) &pip->ip_dst,
690                              2);
691         pip->ip_dst = original_address;
692
693         return(PKT_ALIAS_OK);
694     }
695     return(PKT_ALIAS_IGNORED);
696 }
697
698
699 static int
700 ProtoAliasOut(struct ip *pip)
701 {
702 /*
703   Handle outgoing IP packets. The
704   only thing which is done in this case is to alias
705   the source IP address of the packet.
706 */
707     struct alias_link *link;
708
709 /* Return if proxy-only mode is enabled */
710     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
711         return PKT_ALIAS_OK;
712
713     link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
714     if (link != NULL)
715     {
716         struct in_addr alias_address;
717
718         alias_address = GetAliasAddress(link);
719
720 /* Change source address */
721         DifferentialChecksum(&pip->ip_sum,
722                              (u_short *) &alias_address,
723                              (u_short *) &pip->ip_src,
724                              2);
725         pip->ip_src = alias_address;
726
727         return(PKT_ALIAS_OK);
728     }
729     return(PKT_ALIAS_IGNORED);
730 }
731
732
733 static int
734 UdpAliasIn(struct ip *pip)
735 {
736     struct udphdr *ud;
737     struct alias_link *link;
738
739 /* Return if proxy-only mode is enabled */
740     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
741         return PKT_ALIAS_OK;
742
743     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
744
745     link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
746                         ud->uh_sport, ud->uh_dport,
747                         IPPROTO_UDP, 1);
748     if (link != NULL)
749     {
750         struct in_addr alias_address;
751         struct in_addr original_address;
752         u_short alias_port;
753         int accumulate;
754         int r = 0;
755
756         alias_address = GetAliasAddress(link);
757         original_address = GetOriginalAddress(link);
758         alias_port = ud->uh_dport;
759         ud->uh_dport = GetOriginalPort(link);
760
761 /* Special processing for IP encoding protocols */
762         if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
763             AliasHandleCUSeeMeIn(pip, original_address);
764 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
765         else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
766               || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
767             r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
768         else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
769               || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
770             r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
771                                     &original_address, &ud->uh_dport);
772
773 /* If UDP checksum is not zero, then adjust since destination port */
774 /* is being unaliased and destination address is being altered.    */
775         if (ud->uh_sum != 0)
776         {
777             accumulate  = alias_port;
778             accumulate -= ud->uh_dport;
779             accumulate += twowords(&alias_address);
780             accumulate -= twowords(&original_address);
781             ADJUST_CHECKSUM(accumulate, ud->uh_sum);
782         }
783
784 /* Restore original IP address */
785         DifferentialChecksum(&pip->ip_sum,
786                              (u_short *) &original_address,
787                              (u_short *) &pip->ip_dst,
788                              2);
789         pip->ip_dst = original_address;
790
791         /*
792          * If we cannot figure out the packet, ignore it.
793          */
794         if (r < 0)
795             return(PKT_ALIAS_IGNORED);
796         else
797             return(PKT_ALIAS_OK);
798     }
799     return(PKT_ALIAS_IGNORED);
800 }
801
802 static int
803 UdpAliasOut(struct ip *pip)
804 {
805     struct udphdr *ud;
806     struct alias_link *link;
807
808 /* Return if proxy-only mode is enabled */
809     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
810         return PKT_ALIAS_OK;
811
812     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
813
814     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
815                          ud->uh_sport, ud->uh_dport,
816                          IPPROTO_UDP, 1);
817     if (link != NULL)
818     {
819         u_short alias_port;
820         struct in_addr alias_address;
821
822         alias_address = GetAliasAddress(link);
823         alias_port = GetAliasPort(link);
824
825 /* Special processing for IP encoding protocols */
826         if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
827             AliasHandleCUSeeMeOut(pip, link);
828 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
829         else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
830               || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
831             AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
832         else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
833               || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
834             AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
835                                 &alias_address, &alias_port);
836 /*
837  * We don't know in advance what TID the TFTP server will choose,
838  * so we create a wilcard link (destination port is unspecified)
839  * that will match any TID from a given destination.
840  */
841         else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
842             FindRtspOut(pip->ip_src, pip->ip_dst,
843                         ud->uh_sport, alias_port, IPPROTO_UDP);
844
845 /* If UDP checksum is not zero, adjust since source port is */
846 /* being aliased and source address is being altered        */
847         if (ud->uh_sum != 0)
848         {
849             int accumulate;
850
851             accumulate  = ud->uh_sport;
852             accumulate -= alias_port;
853             accumulate += twowords(&pip->ip_src);
854             accumulate -= twowords(&alias_address);
855             ADJUST_CHECKSUM(accumulate, ud->uh_sum);
856         }
857
858 /* Put alias port in UDP header */
859         ud->uh_sport = alias_port;
860
861 /* Change source address */
862         DifferentialChecksum(&pip->ip_sum,
863                              (u_short *) &alias_address,
864                              (u_short *) &pip->ip_src,
865                              2);
866         pip->ip_src = alias_address;
867
868         return(PKT_ALIAS_OK);
869     }
870     return(PKT_ALIAS_IGNORED);
871 }
872
873
874
875 static int
876 TcpAliasIn(struct ip *pip)
877 {
878     struct tcphdr *tc;
879     struct alias_link *link;
880
881     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
882
883     link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
884                         tc->th_sport, tc->th_dport,
885                         IPPROTO_TCP,
886                         !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
887     if (link != NULL)
888     {
889         struct in_addr alias_address;
890         struct in_addr original_address;
891         struct in_addr proxy_address;
892         u_short alias_port;
893         u_short proxy_port;
894         int accumulate;
895
896 /* Special processing for IP encoding protocols */
897         if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
898          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
899             AliasHandlePptpIn(pip, link);
900
901         alias_address = GetAliasAddress(link);
902         original_address = GetOriginalAddress(link);
903         proxy_address = GetProxyAddress(link);
904         alias_port = tc->th_dport;
905         tc->th_dport = GetOriginalPort(link);
906         proxy_port = GetProxyPort(link);
907
908 /* Adjust TCP checksum since destination port is being unaliased */
909 /* and destination port is being altered.                        */
910         accumulate  = alias_port;
911         accumulate -= tc->th_dport;
912         accumulate += twowords(&alias_address);
913         accumulate -= twowords(&original_address);
914
915 /* If this is a proxy, then modify the TCP source port and
916    checksum accumulation */
917         if (proxy_port != 0)
918         {
919             accumulate += tc->th_sport;
920             tc->th_sport = proxy_port;
921             accumulate -= tc->th_sport;
922             accumulate += twowords(&pip->ip_src);
923             accumulate -= twowords(&proxy_address);
924         }
925
926 /* See if ACK number needs to be modified */
927         if (GetAckModified(link) == 1)
928         {
929             int delta;
930
931             delta = GetDeltaAckIn(pip, link);
932             if (delta != 0)
933             {
934                 accumulate += twowords(&tc->th_ack);
935                 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
936                 accumulate -= twowords(&tc->th_ack);
937             }
938         }
939
940         ADJUST_CHECKSUM(accumulate, tc->th_sum);
941
942 /* Restore original IP address */
943         accumulate  = twowords(&pip->ip_dst);
944         pip->ip_dst = original_address;
945         accumulate -= twowords(&pip->ip_dst);
946
947 /* If this is a transparent proxy packet, then modify the source
948    address */
949         if (proxy_address.s_addr != 0)
950         {
951           accumulate += twowords(&pip->ip_src);
952           pip->ip_src = proxy_address;
953           accumulate -= twowords(&pip->ip_src);
954         }
955
956         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
957
958 /* Monitor TCP connection state */
959         TcpMonitorIn(pip, link);
960
961         return(PKT_ALIAS_OK);
962     }
963     return(PKT_ALIAS_IGNORED);
964 }
965
966 static int
967 TcpAliasOut(struct ip *pip, int maxpacketsize)
968 {
969     int proxy_type;
970     u_short dest_port;
971     u_short proxy_server_port;
972     struct in_addr dest_address;
973     struct in_addr proxy_server_address;
974     struct tcphdr *tc;
975     struct alias_link *link;
976
977     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
978
979     proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
980
981     if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
982         return PKT_ALIAS_OK;
983
984 /* If this is a transparent proxy, save original destination,
985    then alter the destination and adjust checksums */
986     dest_port = tc->th_dport;
987     dest_address = pip->ip_dst;
988     if (proxy_type != 0)
989     {
990         int accumulate;
991
992         accumulate = tc->th_dport;
993         tc->th_dport = proxy_server_port;
994         accumulate -= tc->th_dport;
995         accumulate += twowords(&pip->ip_dst);
996         accumulate -= twowords(&proxy_server_address);
997         ADJUST_CHECKSUM(accumulate, tc->th_sum);
998
999         accumulate  = twowords(&pip->ip_dst);
1000         pip->ip_dst = proxy_server_address;
1001         accumulate -= twowords(&pip->ip_dst);
1002         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1003     }
1004
1005     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1006                          tc->th_sport, tc->th_dport,
1007                          IPPROTO_TCP, 1);
1008     if (link !=NULL)
1009     {
1010         u_short alias_port;
1011         struct in_addr alias_address;
1012         int accumulate;
1013
1014 /* Save original destination address, if this is a proxy packet.
1015    Also modify packet to include destination encoding.  This may
1016    change the size of IP header. */
1017         if (proxy_type != 0)
1018         {
1019             SetProxyPort(link, dest_port);
1020             SetProxyAddress(link, dest_address);
1021             ProxyModify(link, pip, maxpacketsize, proxy_type);
1022             tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1023         }
1024
1025 /* Get alias address and port */
1026         alias_port = GetAliasPort(link);
1027         alias_address = GetAliasAddress(link);
1028
1029 /* Monitor TCP connection state */
1030         TcpMonitorOut(pip, link);
1031
1032 /* Special processing for IP encoding protocols */
1033         if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1034          || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1035             AliasHandleFtpOut(pip, link, maxpacketsize);
1036         else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1037          || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1038             AliasHandleIrcOut(pip, link, maxpacketsize);
1039         else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1040          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1041          || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1042          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 
1043             AliasHandleRtspOut(pip, link, maxpacketsize);
1044         else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1045          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1046             AliasHandlePptpOut(pip, link);
1047
1048 /* Adjust TCP checksum since source port is being aliased */
1049 /* and source address is being altered                    */
1050         accumulate  = tc->th_sport;
1051         tc->th_sport = alias_port;
1052         accumulate -= tc->th_sport;
1053         accumulate += twowords(&pip->ip_src);
1054         accumulate -= twowords(&alias_address);
1055
1056 /* Modify sequence number if necessary */
1057         if (GetAckModified(link) == 1)
1058         {
1059             int delta;
1060
1061             delta = GetDeltaSeqOut(pip, link);
1062             if (delta != 0)
1063             {
1064                 accumulate += twowords(&tc->th_seq);
1065                 tc->th_seq  = htonl(ntohl(tc->th_seq) + delta);
1066                 accumulate -= twowords(&tc->th_seq);
1067             }
1068         }
1069
1070         ADJUST_CHECKSUM(accumulate, tc->th_sum);
1071
1072 /* Change source address */
1073         accumulate  = twowords(&pip->ip_src);
1074         pip->ip_src = alias_address;
1075         accumulate -= twowords(&pip->ip_src);
1076         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1077
1078         return(PKT_ALIAS_OK);
1079     }
1080     return(PKT_ALIAS_IGNORED);
1081 }
1082
1083
1084
1085
1086 /* Fragment Handling
1087
1088     FragmentIn()
1089     FragmentOut()
1090
1091 The packet aliasing module has a limited ability for handling IP
1092 fragments.  If the ICMP, TCP or UDP header is in the first fragment
1093 received, then the ID number of the IP packet is saved, and other
1094 fragments are identified according to their ID number and IP address
1095 they were sent from.  Pointers to unresolved fragments can also be
1096 saved and recalled when a header fragment is seen.
1097 */
1098
1099 /* Local prototypes */
1100 static int FragmentIn(struct ip *);
1101 static int FragmentOut(struct ip *);
1102
1103
1104 static int
1105 FragmentIn(struct ip *pip)
1106 {
1107     struct alias_link *link;
1108
1109     link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1110     if (link != NULL)
1111     {
1112         struct in_addr original_address;
1113
1114         GetFragmentAddr(link, &original_address);
1115         DifferentialChecksum(&pip->ip_sum,
1116                              (u_short *) &original_address,
1117                              (u_short *) &pip->ip_dst,
1118                              2);
1119         pip->ip_dst = original_address; 
1120    
1121         return(PKT_ALIAS_OK);
1122     }
1123     return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1124 }
1125
1126
1127 static int
1128 FragmentOut(struct ip *pip)
1129 {
1130     struct in_addr alias_address;
1131
1132     alias_address = FindAliasAddress(pip->ip_src);
1133     DifferentialChecksum(&pip->ip_sum,
1134                          (u_short *) &alias_address,
1135                          (u_short *) &pip->ip_src,
1136                           2);
1137     pip->ip_src = alias_address;
1138
1139     return(PKT_ALIAS_OK);
1140 }
1141
1142
1143
1144
1145
1146
1147 /* Outside World Access
1148
1149         PacketAliasSaveFragment()
1150         PacketAliasGetFragment()
1151         PacketAliasFragmentIn()
1152         PacketAliasIn()
1153         PacketAliasOut()
1154         PacketUnaliasOut()
1155
1156 (prototypes in alias.h)
1157 */
1158
1159
1160 int
1161 PacketAliasSaveFragment(char *ptr)
1162 {
1163     int iresult;
1164     struct alias_link *link;
1165     struct ip *pip;
1166
1167     pip = (struct ip *) ptr;
1168     link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1169     iresult = PKT_ALIAS_ERROR;
1170     if (link != NULL)
1171     {
1172         SetFragmentPtr(link, ptr);
1173         iresult = PKT_ALIAS_OK;
1174     }
1175     return(iresult);
1176 }
1177
1178
1179 char *
1180 PacketAliasGetFragment(char *ptr)
1181 {
1182     struct alias_link *link;
1183     char *fptr;
1184     struct ip *pip;
1185
1186     pip = (struct ip *) ptr;
1187     link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1188     if (link != NULL)
1189     {
1190         GetFragmentPtr(link, &fptr);
1191         SetFragmentPtr(link, NULL);
1192         SetExpire(link, 0); /* Deletes link */
1193
1194         return(fptr);
1195     }
1196     else
1197     {
1198         return(NULL);
1199     }
1200 }
1201
1202
1203 void
1204 PacketAliasFragmentIn(char *ptr,          /* Points to correctly de-aliased
1205                                              header fragment */
1206                       char *ptr_fragment  /* Points to fragment which must
1207                                              be de-aliased   */
1208                      )
1209 {
1210     struct ip *pip;
1211     struct ip *fpip;
1212
1213     pip = (struct ip *) ptr;
1214     fpip = (struct ip *) ptr_fragment;
1215
1216     DifferentialChecksum(&fpip->ip_sum,
1217                          (u_short *) &pip->ip_dst,
1218                          (u_short *) &fpip->ip_dst,
1219                          2);
1220     fpip->ip_dst = pip->ip_dst;
1221 }
1222
1223
1224 int
1225 PacketAliasIn(char *ptr, int maxpacketsize)
1226 {
1227     struct in_addr alias_addr;
1228     struct ip *pip;
1229     int iresult;
1230
1231     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1232         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1233         iresult = PacketAliasOut(ptr, maxpacketsize);
1234         packetAliasMode |= PKT_ALIAS_REVERSE;
1235         return iresult;
1236     }
1237
1238     HouseKeeping();
1239     ClearCheckNewLink();
1240     pip = (struct ip *) ptr;
1241     alias_addr = pip->ip_dst;
1242         
1243     /* Defense against mangled packets */
1244     if (ntohs(pip->ip_len) > maxpacketsize
1245      || (pip->ip_hl<<2) > maxpacketsize)
1246         return PKT_ALIAS_IGNORED;
1247         
1248     iresult = PKT_ALIAS_IGNORED;
1249     if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1250     {
1251         switch (pip->ip_p)
1252         {
1253             case IPPROTO_ICMP:
1254                 iresult = IcmpAliasIn(pip);
1255                 break;
1256             case IPPROTO_UDP:
1257                 iresult = UdpAliasIn(pip);
1258                 break;
1259             case IPPROTO_TCP:
1260                 iresult = TcpAliasIn(pip);
1261                 break;
1262             case IPPROTO_GRE:
1263                 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1264                     AliasHandlePptpGreIn(pip) == 0)
1265                     iresult = PKT_ALIAS_OK;
1266                 else
1267                     iresult = ProtoAliasIn(pip);
1268                 break;
1269             default:
1270                 iresult = ProtoAliasIn(pip);
1271                 break;
1272         }
1273
1274         if (ntohs(pip->ip_off) & IP_MF)
1275         {
1276             struct alias_link *link;
1277
1278             link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1279             if (link != NULL)
1280             {
1281                 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1282                 SetFragmentAddr(link, pip->ip_dst);
1283             }
1284             else
1285             {
1286                 iresult = PKT_ALIAS_ERROR;
1287             }
1288         }
1289     }
1290     else
1291     {
1292         iresult = FragmentIn(pip);
1293     }
1294
1295     return(iresult);
1296 }
1297
1298
1299
1300 /* Unregistered address ranges */
1301
1302 /* 10.0.0.0   ->   10.255.255.255 */
1303 #define UNREG_ADDR_A_LOWER 0x0a000000
1304 #define UNREG_ADDR_A_UPPER 0x0affffff
1305
1306 /* 172.16.0.0  ->  172.31.255.255 */
1307 #define UNREG_ADDR_B_LOWER 0xac100000
1308 #define UNREG_ADDR_B_UPPER 0xac1fffff
1309
1310 /* 192.168.0.0 -> 192.168.255.255 */
1311 #define UNREG_ADDR_C_LOWER 0xc0a80000
1312 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1313
1314 int
1315 PacketAliasOut(char *ptr,           /* valid IP packet */
1316                int  maxpacketsize   /* How much the packet data may grow
1317                                        (FTP and IRC inline changes) */
1318               )
1319 {
1320     int iresult;
1321     struct in_addr addr_save;
1322     struct ip *pip;
1323
1324     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1325         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1326         iresult = PacketAliasIn(ptr, maxpacketsize);
1327         packetAliasMode |= PKT_ALIAS_REVERSE;
1328         return iresult;
1329     }
1330
1331     HouseKeeping();
1332     ClearCheckNewLink();
1333     pip = (struct ip *) ptr;
1334
1335     /* Defense against mangled packets */
1336     if (ntohs(pip->ip_len) > maxpacketsize
1337      || (pip->ip_hl<<2) > maxpacketsize)
1338         return PKT_ALIAS_IGNORED;
1339
1340     addr_save = GetDefaultAliasAddress();
1341     if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1342     {
1343         u_long addr;
1344         int iclass;
1345
1346         iclass = 0;
1347         addr = ntohl(pip->ip_src.s_addr);
1348         if      (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1349             iclass = 3;
1350         else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1351             iclass = 2;
1352         else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1353             iclass = 1;
1354
1355         if (iclass == 0)
1356         {
1357             SetDefaultAliasAddress(pip->ip_src);
1358         }
1359     }
1360
1361     iresult = PKT_ALIAS_IGNORED;
1362     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1363     {
1364         switch (pip->ip_p)
1365         {
1366             case IPPROTO_ICMP:
1367                 iresult = IcmpAliasOut(pip);
1368                 break;
1369             case IPPROTO_UDP:
1370                 iresult = UdpAliasOut(pip);
1371                 break;
1372             case IPPROTO_TCP:
1373                 iresult = TcpAliasOut(pip, maxpacketsize);
1374                 break;
1375             case IPPROTO_GRE:
1376                 if (AliasHandlePptpGreOut(pip) == 0)
1377                     iresult = PKT_ALIAS_OK;
1378                 else
1379                     iresult = ProtoAliasOut(pip);
1380                 break;
1381             default:
1382                 iresult = ProtoAliasOut(pip);
1383                 break;
1384         }
1385     }
1386     else
1387     {
1388         iresult = FragmentOut(pip);
1389     }
1390
1391     SetDefaultAliasAddress(addr_save);
1392     return(iresult);
1393 }
1394
1395 int
1396 PacketUnaliasOut(char *ptr,           /* valid IP packet */
1397                  int  maxpacketsize   /* for error checking */
1398                 )
1399 {
1400     struct ip           *pip;
1401     struct icmp         *ic;
1402     struct udphdr       *ud;
1403     struct tcphdr       *tc;
1404     struct alias_link   *link;
1405     int                 iresult = PKT_ALIAS_IGNORED;
1406
1407     pip = (struct ip *) ptr;
1408
1409     /* Defense against mangled packets */
1410     if (ntohs(pip->ip_len) > maxpacketsize
1411      || (pip->ip_hl<<2) > maxpacketsize)
1412         return(iresult);
1413
1414     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1415     tc = (struct tcphdr *) ud;
1416     ic = (struct icmp *) ud;
1417
1418     /* Find a link */
1419     if (pip->ip_p == IPPROTO_UDP)
1420         link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1421                             ud->uh_dport, ud->uh_sport,
1422                             IPPROTO_UDP, 0);
1423     else if (pip->ip_p == IPPROTO_TCP)
1424         link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1425                             tc->th_dport, tc->th_sport,
1426                             IPPROTO_TCP, 0);
1427     else if (pip->ip_p == IPPROTO_ICMP) 
1428         link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1429     else
1430         link = NULL;
1431
1432     /* Change it from an aliased packet to an unaliased packet */
1433     if (link != NULL)
1434     {
1435         if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1436         {
1437             int            accumulate;
1438             struct in_addr original_address;
1439             u_short        original_port;
1440
1441             original_address = GetOriginalAddress(link);
1442             original_port = GetOriginalPort(link);
1443     
1444             /* Adjust TCP/UDP checksum */
1445             accumulate  = twowords(&pip->ip_src);
1446             accumulate -= twowords(&original_address);
1447
1448             if (pip->ip_p == IPPROTO_UDP) {
1449                 accumulate += ud->uh_sport;
1450                 accumulate -= original_port;
1451                 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1452             } else { 
1453                 accumulate += tc->th_sport;
1454                 accumulate -= original_port;
1455                 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1456             }
1457
1458             /* Adjust IP checksum */
1459             DifferentialChecksum(&pip->ip_sum,
1460                                  (u_short *) &original_address,
1461                                  (u_short *) &pip->ip_src,
1462                                  2);
1463
1464             /* Un-alias source address and port number */ 
1465             pip->ip_src = original_address;
1466             if (pip->ip_p == IPPROTO_UDP) 
1467                 ud->uh_sport = original_port; 
1468             else   
1469                 tc->th_sport = original_port; 
1470             
1471             iresult = PKT_ALIAS_OK;
1472
1473         } else if (pip->ip_p == IPPROTO_ICMP) {
1474
1475             int            accumulate;
1476             struct in_addr original_address;
1477             u_short        original_id;
1478
1479             original_address = GetOriginalAddress(link);
1480             original_id = GetOriginalPort(link);
1481
1482             /* Adjust ICMP checksum */
1483             accumulate  = twowords(&pip->ip_src);
1484             accumulate -= twowords(&original_address);
1485             accumulate += ic->icmp_id;
1486             accumulate -= original_id;
1487             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1488
1489             /* Adjust IP checksum */
1490             DifferentialChecksum(&pip->ip_sum,
1491                                  (u_short *) &original_address,
1492                                  (u_short *) &pip->ip_src,
1493                                  2);
1494
1495             /* Un-alias source address and port number */
1496             pip->ip_src = original_address;
1497             ic->icmp_id = original_id;
1498
1499             iresult = PKT_ALIAS_OK;
1500         }
1501     }
1502     return(iresult);
1503
1504 }