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