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