alias.c revision 67980
1265555Sambrisko/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
2282531Skadesai/*
3272744Skadesai    Alias.c provides supervisory control for the functions of the
4282531Skadesai    packet aliasing software.  It consists of routines to monitor
5265555Sambrisko    TCP connection state, protocol-specific aliasing routines,
6265555Sambrisko    fragment handling and the following outside world functional
7272744Skadesai    interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
8272744Skadesai    PacketAliasIn and PacketAliasOut.
9265555Sambrisko
10272744Skadesai    The other C program files are briefly described. The data
11272744Skadesai    structure framework which holds information needed to translate
12272744Skadesai    packets is encapsulated in alias_db.c.  Data is accessed by
13272744Skadesai    function calls, so other segments of the program need not know
14272744Skadesai    about the underlying data structures.  Alias_ftp.c contains
15272744Skadesai    special code for modifying the ftp PORT command used to establish
16272744Skadesai    data connections, while alias_irc.c does the same for IRC
17272744Skadesai    DCC. Alias_util.c contains a few utility routines.
18265555Sambrisko
19272744Skadesai    This software is placed into the public domain with no restrictions
20272744Skadesai    on its distribution.
21272744Skadesai
22272744Skadesai    Version 1.0 August, 1996  (cjm)
23272744Skadesai
24272744Skadesai    Version 1.1 August 20, 1996  (cjm)
25272744Skadesai        PPP host accepts incoming connections for ports 0 to 1023.
26272744Skadesai        (Gary Roberts pointed out the need to handle incoming
27272744Skadesai         connections.)
28272744Skadesai
29265555Sambrisko    Version 1.2 September 7, 1996 (cjm)
30265555Sambrisko        Fragment handling error in alias_db.c corrected.
31272744Skadesai        (Tom Torrance helped fix this problem.)
32272744Skadesai
33265555Sambrisko    Version 1.4 September 16, 1996 (cjm)
34265555Sambrisko        - A more generalized method for handling incoming
35282531Skadesai          connections, without the 0-1023 restriction, is
36272744Skadesai          implemented in alias_db.c
37265555Sambrisko        - Improved ICMP support in alias.c.  Traceroute
38265555Sambrisko          packet streams can now be correctly aliased.
39265555Sambrisko        - TCP connection closing logic simplified in
40265555Sambrisko          alias.c and now allows for additional 1 minute
41265555Sambrisko          "grace period" after FIN or RST is observed.
42265555Sambrisko
43265555Sambrisko    Version 1.5 September 17, 1996 (cjm)
44265555Sambrisko        Corrected error in handling incoming UDP packets with 0 checksum.
45265555Sambrisko        (Tom Torrance helped fix this problem.)
46265555Sambrisko
47265555Sambrisko    Version 1.6 September 18, 1996 (cjm)
48265555Sambrisko        Simplified ICMP aliasing scheme.  Should now support
49265555Sambrisko        traceroute from Win95 as well as FreeBSD.
50265555Sambrisko
51265555Sambrisko    Version 1.7 January 9, 1997 (cjm)
52265555Sambrisko        - Out-of-order fragment handling.
53265555Sambrisko        - IP checksum error fixed for ftp transfers
54265555Sambrisko          from aliasing host.
55265555Sambrisko        - Integer return codes added to all
56265555Sambrisko          aliasing/de-aliasing functions.
57265555Sambrisko        - Some obsolete comments cleaned up.
58272744Skadesai        - Differential checksum computations for
59282533Skadesai          IP header (TCP, UDP and ICMP were already
60282533Skadesai          differential).
61282533Skadesai
62272744Skadesai    Version 2.1 May 1997 (cjm)
63272744Skadesai        - Added support for outgoing ICMP error
64272744Skadesai          messages.
65282533Skadesai        - Added two functions PacketAliasIn2()
66272744Skadesai          and PacketAliasOut2() for dynamic address
67272744Skadesai          control (e.g. round-robin allocation of
68272744Skadesai          incoming packets).
69272744Skadesai
70272744Skadesai    Version 2.2 July 1997 (cjm)
71272744Skadesai        - Rationalized API function names to begin
72272744Skadesai          with "PacketAlias..."
73282533Skadesai        - Eliminated PacketAliasIn2() and
74282533Skadesai          PacketAliasOut2() as poorly conceived.
75282533Skadesai
76265555Sambrisko    Version 2.3 Dec 1998 (dillon)
77282533Skadesai	- Major bounds checking additions, see FreeBSD/CVS
78272744Skadesai
79272744Skadesai    Version 3.1 May, 2000 (salander)
80265555Sambrisko	- Added hooks to handle PPTP.
81272744Skadesai
82282533Skadesai    Version 3.2 July, 2000 (salander and satoh)
83282533Skadesai	- Added PacketUnaliasOut routine.
84282533Skadesai	- Added hooks to handle RTSP/RTP.
85272744Skadesai
86272744Skadesai    See HISTORY file for additional revisions.
87272744Skadesai
88272744Skadesai    $FreeBSD: head/sys/netinet/libalias/alias.c 67980 2000-10-30 17:24:12Z ru $
89282533Skadesai*/
90272744Skadesai
91272744Skadesai#include <sys/types.h>
92272744Skadesai
93282533Skadesai#include <netinet/in_systm.h>
94272744Skadesai#include <netinet/in.h>
95272744Skadesai#include <netinet/ip.h>
96272744Skadesai#include <netinet/ip_icmp.h>
97272744Skadesai#include <netinet/tcp.h>
98272744Skadesai#include <netinet/udp.h>
99282533Skadesai
100272744Skadesai#include "alias_local.h"
101272744Skadesai#include "alias.h"
102272744Skadesai
103272744Skadesai#define NETBIOS_NS_PORT_NUMBER 137
104272744Skadesai#define NETBIOS_DGM_PORT_NUMBER 138
105272744Skadesai#define FTP_CONTROL_PORT_NUMBER 21
106272744Skadesai#define IRC_CONTROL_PORT_NUMBER_1 6667
107265555Sambrisko#define IRC_CONTROL_PORT_NUMBER_2 6668
108272735Skadesai#define CUSEEME_PORT_NUMBER 7648
109265555Sambrisko#define RTSP_CONTROL_PORT_NUMBER_1 554
110272744Skadesai#define RTSP_CONTROL_PORT_NUMBER_2 7070
111272744Skadesai#define PPTP_CONTROL_PORT_NUMBER 1723
112265555Sambrisko
113272744Skadesai
114272744Skadesai
115272744Skadesai
116272744Skadesai/* TCP Handling Routines
117272744Skadesai
118272744Skadesai    TcpMonitorIn()  -- These routines monitor TCP connections, and
119272744Skadesai    TcpMonitorOut()    delete a link when a connection is closed.
120272744Skadesai
121272744SkadesaiThese routines look for SYN, FIN and RST flags to determine when TCP
122272744Skadesaiconnections open and close.  When a TCP connection closes, the data
123272744Skadesaistructure containing packet aliasing information is deleted after
124272744Skadesaia timeout period.
125272744Skadesai*/
126272744Skadesai
127272744Skadesai/* Local prototypes */
128265555Sambriskostatic void TcpMonitorIn(struct ip *, struct alias_link *);
129265555Sambrisko
130265555Sambriskostatic void TcpMonitorOut(struct ip *, struct alias_link *);
131272744Skadesai
132265555Sambrisko
133272744Skadesaistatic void
134272744SkadesaiTcpMonitorIn(struct ip *pip, struct alias_link *link)
135272744Skadesai{
136272744Skadesai    struct tcphdr *tc;
137272744Skadesai
138265555Sambrisko    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
139265555Sambrisko
140265555Sambrisko    switch (GetStateIn(link))
141265555Sambrisko    {
142265555Sambrisko        case ALIAS_TCP_STATE_NOT_CONNECTED:
143272744Skadesai            if (tc->th_flags & TH_RST)
144272744Skadesai                SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
145265555Sambrisko            else if (tc->th_flags & TH_SYN)
146272744Skadesai                SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
147272744Skadesai            break;
148272744Skadesai        case ALIAS_TCP_STATE_CONNECTED:
149265555Sambrisko            if (tc->th_flags & (TH_FIN | TH_RST))
150282533Skadesai                SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
151265555Sambrisko            break;
152282527Skadesai    }
153265555Sambrisko}
154265555Sambrisko
155265555Sambriskostatic void
156265555SambriskoTcpMonitorOut(struct ip *pip, struct alias_link *link)
157272744Skadesai{
158265555Sambrisko    struct tcphdr *tc;
159272744Skadesai
160265555Sambrisko    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
161265555Sambrisko
162265555Sambrisko    switch (GetStateOut(link))
163265555Sambrisko    {
164265555Sambrisko        case ALIAS_TCP_STATE_NOT_CONNECTED:
165265555Sambrisko            if (tc->th_flags & TH_RST)
166265555Sambrisko                SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
167265555Sambrisko            else if (tc->th_flags & TH_SYN)
168272744Skadesai                SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
169272744Skadesai            break;
170272744Skadesai        case ALIAS_TCP_STATE_CONNECTED:
171272744Skadesai            if (tc->th_flags & (TH_FIN | TH_RST))
172272744Skadesai                SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
173272744Skadesai            break;
174265555Sambrisko    }
175265555Sambrisko}
176272744Skadesai
177265555Sambrisko
178265555Sambrisko
179265555Sambrisko
180265555Sambrisko
181272744Skadesai/* Protocol Specific Packet Aliasing Routines
182265555Sambrisko
183265555Sambrisko    IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
184265555Sambrisko    IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
185265555Sambrisko    ProtoAliasIn(), ProtoAliasOut()
186265555Sambrisko    UdpAliasIn(), UdpAliasOut()
187265555Sambrisko    TcpAliasIn(), TcpAliasOut()
188265555Sambrisko
189272744SkadesaiThese routines handle protocol specific details of packet aliasing.
190265555SambriskoOne may observe a certain amount of repetitive arithmetic in these
191265555Sambriskofunctions, the purpose of which is to compute a revised checksum
192272744Skadesaiwithout actually summing over the entire data packet, which could be
193272744Skadesaiunnecessarily time consuming.
194265555Sambrisko
195272744SkadesaiThe purpose of the packet aliasing routines is to replace the source
196265555Sambriskoaddress of the outgoing packet and then correctly put it back for
197265555Sambriskoany incoming packets.  For TCP and UDP, ports are also re-mapped.
198272744Skadesai
199272744SkadesaiFor ICMP echo/timestamp requests and replies, the following scheme
200265555Sambriskois used: the ID number is replaced by an alias for the outgoing
201272744Skadesaipacket.
202265555Sambrisko
203265555SambriskoICMP error messages are handled by looking at the IP fragment
204272744Skadesaiin the data section of the message.
205272744Skadesai
206265555SambriskoFor TCP and UDP protocols, a port number is chosen for an outgoing
207272744Skadesaipacket, and then incoming packets are identified by IP address and
208265555Sambriskoport numbers.  For TCP packets, there is additional logic in the event
209265555Sambriskothat sequence and ACK numbers have been altered (as in the case for
210272744SkadesaiFTP data port commands).
211272744Skadesai
212265555SambriskoThe port numbers used by the packet aliasing module are not true
213272744Skadesaiports in the Unix sense.  No sockets are actually bound to ports.
214265555SambriskoThey are more correctly thought of as placeholders.
215265555Sambrisko
216272744SkadesaiAll packets go through the aliasing mechanism, whether they come from
217272744Skadesaithe gateway machine or other machines on a local area network.
218265555Sambrisko*/
219272744Skadesai
220265555Sambrisko
221265555Sambrisko/* Local prototypes */
222272744Skadesaistatic int IcmpAliasIn1(struct ip *);
223272744Skadesaistatic int IcmpAliasIn2(struct ip *);
224265555Sambriskostatic int IcmpAliasIn (struct ip *);
225272744Skadesai
226265555Sambriskostatic int IcmpAliasOut1(struct ip *);
227265555Sambriskostatic int IcmpAliasOut2(struct ip *);
228272744Skadesaistatic int IcmpAliasOut (struct ip *);
229272744Skadesai
230265555Sambriskostatic int ProtoAliasIn(struct ip *);
231272744Skadesaistatic int ProtoAliasOut(struct ip *);
232265555Sambrisko
233265555Sambriskostatic int UdpAliasOut(struct ip *);
234272744Skadesaistatic int UdpAliasIn (struct ip *);
235272744Skadesai
236265555Sambriskostatic int TcpAliasOut(struct ip *, int);
237272744Skadesaistatic int TcpAliasIn (struct ip *);
238265555Sambrisko
239265555Sambrisko
240272744Skadesaistatic int
241272744SkadesaiIcmpAliasIn1(struct ip *pip)
242265555Sambrisko{
243272744Skadesai/*
244265555Sambrisko    De-alias incoming echo and timestamp replies.
245265555Sambrisko    Alias incoming echo and timestamp requests.
246272744Skadesai*/
247272744Skadesai    struct alias_link *link;
248265555Sambrisko    struct icmp *ic;
249272744Skadesai
250272744Skadesai    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
251265555Sambrisko
252272744Skadesai/* Get source address from ICMP data field and restore original data */
253265555Sambrisko    link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
254272744Skadesai    if (link != NULL)
255272744Skadesai    {
256272744Skadesai        u_short original_id;
257272744Skadesai        int accumulate;
258272744Skadesai
259265555Sambrisko        original_id = GetOriginalPort(link);
260272744Skadesai
261272744Skadesai/* Adjust ICMP checksum */
262272744Skadesai        accumulate  = ic->icmp_id;
263272744Skadesai        accumulate -= original_id;
264265555Sambrisko        ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
265272744Skadesai
266265555Sambrisko/* Put original sequence number back in */
267265555Sambrisko        ic->icmp_id = original_id;
268272735Skadesai
269272735Skadesai/* Put original address back into IP header */
270272735Skadesai        {
271272744Skadesai            struct in_addr original_address;
272272744Skadesai
273272735Skadesai            original_address = GetOriginalAddress(link);
274272744Skadesai            DifferentialChecksum(&pip->ip_sum,
275272744Skadesai                                 (u_short *) &original_address,
276272735Skadesai                                 (u_short *) &pip->ip_dst,
277272735Skadesai                                 2);
278272735Skadesai            pip->ip_dst = original_address;
279272735Skadesai        }
280272735Skadesai
281272744Skadesai        return(PKT_ALIAS_OK);
282272735Skadesai    }
283272744Skadesai    return(PKT_ALIAS_IGNORED);
284272744Skadesai}
285272744Skadesai
286272744Skadesaistatic int
287272744SkadesaiIcmpAliasIn2(struct ip *pip)
288272735Skadesai{
289272744Skadesai/*
290272735Skadesai    Alias incoming ICMP error messages containing
291272744Skadesai    IP header and first 64 bits of datagram.
292272735Skadesai*/
293272735Skadesai    struct ip *ip;
294272735Skadesai    struct icmp *ic, *ic2;
295272735Skadesai    struct udphdr *ud;
296272735Skadesai    struct tcphdr *tc;
297272744Skadesai    struct alias_link *link;
298272744Skadesai
299272744Skadesai    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
300272744Skadesai    ip = &ic->icmp_ip;
301272735Skadesai
302272735Skadesai    ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
303272735Skadesai    tc = (struct tcphdr *) ud;
304272735Skadesai    ic2 = (struct icmp *) ud;
305272735Skadesai
306272735Skadesai    if (ip->ip_p == IPPROTO_UDP)
307272735Skadesai        link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
308272744Skadesai                            ud->uh_dport, ud->uh_sport,
309272735Skadesai                            IPPROTO_UDP, 0);
310272744Skadesai    else if (ip->ip_p == IPPROTO_TCP)
311272735Skadesai        link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
312272744Skadesai                            tc->th_dport, tc->th_sport,
313272735Skadesai                            IPPROTO_TCP, 0);
314272735Skadesai    else if (ip->ip_p == IPPROTO_ICMP) {
315272744Skadesai        if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
316272735Skadesai            link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
317272744Skadesai        else
318272735Skadesai            link = NULL;
319272735Skadesai    } else
320272744Skadesai        link = NULL;
321272744Skadesai
322272744Skadesai    if (link != NULL)
323272744Skadesai    {
324272744Skadesai        if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
325272744Skadesai        {
326272744Skadesai            u_short *sptr;
327272744Skadesai            int accumulate;
328272744Skadesai            struct in_addr original_address;
329272744Skadesai            u_short original_port;
330272744Skadesai
331272744Skadesai            original_address = GetOriginalAddress(link);
332272744Skadesai            original_port = GetOriginalPort(link);
333272735Skadesai
334272735Skadesai/* Adjust ICMP checksum */
335272735Skadesai            sptr = (u_short *) &(ip->ip_src);
336272735Skadesai            accumulate  = *sptr++;
337272744Skadesai            accumulate += *sptr;
338272735Skadesai            sptr = (u_short *) &original_address;
339272744Skadesai            accumulate -= *sptr++;
340272744Skadesai            accumulate -= *sptr;
341272735Skadesai            accumulate += ud->uh_sport;
342272735Skadesai            accumulate -= original_port;
343272735Skadesai            ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
344272744Skadesai
345272744Skadesai/* Un-alias address in IP header */
346272744Skadesai            DifferentialChecksum(&pip->ip_sum,
347265555Sambrisko                                 (u_short *) &original_address,
348272744Skadesai                                 (u_short *) &pip->ip_dst,
349265555Sambrisko                                 2);
350265555Sambrisko            pip->ip_dst = original_address;
351272744Skadesai
352272744Skadesai/* Un-alias address and port number of original IP packet
353265555Sambriskofragment contained in ICMP data section */
354265555Sambrisko            ip->ip_src = original_address;
355265555Sambrisko            ud->uh_sport = original_port;
356265555Sambrisko        }
357272744Skadesai        else if (ip->ip_p == IPPROTO_ICMP)
358272735Skadesai        {
359272744Skadesai            u_short *sptr;
360272744Skadesai            int accumulate;
361272735Skadesai            struct in_addr original_address;
362272744Skadesai            u_short original_id;
363272735Skadesai
364272744Skadesai            original_address = GetOriginalAddress(link);
365272744Skadesai            original_id = GetOriginalPort(link);
366272744Skadesai
367265555Sambrisko/* Adjust ICMP checksum */
368272744Skadesai            sptr = (u_short *) &(ip->ip_src);
369272744Skadesai            accumulate  = *sptr++;
370272744Skadesai            accumulate += *sptr;
371272744Skadesai            sptr = (u_short *) &original_address;
372272744Skadesai            accumulate -= *sptr++;
373272744Skadesai            accumulate -= *sptr;
374265555Sambrisko            accumulate += ic2->icmp_id;
375272744Skadesai            accumulate -= original_id;
376272744Skadesai            ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
377272744Skadesai
378272744Skadesai/* Un-alias address in IP header */
379272744Skadesai            DifferentialChecksum(&pip->ip_sum,
380265555Sambrisko                                 (u_short *) &original_address,
381272744Skadesai                                 (u_short *) &pip->ip_dst,
382272744Skadesai                                 2);
383272744Skadesai            pip->ip_dst = original_address;
384282527Skadesai
385265555Sambrisko/* Un-alias address of original IP packet and sequence number of
386272744Skadesai   embedded ICMP datagram */
387265555Sambrisko            ip->ip_src = original_address;
388265555Sambrisko            ic2->icmp_id = original_id;
389265555Sambrisko        }
390272744Skadesai        return(PKT_ALIAS_OK);
391272744Skadesai    }
392272744Skadesai    return(PKT_ALIAS_IGNORED);
393272744Skadesai}
394272744Skadesai
395272744Skadesai
396272744Skadesaistatic int
397272744SkadesaiIcmpAliasIn(struct ip *pip)
398265555Sambrisko{
399272744Skadesai    int iresult;
400272744Skadesai    struct icmp *ic;
401265555Sambrisko
402265555Sambrisko/* Return if proxy-only mode is enabled */
403272744Skadesai    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
404272744Skadesai        return PKT_ALIAS_OK;
405272744Skadesai
406272744Skadesai    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
407272744Skadesai
408272744Skadesai    iresult = PKT_ALIAS_IGNORED;
409272744Skadesai    switch (ic->icmp_type)
410265555Sambrisko    {
411272744Skadesai        case ICMP_ECHOREPLY:
412272744Skadesai        case ICMP_TSTAMPREPLY:
413272744Skadesai            if (ic->icmp_code == 0)
414272744Skadesai            {
415272744Skadesai                iresult = IcmpAliasIn1(pip);
416272744Skadesai            }
417272744Skadesai            break;
418272744Skadesai        case ICMP_UNREACH:
419272744Skadesai        case ICMP_SOURCEQUENCH:
420272744Skadesai        case ICMP_TIMXCEED:
421272744Skadesai        case ICMP_PARAMPROB:
422272744Skadesai            iresult = IcmpAliasIn2(pip);
423272744Skadesai            break;
424272744Skadesai        case ICMP_ECHO:
425272744Skadesai        case ICMP_TSTAMP:
426265555Sambrisko            iresult = IcmpAliasIn1(pip);
427272744Skadesai            break;
428272744Skadesai    }
429272744Skadesai    return(iresult);
430272744Skadesai}
431272744Skadesai
432272744Skadesai
433272744Skadesaistatic int
434272744SkadesaiIcmpAliasOut1(struct ip *pip)
435272744Skadesai{
436272744Skadesai/*
437272744Skadesai    Alias outgoing echo and timestamp requests.
438272744Skadesai    De-alias outgoing echo and timestamp replies.
439272744Skadesai*/
440272744Skadesai    struct alias_link *link;
441272744Skadesai    struct icmp *ic;
442272744Skadesai
443272744Skadesai    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
444272744Skadesai
445272744Skadesai/* Save overwritten data for when echo packet returns */
446272744Skadesai    link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
447272744Skadesai    if (link != NULL)
448272744Skadesai    {
449272744Skadesai        u_short alias_id;
450272744Skadesai        int accumulate;
451272744Skadesai
452272744Skadesai        alias_id = GetAliasPort(link);
453272744Skadesai
454272744Skadesai/* Since data field is being modified, adjust ICMP checksum */
455272744Skadesai        accumulate  = ic->icmp_id;
456272744Skadesai        accumulate -= alias_id;
457272744Skadesai        ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
458272744Skadesai
459272744Skadesai/* Alias sequence number */
460272744Skadesai        ic->icmp_id = alias_id;
461265555Sambrisko
462272744Skadesai/* Change source address */
463265555Sambrisko        {
464265555Sambrisko            struct in_addr alias_address;
465272744Skadesai
466272744Skadesai            alias_address = GetAliasAddress(link);
467272744Skadesai            DifferentialChecksum(&pip->ip_sum,
468272744Skadesai                                 (u_short *) &alias_address,
469272744Skadesai                                 (u_short *) &pip->ip_src,
470272744Skadesai                                 2);
471272744Skadesai            pip->ip_src = alias_address;
472272744Skadesai        }
473272744Skadesai
474272744Skadesai        return(PKT_ALIAS_OK);
475272744Skadesai    }
476272744Skadesai    return(PKT_ALIAS_IGNORED);
477265555Sambrisko}
478272744Skadesai
479272744Skadesai
480272744Skadesaistatic int
481265555SambriskoIcmpAliasOut2(struct ip *pip)
482272744Skadesai{
483272744Skadesai/*
484272744Skadesai    Alias outgoing ICMP error messages containing
485272744Skadesai    IP header and first 64 bits of datagram.
486272744Skadesai*/
487265555Sambrisko    struct ip *ip;
488272744Skadesai    struct icmp *ic, *ic2;
489272744Skadesai    struct udphdr *ud;
490265555Sambrisko    struct tcphdr *tc;
491272744Skadesai    struct alias_link *link;
492272744Skadesai
493272744Skadesai    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
494272744Skadesai    ip = &ic->icmp_ip;
495265555Sambrisko
496272744Skadesai    ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
497272744Skadesai    tc = (struct tcphdr *) ud;
498272744Skadesai    ic2 = (struct icmp *) ud;
499272744Skadesai
500272744Skadesai    if (ip->ip_p == IPPROTO_UDP)
501272744Skadesai        link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
502272744Skadesai                            ud->uh_dport, ud->uh_sport,
503272744Skadesai                            IPPROTO_UDP, 0);
504272744Skadesai    else if (ip->ip_p == IPPROTO_TCP)
505272744Skadesai        link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
506272744Skadesai                            tc->th_dport, tc->th_sport,
507272744Skadesai                            IPPROTO_TCP, 0);
508272744Skadesai    else if (ip->ip_p == IPPROTO_ICMP) {
509272744Skadesai        if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
510272744Skadesai            link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
511272744Skadesai        else
512272744Skadesai            link = NULL;
513272744Skadesai    } else
514272744Skadesai        link = NULL;
515272744Skadesai
516272744Skadesai    if (link != NULL)
517272744Skadesai    {
518272744Skadesai        if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
519272744Skadesai        {
520272744Skadesai            u_short *sptr;
521272744Skadesai            int accumulate;
522272744Skadesai            struct in_addr alias_address;
523272744Skadesai            u_short alias_port;
524272744Skadesai
525265555Sambrisko            alias_address = GetAliasAddress(link);
526265555Sambrisko            alias_port = GetAliasPort(link);
527265555Sambrisko
528272744Skadesai/* Adjust ICMP checksum */
529272744Skadesai            sptr = (u_short *) &(ip->ip_dst);
530272744Skadesai            accumulate  = *sptr++;
531272744Skadesai            accumulate += *sptr;
532272744Skadesai            sptr = (u_short *) &alias_address;
533272744Skadesai            accumulate -= *sptr++;
534272744Skadesai            accumulate -= *sptr;
535272744Skadesai            accumulate += ud->uh_dport;
536272744Skadesai            accumulate -= alias_port;
537272744Skadesai            ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
538265555Sambrisko
539272744Skadesai/*
540272744Skadesai * Alias address in IP header if it comes from the host
541272744Skadesai * the original TCP/UDP packet was destined for.
542265555Sambrisko */
543272744Skadesai	    if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
544272744Skadesai		DifferentialChecksum(&pip->ip_sum,
545272744Skadesai				     (u_short *) &alias_address,
546272744Skadesai				     (u_short *) &pip->ip_src,
547272744Skadesai				     2);
548265555Sambrisko		pip->ip_src = alias_address;
549272744Skadesai	    }
550272744Skadesai
551265555Sambrisko/* Alias address and port number of original IP packet
552272744Skadesaifragment contained in ICMP data section */
553272744Skadesai            ip->ip_dst = alias_address;
554272744Skadesai            ud->uh_dport = alias_port;
555272744Skadesai        }
556265555Sambrisko        else if (ip->ip_p == IPPROTO_ICMP)
557272744Skadesai        {
558272744Skadesai            u_short *sptr;
559272744Skadesai            int accumulate;
560272744Skadesai            struct in_addr alias_address;
561272744Skadesai            u_short alias_id;
562272744Skadesai
563272744Skadesai            alias_address = GetAliasAddress(link);
564272744Skadesai            alias_id = GetAliasPort(link);
565272744Skadesai
566272744Skadesai/* Adjust ICMP checksum */
567272744Skadesai            sptr = (u_short *) &(ip->ip_dst);
568272744Skadesai            accumulate  = *sptr++;
569272744Skadesai            accumulate += *sptr;
570272744Skadesai            sptr = (u_short *) &alias_address;
571282531Skadesai            accumulate -= *sptr++;
572272744Skadesai            accumulate -= *sptr;
573272744Skadesai            accumulate += ic2->icmp_id;
574272744Skadesai            accumulate -= alias_id;
575272744Skadesai            ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
576282531Skadesai
577272744Skadesai/*
578272744Skadesai * Alias address in IP header if it comes from the host
579272744Skadesai * the original ICMP message was destined for.
580272744Skadesai */
581272744Skadesai	    if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
582265555Sambrisko		DifferentialChecksum(&pip->ip_sum,
583265555Sambrisko				     (u_short *) &alias_address,
584265555Sambrisko				     (u_short *) &pip->ip_src,
585265555Sambrisko				     2);
586272744Skadesai		pip->ip_src = alias_address;
587272744Skadesai	    }
588272744Skadesai
589272744Skadesai/* Alias address of original IP packet and sequence number of
590272744Skadesai   embedded ICMP datagram */
591272744Skadesai            ip->ip_dst = alias_address;
592272744Skadesai            ic2->icmp_id = alias_id;
593272744Skadesai        }
594272744Skadesai        return(PKT_ALIAS_OK);
595272744Skadesai    }
596265555Sambrisko    return(PKT_ALIAS_IGNORED);
597272744Skadesai}
598272744Skadesai
599272744Skadesai
600265555Sambriskostatic int
601272744SkadesaiIcmpAliasOut(struct ip *pip)
602272744Skadesai{
603272744Skadesai    int iresult;
604272744Skadesai    struct icmp *ic;
605272744Skadesai
606272744Skadesai/* Return if proxy-only mode is enabled */
607265555Sambrisko    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
608272744Skadesai        return PKT_ALIAS_OK;
609272744Skadesai
610265555Sambrisko    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
611272744Skadesai
612272744Skadesai    iresult = PKT_ALIAS_IGNORED;
613272744Skadesai    switch (ic->icmp_type)
614272744Skadesai    {
615265555Sambrisko        case ICMP_ECHO:
616272744Skadesai        case ICMP_TSTAMP:
617272744Skadesai            if (ic->icmp_code == 0)
618272744Skadesai            {
619272744Skadesai                iresult = IcmpAliasOut1(pip);
620272744Skadesai            }
621272744Skadesai            break;
622272744Skadesai        case ICMP_UNREACH:
623272744Skadesai        case ICMP_SOURCEQUENCH:
624272744Skadesai        case ICMP_TIMXCEED:
625272744Skadesai        case ICMP_PARAMPROB:
626272744Skadesai            iresult = IcmpAliasOut2(pip);
627272744Skadesai            break;
628272744Skadesai        case ICMP_ECHOREPLY:
629272744Skadesai        case ICMP_TSTAMPREPLY:
630272744Skadesai            iresult = IcmpAliasOut1(pip);
631272744Skadesai    }
632272744Skadesai    return(iresult);
633272744Skadesai}
634272744Skadesai
635272744Skadesai
636282531Skadesai
637272744Skadesaistatic int
638272744SkadesaiProtoAliasIn(struct ip *pip)
639265555Sambrisko{
640265555Sambrisko/*
641265555Sambrisko  Handle incoming IP packets. The
642272744Skadesai  only thing which is done in this case is to alias
643272744Skadesai  the dest IP address of the packet to our inside
644272744Skadesai  machine.
645272744Skadesai*/
646272744Skadesai    struct alias_link *link;
647272744Skadesai
648272744Skadesai/* Return if proxy-only mode is enabled */
649272744Skadesai    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
650272744Skadesai        return PKT_ALIAS_OK;
651272744Skadesai
652272744Skadesai    link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
653272744Skadesai    if (link != NULL)
654265555Sambrisko    {
655272744Skadesai        struct in_addr original_address;
656272744Skadesai
657272744Skadesai        original_address = GetOriginalAddress(link);
658265555Sambrisko
659272744Skadesai/* Restore original IP address */
660272744Skadesai        DifferentialChecksum(&pip->ip_sum,
661272744Skadesai                             (u_short *) &original_address,
662272744Skadesai                             (u_short *) &pip->ip_dst,
663265555Sambrisko                             2);
664272744Skadesai        pip->ip_dst = original_address;
665272744Skadesai
666265555Sambrisko	return(PKT_ALIAS_OK);
667272744Skadesai    }
668272744Skadesai    return(PKT_ALIAS_IGNORED);
669272744Skadesai}
670272744Skadesai
671265555Sambrisko
672272744Skadesaistatic int
673272744SkadesaiProtoAliasOut(struct ip *pip)
674272744Skadesai{
675265555Sambrisko/*
676272744Skadesai  Handle outgoing IP packets. The
677272744Skadesai  only thing which is done in this case is to alias
678272744Skadesai  the source IP address of the packet.
679272744Skadesai*/
680272744Skadesai    struct alias_link *link;
681272744Skadesai
682272744Skadesai/* Return if proxy-only mode is enabled */
683272744Skadesai    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
684282531Skadesai        return PKT_ALIAS_OK;
685272744Skadesai
686272744Skadesai    link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
687272744Skadesai    if (link != NULL)
688272744Skadesai    {
689265555Sambrisko        struct in_addr alias_address;
690282531Skadesai
691272744Skadesai        alias_address = GetAliasAddress(link);
692265555Sambrisko
693272744Skadesai/* Change source address */
694265555Sambrisko        DifferentialChecksum(&pip->ip_sum,
695265555Sambrisko                             (u_short *) &alias_address,
696265555Sambrisko                             (u_short *) &pip->ip_src,
697265555Sambrisko                             2);
698272744Skadesai        pip->ip_src = alias_address;
699272744Skadesai
700272744Skadesai        return(PKT_ALIAS_OK);
701265555Sambrisko    }
702272744Skadesai    return(PKT_ALIAS_IGNORED);
703265555Sambrisko}
704272744Skadesai
705272744Skadesai
706265555Sambriskostatic int
707272744SkadesaiUdpAliasIn(struct ip *pip)
708272744Skadesai{
709272744Skadesai    struct udphdr *ud;
710272744Skadesai    struct alias_link *link;
711272744Skadesai
712272744Skadesai/* Return if proxy-only mode is enabled */
713272744Skadesai    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
714272744Skadesai        return PKT_ALIAS_OK;
715272744Skadesai
716272744Skadesai    ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
717272744Skadesai
718272744Skadesai    link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
719265555Sambrisko                        ud->uh_sport, ud->uh_dport,
720272744Skadesai                        IPPROTO_UDP, 1);
721265555Sambrisko    if (link != NULL)
722265555Sambrisko    {
723265555Sambrisko        struct in_addr alias_address;
724272744Skadesai        struct in_addr original_address;
725272744Skadesai        u_short alias_port;
726272744Skadesai        int accumulate;
727272744Skadesai        u_short *sptr;
728282527Skadesai	int r = 0;
729282527Skadesai
730282527Skadesai        alias_address = GetAliasAddress(link);
731282527Skadesai        original_address = GetOriginalAddress(link);
732282527Skadesai        alias_port = ud->uh_dport;
733272744Skadesai        ud->uh_dport = GetOriginalPort(link);
734272744Skadesai
735272744Skadesai/* Special processing for IP encoding protocols */
736272744Skadesai	if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
737272744Skadesai	    AliasHandleCUSeeMeIn(pip, original_address);
738272744Skadesai/* If NETBIOS Datagram, It should be alias address in UDP Data, too */
739272744Skadesai	else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
740272744Skadesai	      || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
741265555Sambrisko	    r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
742272744Skadesai	else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
743272744Skadesai	      || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
744272744Skadesai	    r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
745272744Skadesai				    &original_address, &ud->uh_dport);
746272744Skadesai
747272744Skadesai/* If UDP checksum is not zero, then adjust since destination port */
748272744Skadesai/* is being unaliased and destination address is being altered.    */
749272744Skadesai        if (ud->uh_sum != 0)
750272744Skadesai        {
751265555Sambrisko            accumulate  = alias_port;
752299670Skadesai            accumulate -= ud->uh_dport;
753299670Skadesai            sptr = (u_short *) &alias_address;
754299670Skadesai            accumulate += *sptr++;
755301203Skadesai            accumulate += *sptr;
756301203Skadesai            sptr = (u_short *) &original_address;
757301203Skadesai            accumulate -= *sptr++;
758272744Skadesai            accumulate -= *sptr;
759265555Sambrisko            ADJUST_CHECKSUM(accumulate, ud->uh_sum)
760272744Skadesai        }
761272744Skadesai
762272744Skadesai/* Restore original IP address */
763265555Sambrisko        DifferentialChecksum(&pip->ip_sum,
764265555Sambrisko                             (u_short *) &original_address,
765272744Skadesai                             (u_short *) &pip->ip_dst,
766272744Skadesai                             2);
767272744Skadesai        pip->ip_dst = original_address;
768272744Skadesai
769272744Skadesai	/*
770272744Skadesai	 * If we cannot figure out the packet, ignore it.
771272744Skadesai	 */
772272744Skadesai	if (r < 0)
773272744Skadesai	    return(PKT_ALIAS_IGNORED);
774272744Skadesai	else
775272744Skadesai	    return(PKT_ALIAS_OK);
776265555Sambrisko    }
777265555Sambrisko    return(PKT_ALIAS_IGNORED);
778272744Skadesai}
779272744Skadesai
780265555Sambriskostatic int
781272744SkadesaiUdpAliasOut(struct ip *pip)
782272744Skadesai{
783272744Skadesai    struct udphdr *ud;
784272744Skadesai    struct alias_link *link;
785272744Skadesai
786272744Skadesai/* Return if proxy-only mode is enabled */
787272744Skadesai    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
788272744Skadesai        return PKT_ALIAS_OK;
789272744Skadesai
790272744Skadesai    ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
791272744Skadesai
792272744Skadesai    link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
793272744Skadesai                         ud->uh_sport, ud->uh_dport,
794272744Skadesai                         IPPROTO_UDP, 1);
795272744Skadesai    if (link != NULL)
796272744Skadesai    {
797282527Skadesai        u_short alias_port;
798272744Skadesai        struct in_addr alias_address;
799265555Sambrisko
800265555Sambrisko        alias_address = GetAliasAddress(link);
801272744Skadesai        alias_port = GetAliasPort(link);
802272744Skadesai
803272744Skadesai/* Special processing for IP encoding protocols */
804272744Skadesai	if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
805272744Skadesai	    AliasHandleCUSeeMeOut(pip, link);
806272744Skadesai/* If NETBIOS Datagram, It should be alias address in UDP Data, too */
807272744Skadesai	else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
808272744Skadesai	      || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
809265555Sambrisko	    AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
810272744Skadesai	else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
811265555Sambrisko	      || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
812272744Skadesai	    AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
813272744Skadesai				&alias_address, &alias_port);
814272744Skadesai
815272744Skadesai/* If UDP checksum is not zero, adjust since source port is */
816272744Skadesai/* being aliased and source address is being altered        */
817272744Skadesai        if (ud->uh_sum != 0)
818272744Skadesai        {
819272744Skadesai            int accumulate;
820272744Skadesai            u_short *sptr;
821272744Skadesai
822272744Skadesai            accumulate  = ud->uh_sport;
823265555Sambrisko            accumulate -= alias_port;
824272744Skadesai            sptr = (u_short *) &(pip->ip_src);
825272744Skadesai            accumulate += *sptr++;
826265555Sambrisko            accumulate += *sptr;
827272744Skadesai            sptr = (u_short *) &alias_address;
828272744Skadesai            accumulate -= *sptr++;
829272744Skadesai            accumulate -= *sptr;
830272744Skadesai            ADJUST_CHECKSUM(accumulate, ud->uh_sum)
831272744Skadesai        }
832265555Sambrisko
833272744Skadesai/* Put alias port in UDP header */
834265555Sambrisko        ud->uh_sport = alias_port;
835272744Skadesai
836272744Skadesai/* Change source address */
837265555Sambrisko        DifferentialChecksum(&pip->ip_sum,
838272744Skadesai                             (u_short *) &alias_address,
839272744Skadesai                             (u_short *) &pip->ip_src,
840272744Skadesai                             2);
841272744Skadesai        pip->ip_src = alias_address;
842272744Skadesai
843272744Skadesai        return(PKT_ALIAS_OK);
844282531Skadesai    }
845272744Skadesai    return(PKT_ALIAS_IGNORED);
846272744Skadesai}
847272744Skadesai
848272744Skadesai
849265555Sambrisko
850272744Skadesaistatic int
851272744SkadesaiTcpAliasIn(struct ip *pip)
852272744Skadesai{
853272744Skadesai    struct tcphdr *tc;
854272744Skadesai    struct alias_link *link;
855272744Skadesai
856272744Skadesai    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
857272744Skadesai
858272744Skadesai    link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
859272744Skadesai                        tc->th_sport, tc->th_dport,
860272744Skadesai                        IPPROTO_TCP,
861272744Skadesai                        !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
862272744Skadesai    if (link != NULL)
863272744Skadesai    {
864272744Skadesai        struct in_addr alias_address;
865272744Skadesai        struct in_addr original_address;
866272744Skadesai        struct in_addr proxy_address;
867272744Skadesai        u_short alias_port;
868272744Skadesai        u_short proxy_port;
869272744Skadesai        int accumulate;
870272744Skadesai        u_short *sptr;
871282531Skadesai
872272744Skadesai/* Special processing for IP encoding protocols */
873272744Skadesai        if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
874272744Skadesai         || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
875272744Skadesai            AliasHandlePptpIn(pip, link);
876272744Skadesai
877282531Skadesai        alias_address = GetAliasAddress(link);
878272744Skadesai        original_address = GetOriginalAddress(link);
879272744Skadesai        proxy_address = GetProxyAddress(link);
880272744Skadesai        alias_port = tc->th_dport;
881272744Skadesai        tc->th_dport = GetOriginalPort(link);
882272744Skadesai        proxy_port = GetProxyPort(link);
883272744Skadesai
884272744Skadesai/* Adjust TCP checksum since destination port is being unaliased */
885272744Skadesai/* and destination port is being altered.                        */
886282531Skadesai        accumulate  = alias_port;
887272744Skadesai        accumulate -= tc->th_dport;
888272744Skadesai        sptr = (u_short *) &alias_address;
889272744Skadesai        accumulate += *sptr++;
890272744Skadesai        accumulate += *sptr;
891282531Skadesai        sptr = (u_short *) &original_address;
892272744Skadesai        accumulate -= *sptr++;
893272744Skadesai        accumulate -= *sptr;
894272744Skadesai
895272744Skadesai/* If this is a proxy, then modify the TCP source port and
896272744Skadesai   checksum accumulation */
897265555Sambrisko        if (proxy_port != 0)
898272744Skadesai        {
899265555Sambrisko            accumulate += tc->th_sport;
900272744Skadesai            tc->th_sport = proxy_port;
901272744Skadesai            accumulate -= tc->th_sport;
902272744Skadesai
903272744Skadesai            sptr = (u_short *) &pip->ip_src;
904272744Skadesai            accumulate += *sptr++;
905272744Skadesai            accumulate += *sptr;
906265555Sambrisko            sptr = (u_short *) &proxy_address;
907272744Skadesai            accumulate -= *sptr++;
908272744Skadesai            accumulate -= *sptr;
909272744Skadesai        }
910272744Skadesai
911272744Skadesai/* See if ACK number needs to be modified */
912272744Skadesai        if (GetAckModified(link) == 1)
913272744Skadesai        {
914272744Skadesai            int delta;
915272744Skadesai
916272744Skadesai            delta = GetDeltaAckIn(pip, link);
917272744Skadesai            if (delta != 0)
918272744Skadesai            {
919265555Sambrisko                sptr = (u_short *) &tc->th_ack;
920272744Skadesai                accumulate += *sptr++;
921272744Skadesai                accumulate += *sptr;
922272744Skadesai                tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
923272744Skadesai                sptr = (u_short *) &tc->th_ack;
924272744Skadesai                accumulate -= *sptr++;
925272744Skadesai                accumulate -= *sptr;
926272744Skadesai            }
927272744Skadesai        }
928272744Skadesai
929272744Skadesai        ADJUST_CHECKSUM(accumulate, tc->th_sum);
930272744Skadesai
931272744Skadesai/* Restore original IP address */
932272744Skadesai        sptr = (u_short *) &pip->ip_dst;
933272744Skadesai        accumulate  = *sptr++;
934272744Skadesai        accumulate += *sptr;
935272744Skadesai        pip->ip_dst = original_address;
936272744Skadesai        sptr = (u_short *) &pip->ip_dst;
937272744Skadesai        accumulate -= *sptr++;
938272744Skadesai        accumulate -= *sptr;
939265555Sambrisko
940272744Skadesai/* If this is a transparent proxy packet, then modify the source
941265555Sambrisko   address */
942272744Skadesai        if (proxy_address.s_addr != 0)
943272744Skadesai        {
944272744Skadesai            sptr = (u_short *) &pip->ip_src;
945272744Skadesai            accumulate += *sptr++;
946272744Skadesai            accumulate += *sptr;
947272744Skadesai            pip->ip_src = proxy_address;
948272744Skadesai            sptr = (u_short *) &pip->ip_src;
949272744Skadesai            accumulate -= *sptr++;
950272744Skadesai            accumulate -= *sptr;
951272744Skadesai        }
952272744Skadesai
953272744Skadesai        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
954272744Skadesai
955265555Sambrisko/* Monitor TCP connection state */
956272744Skadesai        TcpMonitorIn(pip, link);
957272744Skadesai
958272744Skadesai        return(PKT_ALIAS_OK);
959272744Skadesai    }
960265555Sambrisko    return(PKT_ALIAS_IGNORED);
961272744Skadesai}
962272744Skadesai
963272744Skadesaistatic int
964272744SkadesaiTcpAliasOut(struct ip *pip, int maxpacketsize)
965272744Skadesai{
966272744Skadesai    int proxy_type;
967272744Skadesai    u_short dest_port;
968299670Skadesai    u_short proxy_server_port;
969299670Skadesai    struct in_addr dest_address;
970299670Skadesai    struct in_addr proxy_server_address;
971301203Skadesai    struct tcphdr *tc;
972301203Skadesai    struct alias_link *link;
973301203Skadesai
974272744Skadesai    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
975272744Skadesai
976272744Skadesai    proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
977272744Skadesai
978272744Skadesai    if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
979272744Skadesai        return PKT_ALIAS_OK;
980272744Skadesai
981265555Sambrisko/* If this is a transparent proxy, save original destination,
982272744Skadesai   then alter the destination and adjust checksums */
983272744Skadesai    dest_port = tc->th_dport;
984272744Skadesai    dest_address = pip->ip_dst;
985272744Skadesai    if (proxy_type != 0)
986272744Skadesai    {
987272744Skadesai        int accumulate;
988272744Skadesai        u_short *sptr;
989272744Skadesai
990272744Skadesai        accumulate = tc->th_dport;
991272744Skadesai        tc->th_dport = proxy_server_port;
992272744Skadesai        accumulate -= tc->th_dport;
993272744Skadesai
994272744Skadesai        sptr = (u_short *) &(pip->ip_dst);
995272744Skadesai        accumulate += *sptr++;
996272744Skadesai        accumulate += *sptr;
997272744Skadesai        sptr = (u_short *) &proxy_server_address;
998272744Skadesai        accumulate -= *sptr++;
999272744Skadesai        accumulate -= *sptr;
1000272744Skadesai
1001272744Skadesai        ADJUST_CHECKSUM(accumulate, tc->th_sum);
1002272744Skadesai
1003272744Skadesai        sptr = (u_short *) &(pip->ip_dst);
1004272744Skadesai        accumulate  = *sptr++;
1005272744Skadesai        accumulate += *sptr;
1006272744Skadesai        pip->ip_dst = proxy_server_address;
1007265555Sambrisko        sptr = (u_short *) &(pip->ip_dst);
1008272744Skadesai        accumulate -= *sptr++;
1009272744Skadesai        accumulate -= *sptr;
1010265555Sambrisko
1011272744Skadesai        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1012265555Sambrisko    }
1013265555Sambrisko
1014265555Sambrisko    link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1015272744Skadesai                         tc->th_sport, tc->th_dport,
1016272744Skadesai                         IPPROTO_TCP, 1);
1017272744Skadesai    if (link !=NULL)
1018272744Skadesai    {
1019272744Skadesai        u_short alias_port;
1020272744Skadesai        struct in_addr alias_address;
1021272744Skadesai        int accumulate;
1022272744Skadesai        u_short *sptr;
1023272744Skadesai
1024272744Skadesai/* Save original destination address, if this is a proxy packet.
1025265555Sambrisko   Also modify packet to include destination encoding. */
1026272744Skadesai        if (proxy_type != 0)
1027272744Skadesai        {
1028272744Skadesai            SetProxyPort(link, dest_port);
1029272744Skadesai            SetProxyAddress(link, dest_address);
1030272744Skadesai            ProxyModify(link, pip, maxpacketsize, proxy_type);
1031272744Skadesai        }
1032272744Skadesai
1033272744Skadesai/* Get alias address and port */
1034272735Skadesai        alias_port = GetAliasPort(link);
1035272744Skadesai        alias_address = GetAliasAddress(link);
1036272744Skadesai
1037272744Skadesai/* Monitor TCP connection state */
1038272744Skadesai        TcpMonitorOut(pip, link);
1039272744Skadesai
1040272744Skadesai/* Special processing for IP encoding protocols */
1041272744Skadesai        if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1042272744Skadesai         || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1043272744Skadesai            AliasHandleFtpOut(pip, link, maxpacketsize);
1044272744Skadesai        else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1045272744Skadesai         || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1046272744Skadesai            AliasHandleIrcOut(pip, link, maxpacketsize);
1047272744Skadesai        else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1048272744Skadesai         || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1049265555Sambrisko         || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1050272744Skadesai         || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1051265555Sambrisko            AliasHandleRtspOut(pip, link, maxpacketsize);
1052272744Skadesai        else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1053272744Skadesai         || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1054272744Skadesai            AliasHandlePptpOut(pip, link);
1055272744Skadesai
1056272744Skadesai/* Adjust TCP checksum since source port is being aliased */
1057272744Skadesai/* and source address is being altered                    */
1058272744Skadesai        accumulate  = tc->th_sport;
1059265555Sambrisko        tc->th_sport = alias_port;
1060282531Skadesai        accumulate -= tc->th_sport;
1061272744Skadesai
1062265555Sambrisko        sptr = (u_short *) &(pip->ip_src);
1063272744Skadesai        accumulate += *sptr++;
1064272744Skadesai        accumulate += *sptr;
1065265555Sambrisko        sptr = (u_short *) &alias_address;
1066272744Skadesai        accumulate -= *sptr++;
1067272744Skadesai        accumulate -= *sptr;
1068272744Skadesai
1069265555Sambrisko/* Modify sequence number if necessary */
1070272744Skadesai        if (GetAckModified(link) == 1)
1071272744Skadesai        {
1072272744Skadesai            int delta;
1073272744Skadesai
1074265555Sambrisko            delta = GetDeltaSeqOut(pip, link);
1075272744Skadesai            if (delta != 0)
1076272744Skadesai            {
1077265555Sambrisko                sptr = (u_short *) &tc->th_seq;
1078272744Skadesai                accumulate += *sptr++;
1079272744Skadesai                accumulate += *sptr;
1080265555Sambrisko                tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1081272744Skadesai                sptr = (u_short *) &tc->th_seq;
1082272744Skadesai                accumulate -= *sptr++;
1083272744Skadesai                accumulate -= *sptr;
1084272744Skadesai            }
1085272744Skadesai        }
1086272744Skadesai
1087272744Skadesai        ADJUST_CHECKSUM(accumulate, tc->th_sum)
1088265555Sambrisko
1089272744Skadesai/* Change source address */
1090272744Skadesai        sptr = (u_short *) &(pip->ip_src);
1091272744Skadesai        accumulate  = *sptr++;
1092272744Skadesai        accumulate += *sptr;
1093272744Skadesai        pip->ip_src = alias_address;
1094272744Skadesai        sptr = (u_short *) &(pip->ip_src);
1095272744Skadesai        accumulate -= *sptr++;
1096272744Skadesai        accumulate -= *sptr;
1097272744Skadesai
1098272744Skadesai        ADJUST_CHECKSUM(accumulate, pip->ip_sum)
1099272744Skadesai
1100272744Skadesai        return(PKT_ALIAS_OK);
1101272744Skadesai    }
1102272744Skadesai    return(PKT_ALIAS_IGNORED);
1103272744Skadesai}
1104272744Skadesai
1105272744Skadesai
1106272744Skadesai
1107272744Skadesai
1108265555Sambrisko/* Fragment Handling
1109272744Skadesai
1110265555Sambrisko    FragmentIn()
1111265555Sambrisko    FragmentOut()
1112265555Sambrisko
1113272744SkadesaiThe packet aliasing module has a limited ability for handling IP
1114272744Skadesaifragments.  If the ICMP, TCP or UDP header is in the first fragment
1115282527Skadesaireceived, then the ID number of the IP packet is saved, and other
1116282527Skadesaifragments are identified according to their ID number and IP address
1117282527Skadesaithey were sent from.  Pointers to unresolved fragments can also be
1118282527Skadesaisaved and recalled when a header fragment is seen.
1119265555Sambrisko*/
1120272744Skadesai
1121272744Skadesai/* Local prototypes */
1122265555Sambriskostatic int FragmentIn(struct ip *);
1123282533Skadesaistatic int FragmentOut(struct ip *);
1124282527Skadesai
1125282533Skadesai
1126265555Sambriskostatic int
1127272744SkadesaiFragmentIn(struct ip *pip)
1128272744Skadesai{
1129272744Skadesai    struct alias_link *link;
1130265555Sambrisko
1131282533Skadesai    link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1132282533Skadesai    if (link != NULL)
1133282527Skadesai    {
1134282527Skadesai        struct in_addr original_address;
1135282527Skadesai
1136282527Skadesai        GetFragmentAddr(link, &original_address);
1137272744Skadesai        DifferentialChecksum(&pip->ip_sum,
1138272744Skadesai                             (u_short *) &original_address,
1139272744Skadesai                             (u_short *) &pip->ip_dst,
1140282527Skadesai                             2);
1141282527Skadesai        pip->ip_dst = original_address;
1142282533Skadesai
1143272744Skadesai        return(PKT_ALIAS_OK);
1144282527Skadesai    }
1145282527Skadesai    return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1146282527Skadesai}
1147272744Skadesai
1148265555Sambrisko
1149265555Sambriskostatic int
1150265555SambriskoFragmentOut(struct ip *pip)
1151272744Skadesai{
1152272744Skadesai    struct in_addr alias_address;
1153272744Skadesai
1154272744Skadesai    alias_address = FindAliasAddress(pip->ip_src);
1155272744Skadesai    DifferentialChecksum(&pip->ip_sum,
1156272744Skadesai                         (u_short *) &alias_address,
1157272744Skadesai                         (u_short *) &pip->ip_src,
1158272744Skadesai                          2);
1159265555Sambrisko    pip->ip_src = alias_address;
1160265555Sambrisko
1161265555Sambrisko    return(PKT_ALIAS_OK);
1162282533Skadesai}
1163272744Skadesai
1164265555Sambrisko
1165272744Skadesai
1166265555Sambrisko
1167265555Sambrisko
1168272744Skadesai
1169272744Skadesai/* Outside World Access
1170272744Skadesai
1171272744Skadesai        PacketAliasSaveFragment()
1172272744Skadesai        PacketAliasGetFragment()
1173272744Skadesai        PacketAliasFragmentIn()
1174272744Skadesai        PacketAliasIn()
1175265555Sambrisko        PacketAliasOut()
1176272744Skadesai        PacketUnaliasOut()
1177272744Skadesai
1178272744Skadesai(prototypes in alias.h)
1179272744Skadesai*/
1180272744Skadesai
1181272744Skadesai
1182272744Skadesaiint
1183265555SambriskoPacketAliasSaveFragment(char *ptr)
1184272744Skadesai{
1185272744Skadesai    int iresult;
1186272744Skadesai    struct alias_link *link;
1187272744Skadesai    struct ip *pip;
1188272744Skadesai
1189265555Sambrisko    pip = (struct ip *) ptr;
1190272744Skadesai    link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1191272744Skadesai    iresult = PKT_ALIAS_ERROR;
1192272744Skadesai    if (link != NULL)
1193272744Skadesai    {
1194272744Skadesai        SetFragmentPtr(link, ptr);
1195272744Skadesai        iresult = PKT_ALIAS_OK;
1196272744Skadesai    }
1197272744Skadesai    return(iresult);
1198272744Skadesai}
1199265555Sambrisko
1200272744Skadesai
1201272744Skadesaichar *
1202272744SkadesaiPacketAliasGetFragment(char *ptr)
1203272744Skadesai{
1204265555Sambrisko    struct alias_link *link;
1205272744Skadesai    char *fptr;
1206272744Skadesai    struct ip *pip;
1207272744Skadesai
1208272744Skadesai    pip = (struct ip *) ptr;
1209272744Skadesai    link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1210265555Sambrisko    if (link != NULL)
1211272744Skadesai    {
1212272744Skadesai        GetFragmentPtr(link, &fptr);
1213272744Skadesai        SetFragmentPtr(link, NULL);
1214272744Skadesai        SetExpire(link, 0); /* Deletes link */
1215272744Skadesai
1216272744Skadesai        return(fptr);
1217272744Skadesai    }
1218272744Skadesai    else
1219272744Skadesai    {
1220272744Skadesai        return(NULL);
1221272744Skadesai    }
1222272744Skadesai}
1223272744Skadesai
1224272744Skadesai
1225272744Skadesaivoid
1226272744SkadesaiPacketAliasFragmentIn(char *ptr,          /* Points to correctly de-aliased
1227272744Skadesai                                             header fragment */
1228272744Skadesai                      char *ptr_fragment  /* Points to fragment which must
1229272744Skadesai                                             be de-aliased   */
1230272744Skadesai                     )
1231272744Skadesai{
1232272744Skadesai    struct ip *pip;
1233272744Skadesai    struct ip *fpip;
1234272744Skadesai
1235272744Skadesai    pip = (struct ip *) ptr;
1236272744Skadesai    fpip = (struct ip *) ptr_fragment;
1237272744Skadesai
1238272744Skadesai    DifferentialChecksum(&fpip->ip_sum,
1239272744Skadesai                         (u_short *) &pip->ip_dst,
1240272744Skadesai                         (u_short *) &fpip->ip_dst,
1241265555Sambrisko                         2);
1242272744Skadesai    fpip->ip_dst = pip->ip_dst;
1243265555Sambrisko}
1244272744Skadesai
1245272744Skadesai
1246272744Skadesaiint
1247272744SkadesaiPacketAliasIn(char *ptr, int maxpacketsize)
1248265555Sambrisko{
1249272744Skadesai    struct in_addr alias_addr;
1250272744Skadesai    struct ip *pip;
1251272744Skadesai    int iresult;
1252265555Sambrisko
1253272744Skadesai    if (packetAliasMode & PKT_ALIAS_REVERSE) {
1254272744Skadesai        packetAliasMode &= ~PKT_ALIAS_REVERSE;
1255272744Skadesai        iresult = PacketAliasOut(ptr, maxpacketsize);
1256272744Skadesai        packetAliasMode |= PKT_ALIAS_REVERSE;
1257272744Skadesai        return iresult;
1258272744Skadesai    }
1259272744Skadesai
1260272744Skadesai    HouseKeeping();
1261272744Skadesai    ClearCheckNewLink();
1262272744Skadesai    pip = (struct ip *) ptr;
1263272744Skadesai    alias_addr = pip->ip_dst;
1264272744Skadesai
1265272744Skadesai    /* Defense against mangled packets */
1266272744Skadesai    if (ntohs(pip->ip_len) > maxpacketsize
1267272744Skadesai     || (pip->ip_hl<<2) > maxpacketsize)
1268272744Skadesai        return PKT_ALIAS_IGNORED;
1269272744Skadesai
1270272744Skadesai    iresult = PKT_ALIAS_IGNORED;
1271272744Skadesai    if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1272272744Skadesai    {
1273272744Skadesai        switch (pip->ip_p)
1274272744Skadesai        {
1275265555Sambrisko            case IPPROTO_ICMP:
1276272744Skadesai                iresult = IcmpAliasIn(pip);
1277265555Sambrisko                break;
1278272744Skadesai            case IPPROTO_UDP:
1279272744Skadesai                iresult = UdpAliasIn(pip);
1280272744Skadesai                break;
1281272744Skadesai            case IPPROTO_TCP:
1282265555Sambrisko                iresult = TcpAliasIn(pip);
1283272744Skadesai                break;
1284272744Skadesai            case IPPROTO_GRE:
1285272744Skadesai		if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1286272744Skadesai		    AliasHandlePptpGreIn(pip) == 0)
1287272744Skadesai		    iresult = PKT_ALIAS_OK;
1288265555Sambrisko		else
1289272744Skadesai		    iresult = ProtoAliasIn(pip);
1290272744Skadesai		break;
1291272744Skadesai	    default:
1292272744Skadesai		iresult = ProtoAliasIn(pip);
1293272744Skadesai                break;
1294272744Skadesai        }
1295265555Sambrisko
1296272744Skadesai        if (ntohs(pip->ip_off) & IP_MF)
1297272744Skadesai        {
1298272744Skadesai            struct alias_link *link;
1299265555Sambrisko
1300272744Skadesai            link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1301272744Skadesai            if (link != NULL)
1302272744Skadesai            {
1303272744Skadesai                iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1304272744Skadesai                SetFragmentAddr(link, pip->ip_dst);
1305272744Skadesai            }
1306272744Skadesai            else
1307272744Skadesai            {
1308272744Skadesai                iresult = PKT_ALIAS_ERROR;
1309282533Skadesai            }
1310272744Skadesai        }
1311272744Skadesai    }
1312272744Skadesai    else
1313272744Skadesai    {
1314272744Skadesai        iresult = FragmentIn(pip);
1315272744Skadesai    }
1316272744Skadesai
1317272744Skadesai    return(iresult);
1318272744Skadesai}
1319272744Skadesai
1320272744Skadesai
1321272744Skadesai
1322272744Skadesai/* Unregistered address ranges */
1323272744Skadesai
1324272744Skadesai/* 10.0.0.0   ->   10.255.255.255 */
1325272744Skadesai#define UNREG_ADDR_A_LOWER 0x0a000000
1326272744Skadesai#define UNREG_ADDR_A_UPPER 0x0affffff
1327272744Skadesai
1328272744Skadesai/* 172.16.0.0  ->  172.31.255.255 */
1329272744Skadesai#define UNREG_ADDR_B_LOWER 0xac100000
1330272744Skadesai#define UNREG_ADDR_B_UPPER 0xac1fffff
1331272744Skadesai
1332272744Skadesai/* 192.168.0.0 -> 192.168.255.255 */
1333265555Sambrisko#define UNREG_ADDR_C_LOWER 0xc0a80000
1334265555Sambrisko#define UNREG_ADDR_C_UPPER 0xc0a8ffff
1335265555Sambrisko
1336272744Skadesaiint
1337282527SkadesaiPacketAliasOut(char *ptr,           /* valid IP packet */
1338282527Skadesai               int  maxpacketsize   /* How much the packet data may grow
1339282527Skadesai                                       (FTP and IRC inline changes) */
1340282527Skadesai              )
1341282527Skadesai{
1342265555Sambrisko    int iresult;
1343265555Sambrisko    struct in_addr addr_save;
1344265555Sambrisko    struct ip *pip;
1345265555Sambrisko
1346282533Skadesai    if (packetAliasMode & PKT_ALIAS_REVERSE) {
1347282533Skadesai        packetAliasMode &= ~PKT_ALIAS_REVERSE;
1348282533Skadesai        iresult = PacketAliasIn(ptr, maxpacketsize);
1349265555Sambrisko        packetAliasMode |= PKT_ALIAS_REVERSE;
1350282533Skadesai        return iresult;
1351282527Skadesai    }
1352282527Skadesai
1353272744Skadesai    HouseKeeping();
1354282527Skadesai    ClearCheckNewLink();
1355282527Skadesai    pip = (struct ip *) ptr;
1356265555Sambrisko
1357282527Skadesai    /* Defense against mangled packets */
1358282527Skadesai    if (ntohs(pip->ip_len) > maxpacketsize
1359282527Skadesai     || (pip->ip_hl<<2) > maxpacketsize)
1360282527Skadesai        return PKT_ALIAS_IGNORED;
1361282533Skadesai
1362282527Skadesai    addr_save = GetDefaultAliasAddress();
1363282527Skadesai    if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1364282527Skadesai    {
1365282527Skadesai        u_long addr;
1366282527Skadesai        int iclass;
1367282527Skadesai
1368282533Skadesai        iclass = 0;
1369282527Skadesai        addr = ntohl(pip->ip_src.s_addr);
1370282533Skadesai        if      (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1371282533Skadesai            iclass = 3;
1372282533Skadesai        else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1373282533Skadesai            iclass = 2;
1374282527Skadesai        else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1375272744Skadesai            iclass = 1;
1376282527Skadesai
1377282527Skadesai        if (iclass == 0)
1378265555Sambrisko        {
1379272744Skadesai            SetDefaultAliasAddress(pip->ip_src);
1380282527Skadesai        }
1381282527Skadesai    }
1382282527Skadesai
1383265555Sambrisko    iresult = PKT_ALIAS_IGNORED;
1384282527Skadesai    if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1385282533Skadesai    {
1386272744Skadesai        switch (pip->ip_p)
1387265555Sambrisko        {
1388272744Skadesai            case IPPROTO_ICMP:
1389282533Skadesai                iresult = IcmpAliasOut(pip);
1390282527Skadesai                break;
1391282533Skadesai            case IPPROTO_UDP:
1392282527Skadesai                iresult = UdpAliasOut(pip);
1393282533Skadesai                break;
1394282533Skadesai            case IPPROTO_TCP:
1395282533Skadesai                iresult = TcpAliasOut(pip, maxpacketsize);
1396282533Skadesai                break;
1397282527Skadesai	    case IPPROTO_GRE:
1398265555Sambrisko		if (AliasHandlePptpGreOut(pip) == 0)
1399282527Skadesai		    iresult = PKT_ALIAS_OK;
1400265555Sambrisko		else
1401265555Sambrisko		    iresult = ProtoAliasOut(pip);
1402272744Skadesai		break;
1403272744Skadesai	    default:
1404282527Skadesai		iresult = ProtoAliasOut(pip);
1405282527Skadesai                break;
1406282527Skadesai        }
1407282527Skadesai    }
1408265555Sambrisko    else
1409265555Sambrisko    {
1410265555Sambrisko        iresult = FragmentOut(pip);
1411282533Skadesai    }
1412282533Skadesai
1413282533Skadesai    SetDefaultAliasAddress(addr_save);
1414265555Sambrisko    return(iresult);
1415282527Skadesai}
1416272744Skadesai
1417282527Skadesaiint
1418265555SambriskoPacketUnaliasOut(char *ptr,           /* valid IP packet */
1419282527Skadesai                 int  maxpacketsize   /* for error checking */
1420265555Sambrisko                )
1421272744Skadesai{
1422282533Skadesai    struct ip		*pip;
1423282527Skadesai    struct icmp 	*ic;
1424282527Skadesai    struct udphdr	*ud;
1425265555Sambrisko    struct tcphdr 	*tc;
1426272744Skadesai    struct alias_link 	*link;
1427265555Sambrisko    int 		iresult = PKT_ALIAS_IGNORED;
1428265555Sambrisko
1429272744Skadesai    pip = (struct ip *) ptr;
1430272744Skadesai
1431272744Skadesai    /* Defense against mangled packets */
1432272744Skadesai    if (ntohs(pip->ip_len) > maxpacketsize
1433272744Skadesai     || (pip->ip_hl<<2) > maxpacketsize)
1434272744Skadesai        return(iresult);
1435265555Sambrisko
1436272744Skadesai    ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1437272744Skadesai    tc = (struct tcphdr *) ud;
1438272744Skadesai    ic = (struct icmp *) ud;
1439272744Skadesai
1440265555Sambrisko    /* Find a link */
1441272744Skadesai    if (pip->ip_p == IPPROTO_UDP)
1442272744Skadesai        link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1443272744Skadesai                            ud->uh_dport, ud->uh_sport,
1444272744Skadesai                            IPPROTO_UDP, 0);
1445272744Skadesai    else if (pip->ip_p == IPPROTO_TCP)
1446265555Sambrisko        link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1447272744Skadesai                            tc->th_dport, tc->th_sport,
1448272744Skadesai                            IPPROTO_TCP, 0);
1449272744Skadesai    else if (pip->ip_p == IPPROTO_ICMP)
1450272744Skadesai        link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1451272744Skadesai    else
1452272744Skadesai        link = NULL;
1453265555Sambrisko
1454272744Skadesai    /* Change it from an aliased packet to an unaliased packet */
1455272744Skadesai    if (link != NULL)
1456265555Sambrisko    {
1457265555Sambrisko        if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1458299670Skadesai        {
1459299670Skadesai            u_short        *sptr;
1460299670Skadesai            int 	   accumulate;
1461301203Skadesai            struct in_addr original_address;
1462301203Skadesai            u_short        original_port;
1463301203Skadesai
1464265555Sambrisko            original_address = GetOriginalAddress(link);
1465265555Sambrisko            original_port = GetOriginalPort(link);
1466272744Skadesai
1467265555Sambrisko            /* Adjust TCP/UDP checksum */
1468272744Skadesai            sptr = (u_short *) &(pip->ip_src);
1469272744Skadesai            accumulate  = *sptr++;
1470272744Skadesai            accumulate += *sptr;
1471272744Skadesai            sptr = (u_short *) &original_address;
1472272744Skadesai            accumulate -= *sptr++;
1473272744Skadesai            accumulate -= *sptr;
1474272744Skadesai
1475272744Skadesai            if (pip->ip_p == IPPROTO_UDP) {
1476272744Skadesai                accumulate += ud->uh_sport;
1477272744Skadesai                accumulate -= original_port;
1478272744Skadesai                ADJUST_CHECKSUM(accumulate, ud->uh_sum)
1479272744Skadesai	    } else {
1480272744Skadesai                accumulate += tc->th_sport;
1481272744Skadesai                accumulate -= original_port;
1482272744Skadesai                ADJUST_CHECKSUM(accumulate, tc->th_sum)
1483272744Skadesai	    }
1484265555Sambrisko
1485272744Skadesai            /* Adjust IP checksum */
1486272744Skadesai            DifferentialChecksum(&pip->ip_sum,
1487272744Skadesai                                 (u_short *) &original_address,
1488272744Skadesai                                 (u_short *) &pip->ip_src,
1489272744Skadesai                                 2);
1490272744Skadesai
1491272744Skadesai            /* Un-alias source address and port number */
1492272744Skadesai            pip->ip_src = original_address;
1493265555Sambrisko            if (pip->ip_p == IPPROTO_UDP)
1494272744Skadesai                ud->uh_sport = original_port;
1495272744Skadesai	    else
1496265555Sambrisko                tc->th_sport = original_port;
1497272744Skadesai
1498265555Sambrisko	    iresult = PKT_ALIAS_OK;
1499272744Skadesai
1500272744Skadesai        } else if (pip->ip_p == IPPROTO_ICMP) {
1501272744Skadesai
1502272744Skadesai            u_short        *sptr;
1503272744Skadesai            int            accumulate;
1504272744Skadesai            struct in_addr original_address;
1505272744Skadesai            u_short        original_id;
1506272744Skadesai
1507272744Skadesai            original_address = GetOriginalAddress(link);
1508272744Skadesai            original_id = GetOriginalPort(link);
1509272744Skadesai
1510272744Skadesai            /* Adjust ICMP checksum */
1511272744Skadesai            sptr = (u_short *) &(pip->ip_src);
1512272744Skadesai            accumulate  = *sptr++;
1513272744Skadesai            accumulate += *sptr;
1514272744Skadesai            sptr = (u_short *) &original_address;
1515265555Sambrisko            accumulate -= *sptr++;
1516272744Skadesai            accumulate -= *sptr;
1517272744Skadesai            accumulate += ic->icmp_id;
1518282527Skadesai            accumulate -= original_id;
1519272744Skadesai            ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
1520265555Sambrisko
1521265555Sambrisko            /* Adjust IP checksum */
1522272744Skadesai            DifferentialChecksum(&pip->ip_sum,
1523272744Skadesai                                 (u_short *) &original_address,
1524272744Skadesai                                 (u_short *) &pip->ip_src,
1525272744Skadesai                                 2);
1526272744Skadesai
1527272744Skadesai            /* Un-alias source address and port number */
1528265555Sambrisko            pip->ip_src = original_address;
1529272744Skadesai            ic->icmp_id = original_id;
1530272744Skadesai
1531272744Skadesai	    iresult = PKT_ALIAS_OK;
1532265555Sambrisko        }
1533272744Skadesai    }
1534272744Skadesai    return(iresult);
1535272744Skadesai
1536265555Sambrisko}
1537272744Skadesai