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