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