alias.c revision 85964
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: head/sys/netinet/libalias/alias.c 85964 2001-11-03 11:34:09Z brian $");
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
149These routines look for SYN, FIN and RST flags to determine when TCP
150connections open and close.  When a TCP connection closes, the data
151structure containing packet aliasing information is deleted after
152a timeout period.
153*/
154
155/* Local prototypes */
156static void TcpMonitorIn(struct ip *, struct alias_link *);
157
158static void TcpMonitorOut(struct ip *, struct alias_link *);
159
160
161static void
162TcpMonitorIn(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
183static void
184TcpMonitorOut(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
217These routines handle protocol specific details of packet aliasing.
218One may observe a certain amount of repetitive arithmetic in these
219functions, the purpose of which is to compute a revised checksum
220without actually summing over the entire data packet, which could be
221unnecessarily time consuming.
222
223The purpose of the packet aliasing routines is to replace the source
224address of the outgoing packet and then correctly put it back for
225any incoming packets.  For TCP and UDP, ports are also re-mapped.
226
227For ICMP echo/timestamp requests and replies, the following scheme
228is used: the ID number is replaced by an alias for the outgoing
229packet.
230
231ICMP error messages are handled by looking at the IP fragment
232in the data section of the message.
233
234For TCP and UDP protocols, a port number is chosen for an outgoing
235packet, and then incoming packets are identified by IP address and
236port numbers.  For TCP packets, there is additional logic in the event
237that sequence and ACK numbers have been altered (as in the case for
238FTP data port commands).
239
240The port numbers used by the packet aliasing module are not true
241ports in the Unix sense.  No sockets are actually bound to ports.
242They are more correctly thought of as placeholders.
243
244All packets go through the aliasing mechanism, whether they come from
245the gateway machine or other machines on a local area network.
246*/
247
248
249/* Local prototypes */
250static int IcmpAliasIn1(struct ip *);
251static int IcmpAliasIn2(struct ip *);
252static int IcmpAliasIn (struct ip *);
253
254static int IcmpAliasOut1(struct ip *);
255static int IcmpAliasOut2(struct ip *);
256static int IcmpAliasOut (struct ip *);
257
258static int ProtoAliasIn(struct ip *);
259static int ProtoAliasOut(struct ip *);
260
261static int UdpAliasOut(struct ip *);
262static int UdpAliasIn (struct ip *);
263
264static int TcpAliasOut(struct ip *, int);
265static int TcpAliasIn (struct ip *);
266
267
268static int
269IcmpAliasIn1(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
314static int
315IcmpAliasIn2(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
381fragment 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
424static int
425IcmpAliasIn(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
461static int
462IcmpAliasOut1(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
508static int
509IcmpAliasOut2(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
580fragment 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
628static int
629IcmpAliasOut(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
665static int
666ProtoAliasIn(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
700static int
701ProtoAliasOut(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
734static int
735UdpAliasIn(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
808static int
809UdpAliasOut(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
886static int
887TcpAliasIn(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
999static int
1000TcpAliasOut(struct ip *pip, int maxpacketsize)
1001{
1002    int proxy_type;
1003    u_short dest_port;
1004    u_short proxy_server_port;
1005    struct in_addr dest_address;
1006    struct in_addr proxy_server_address;
1007    struct tcphdr *tc;
1008    struct alias_link *link;
1009
1010    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1011
1012    proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1013
1014    if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1015        return PKT_ALIAS_OK;
1016
1017/* If this is a transparent proxy, save original destination,
1018   then alter the destination and adjust checksums */
1019    dest_port = tc->th_dport;
1020    dest_address = pip->ip_dst;
1021    if (proxy_type != 0)
1022    {
1023        int accumulate;
1024        u_short *sptr;
1025
1026        accumulate = tc->th_dport;
1027        tc->th_dport = proxy_server_port;
1028        accumulate -= tc->th_dport;
1029
1030        sptr = (u_short *) &(pip->ip_dst);
1031        accumulate += *sptr++;
1032        accumulate += *sptr;
1033        sptr = (u_short *) &proxy_server_address;
1034        accumulate -= *sptr++;
1035        accumulate -= *sptr;
1036
1037        ADJUST_CHECKSUM(accumulate, tc->th_sum);
1038
1039        sptr = (u_short *) &(pip->ip_dst);
1040        accumulate  = *sptr++;
1041        accumulate += *sptr;
1042        pip->ip_dst = proxy_server_address;
1043        sptr = (u_short *) &(pip->ip_dst);
1044        accumulate -= *sptr++;
1045        accumulate -= *sptr;
1046
1047        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1048    }
1049
1050    link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1051                         tc->th_sport, tc->th_dport,
1052                         IPPROTO_TCP, 1);
1053    if (link !=NULL)
1054    {
1055        u_short alias_port;
1056        struct in_addr alias_address;
1057        int accumulate;
1058        u_short *sptr;
1059
1060/* Save original destination address, if this is a proxy packet.
1061   Also modify packet to include destination encoding. */
1062        if (proxy_type != 0)
1063        {
1064            SetProxyPort(link, dest_port);
1065            SetProxyAddress(link, dest_address);
1066            ProxyModify(link, pip, maxpacketsize, proxy_type);
1067        }
1068
1069/* Get alias address and port */
1070        alias_port = GetAliasPort(link);
1071        alias_address = GetAliasAddress(link);
1072
1073/* Monitor TCP connection state */
1074        TcpMonitorOut(pip, link);
1075
1076/* Special processing for IP encoding protocols */
1077        if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1078         || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1079            AliasHandleFtpOut(pip, link, maxpacketsize);
1080        else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1081         || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1082            AliasHandleIrcOut(pip, link, maxpacketsize);
1083        else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1084         || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1085         || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1086         || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1087            AliasHandleRtspOut(pip, link, maxpacketsize);
1088        else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1089         || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1090            AliasHandlePptpOut(pip, link);
1091
1092/* Adjust TCP checksum since source port is being aliased */
1093/* and source address is being altered                    */
1094        accumulate  = tc->th_sport;
1095        tc->th_sport = alias_port;
1096        accumulate -= tc->th_sport;
1097
1098        sptr = (u_short *) &(pip->ip_src);
1099        accumulate += *sptr++;
1100        accumulate += *sptr;
1101        sptr = (u_short *) &alias_address;
1102        accumulate -= *sptr++;
1103        accumulate -= *sptr;
1104
1105/* Modify sequence number if necessary */
1106        if (GetAckModified(link) == 1)
1107        {
1108            int delta;
1109
1110            delta = GetDeltaSeqOut(pip, link);
1111            if (delta != 0)
1112            {
1113                sptr = (u_short *) &tc->th_seq;
1114                accumulate += *sptr++;
1115                accumulate += *sptr;
1116                tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1117                sptr = (u_short *) &tc->th_seq;
1118                accumulate -= *sptr++;
1119                accumulate -= *sptr;
1120            }
1121        }
1122
1123        ADJUST_CHECKSUM(accumulate, tc->th_sum);
1124
1125/* Change source address */
1126        sptr = (u_short *) &(pip->ip_src);
1127        accumulate  = *sptr++;
1128        accumulate += *sptr;
1129        pip->ip_src = alias_address;
1130        sptr = (u_short *) &(pip->ip_src);
1131        accumulate -= *sptr++;
1132        accumulate -= *sptr;
1133
1134        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1135
1136        return(PKT_ALIAS_OK);
1137    }
1138    return(PKT_ALIAS_IGNORED);
1139}
1140
1141
1142
1143
1144/* Fragment Handling
1145
1146    FragmentIn()
1147    FragmentOut()
1148
1149The packet aliasing module has a limited ability for handling IP
1150fragments.  If the ICMP, TCP or UDP header is in the first fragment
1151received, then the ID number of the IP packet is saved, and other
1152fragments are identified according to their ID number and IP address
1153they were sent from.  Pointers to unresolved fragments can also be
1154saved and recalled when a header fragment is seen.
1155*/
1156
1157/* Local prototypes */
1158static int FragmentIn(struct ip *);
1159static int FragmentOut(struct ip *);
1160
1161
1162static int
1163FragmentIn(struct ip *pip)
1164{
1165    struct alias_link *link;
1166
1167    link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1168    if (link != NULL)
1169    {
1170        struct in_addr original_address;
1171
1172        GetFragmentAddr(link, &original_address);
1173        DifferentialChecksum(&pip->ip_sum,
1174                             (u_short *) &original_address,
1175                             (u_short *) &pip->ip_dst,
1176                             2);
1177        pip->ip_dst = original_address;
1178
1179        return(PKT_ALIAS_OK);
1180    }
1181    return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1182}
1183
1184
1185static int
1186FragmentOut(struct ip *pip)
1187{
1188    struct in_addr alias_address;
1189
1190    alias_address = FindAliasAddress(pip->ip_src);
1191    DifferentialChecksum(&pip->ip_sum,
1192                         (u_short *) &alias_address,
1193                         (u_short *) &pip->ip_src,
1194                          2);
1195    pip->ip_src = alias_address;
1196
1197    return(PKT_ALIAS_OK);
1198}
1199
1200
1201
1202
1203
1204
1205/* Outside World Access
1206
1207        PacketAliasSaveFragment()
1208        PacketAliasGetFragment()
1209        PacketAliasFragmentIn()
1210        PacketAliasIn()
1211        PacketAliasOut()
1212        PacketUnaliasOut()
1213
1214(prototypes in alias.h)
1215*/
1216
1217
1218int
1219PacketAliasSaveFragment(char *ptr)
1220{
1221    int iresult;
1222    struct alias_link *link;
1223    struct ip *pip;
1224
1225    pip = (struct ip *) ptr;
1226    link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1227    iresult = PKT_ALIAS_ERROR;
1228    if (link != NULL)
1229    {
1230        SetFragmentPtr(link, ptr);
1231        iresult = PKT_ALIAS_OK;
1232    }
1233    return(iresult);
1234}
1235
1236
1237char *
1238PacketAliasGetFragment(char *ptr)
1239{
1240    struct alias_link *link;
1241    char *fptr;
1242    struct ip *pip;
1243
1244    pip = (struct ip *) ptr;
1245    link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1246    if (link != NULL)
1247    {
1248        GetFragmentPtr(link, &fptr);
1249        SetFragmentPtr(link, NULL);
1250        SetExpire(link, 0); /* Deletes link */
1251
1252        return(fptr);
1253    }
1254    else
1255    {
1256        return(NULL);
1257    }
1258}
1259
1260
1261void
1262PacketAliasFragmentIn(char *ptr,          /* Points to correctly de-aliased
1263                                             header fragment */
1264                      char *ptr_fragment  /* Points to fragment which must
1265                                             be de-aliased   */
1266                     )
1267{
1268    struct ip *pip;
1269    struct ip *fpip;
1270
1271    pip = (struct ip *) ptr;
1272    fpip = (struct ip *) ptr_fragment;
1273
1274    DifferentialChecksum(&fpip->ip_sum,
1275                         (u_short *) &pip->ip_dst,
1276                         (u_short *) &fpip->ip_dst,
1277                         2);
1278    fpip->ip_dst = pip->ip_dst;
1279}
1280
1281
1282int
1283PacketAliasIn(char *ptr, int maxpacketsize)
1284{
1285    struct in_addr alias_addr;
1286    struct ip *pip;
1287    int iresult;
1288
1289    if (packetAliasMode & PKT_ALIAS_REVERSE) {
1290        packetAliasMode &= ~PKT_ALIAS_REVERSE;
1291        iresult = PacketAliasOut(ptr, maxpacketsize);
1292        packetAliasMode |= PKT_ALIAS_REVERSE;
1293        return iresult;
1294    }
1295
1296    HouseKeeping();
1297    ClearCheckNewLink();
1298    pip = (struct ip *) ptr;
1299    alias_addr = pip->ip_dst;
1300
1301    /* Defense against mangled packets */
1302    if (ntohs(pip->ip_len) > maxpacketsize
1303     || (pip->ip_hl<<2) > maxpacketsize)
1304        return PKT_ALIAS_IGNORED;
1305
1306    iresult = PKT_ALIAS_IGNORED;
1307    if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1308    {
1309        switch (pip->ip_p)
1310        {
1311            case IPPROTO_ICMP:
1312                iresult = IcmpAliasIn(pip);
1313                break;
1314            case IPPROTO_UDP:
1315                iresult = UdpAliasIn(pip);
1316                break;
1317            case IPPROTO_TCP:
1318                iresult = TcpAliasIn(pip);
1319                break;
1320            case IPPROTO_GRE:
1321		if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1322		    AliasHandlePptpGreIn(pip) == 0)
1323		    iresult = PKT_ALIAS_OK;
1324		else
1325		    iresult = ProtoAliasIn(pip);
1326		break;
1327	    default:
1328		iresult = ProtoAliasIn(pip);
1329                break;
1330        }
1331
1332        if (ntohs(pip->ip_off) & IP_MF)
1333        {
1334            struct alias_link *link;
1335
1336            link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1337            if (link != NULL)
1338            {
1339                iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1340                SetFragmentAddr(link, pip->ip_dst);
1341            }
1342            else
1343            {
1344                iresult = PKT_ALIAS_ERROR;
1345            }
1346        }
1347    }
1348    else
1349    {
1350        iresult = FragmentIn(pip);
1351    }
1352
1353    return(iresult);
1354}
1355
1356
1357
1358/* Unregistered address ranges */
1359
1360/* 10.0.0.0   ->   10.255.255.255 */
1361#define UNREG_ADDR_A_LOWER 0x0a000000
1362#define UNREG_ADDR_A_UPPER 0x0affffff
1363
1364/* 172.16.0.0  ->  172.31.255.255 */
1365#define UNREG_ADDR_B_LOWER 0xac100000
1366#define UNREG_ADDR_B_UPPER 0xac1fffff
1367
1368/* 192.168.0.0 -> 192.168.255.255 */
1369#define UNREG_ADDR_C_LOWER 0xc0a80000
1370#define UNREG_ADDR_C_UPPER 0xc0a8ffff
1371
1372int
1373PacketAliasOut(char *ptr,           /* valid IP packet */
1374               int  maxpacketsize   /* How much the packet data may grow
1375                                       (FTP and IRC inline changes) */
1376              )
1377{
1378    int iresult;
1379    struct in_addr addr_save;
1380    struct ip *pip;
1381
1382    if (packetAliasMode & PKT_ALIAS_REVERSE) {
1383        packetAliasMode &= ~PKT_ALIAS_REVERSE;
1384        iresult = PacketAliasIn(ptr, maxpacketsize);
1385        packetAliasMode |= PKT_ALIAS_REVERSE;
1386        return iresult;
1387    }
1388
1389    HouseKeeping();
1390    ClearCheckNewLink();
1391    pip = (struct ip *) ptr;
1392
1393    /* Defense against mangled packets */
1394    if (ntohs(pip->ip_len) > maxpacketsize
1395     || (pip->ip_hl<<2) > maxpacketsize)
1396        return PKT_ALIAS_IGNORED;
1397
1398    addr_save = GetDefaultAliasAddress();
1399    if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1400    {
1401        u_long addr;
1402        int iclass;
1403
1404        iclass = 0;
1405        addr = ntohl(pip->ip_src.s_addr);
1406        if      (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1407            iclass = 3;
1408        else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1409            iclass = 2;
1410        else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1411            iclass = 1;
1412
1413        if (iclass == 0)
1414        {
1415            SetDefaultAliasAddress(pip->ip_src);
1416        }
1417    }
1418
1419    iresult = PKT_ALIAS_IGNORED;
1420    if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1421    {
1422        switch (pip->ip_p)
1423        {
1424            case IPPROTO_ICMP:
1425                iresult = IcmpAliasOut(pip);
1426                break;
1427            case IPPROTO_UDP:
1428                iresult = UdpAliasOut(pip);
1429                break;
1430            case IPPROTO_TCP:
1431                iresult = TcpAliasOut(pip, maxpacketsize);
1432                break;
1433	    case IPPROTO_GRE:
1434		if (AliasHandlePptpGreOut(pip) == 0)
1435		    iresult = PKT_ALIAS_OK;
1436		else
1437		    iresult = ProtoAliasOut(pip);
1438		break;
1439	    default:
1440		iresult = ProtoAliasOut(pip);
1441                break;
1442        }
1443    }
1444    else
1445    {
1446        iresult = FragmentOut(pip);
1447    }
1448
1449    SetDefaultAliasAddress(addr_save);
1450    return(iresult);
1451}
1452
1453int
1454PacketUnaliasOut(char *ptr,           /* valid IP packet */
1455                 int  maxpacketsize   /* for error checking */
1456                )
1457{
1458    struct ip		*pip;
1459    struct icmp 	*ic;
1460    struct udphdr	*ud;
1461    struct tcphdr 	*tc;
1462    struct alias_link 	*link;
1463    int 		iresult = PKT_ALIAS_IGNORED;
1464
1465    pip = (struct ip *) ptr;
1466
1467    /* Defense against mangled packets */
1468    if (ntohs(pip->ip_len) > maxpacketsize
1469     || (pip->ip_hl<<2) > maxpacketsize)
1470        return(iresult);
1471
1472    ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1473    tc = (struct tcphdr *) ud;
1474    ic = (struct icmp *) ud;
1475
1476    /* Find a link */
1477    if (pip->ip_p == IPPROTO_UDP)
1478        link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1479                            ud->uh_dport, ud->uh_sport,
1480                            IPPROTO_UDP, 0);
1481    else if (pip->ip_p == IPPROTO_TCP)
1482        link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1483                            tc->th_dport, tc->th_sport,
1484                            IPPROTO_TCP, 0);
1485    else if (pip->ip_p == IPPROTO_ICMP)
1486        link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1487    else
1488        link = NULL;
1489
1490    /* Change it from an aliased packet to an unaliased packet */
1491    if (link != NULL)
1492    {
1493        if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1494        {
1495            u_short        *sptr;
1496            int 	   accumulate;
1497            struct in_addr original_address;
1498            u_short        original_port;
1499
1500            original_address = GetOriginalAddress(link);
1501            original_port = GetOriginalPort(link);
1502
1503            /* Adjust TCP/UDP checksum */
1504            sptr = (u_short *) &(pip->ip_src);
1505            accumulate  = *sptr++;
1506            accumulate += *sptr;
1507            sptr = (u_short *) &original_address;
1508            accumulate -= *sptr++;
1509            accumulate -= *sptr;
1510
1511            if (pip->ip_p == IPPROTO_UDP) {
1512                accumulate += ud->uh_sport;
1513                accumulate -= original_port;
1514                ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1515	    } else {
1516                accumulate += tc->th_sport;
1517                accumulate -= original_port;
1518                ADJUST_CHECKSUM(accumulate, tc->th_sum);
1519	    }
1520
1521            /* Adjust IP checksum */
1522            DifferentialChecksum(&pip->ip_sum,
1523                                 (u_short *) &original_address,
1524                                 (u_short *) &pip->ip_src,
1525                                 2);
1526
1527            /* Un-alias source address and port number */
1528            pip->ip_src = original_address;
1529            if (pip->ip_p == IPPROTO_UDP)
1530                ud->uh_sport = original_port;
1531	    else
1532                tc->th_sport = original_port;
1533
1534	    iresult = PKT_ALIAS_OK;
1535
1536        } else if (pip->ip_p == IPPROTO_ICMP) {
1537
1538            u_short        *sptr;
1539            int            accumulate;
1540            struct in_addr original_address;
1541            u_short        original_id;
1542
1543            original_address = GetOriginalAddress(link);
1544            original_id = GetOriginalPort(link);
1545
1546            /* Adjust ICMP checksum */
1547            sptr = (u_short *) &(pip->ip_src);
1548            accumulate  = *sptr++;
1549            accumulate += *sptr;
1550            sptr = (u_short *) &original_address;
1551            accumulate -= *sptr++;
1552            accumulate -= *sptr;
1553            accumulate += ic->icmp_id;
1554            accumulate -= original_id;
1555            ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1556
1557            /* Adjust IP checksum */
1558            DifferentialChecksum(&pip->ip_sum,
1559                                 (u_short *) &original_address,
1560                                 (u_short *) &pip->ip_src,
1561                                 2);
1562
1563            /* Un-alias source address and port number */
1564            pip->ip_src = original_address;
1565            ic->icmp_id = original_id;
1566
1567	    iresult = PKT_ALIAS_OK;
1568        }
1569    }
1570    return(iresult);
1571
1572}
1573