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