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