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