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