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