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