xref: /freebsd/sys/netinet/libalias/alias.c (revision db901281608f0c69c05dd9ab366155d3225f0fd2)
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()
184     IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
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 IcmpAliasIn (struct ip *);
226 
227 static int IcmpAliasOut1(struct ip *);
228 static int IcmpAliasOut2(struct ip *);
229 static int IcmpAliasOut (struct ip *);
230 
231 static int ProtoAliasIn(struct ip *);
232 static int ProtoAliasOut(struct ip *);
233 
234 static int UdpAliasOut(struct ip *);
235 static int UdpAliasIn (struct ip *);
236 
237 static int TcpAliasOut(struct ip *, int);
238 static int TcpAliasIn (struct ip *);
239 
240 static int GreAliasIn(struct ip *);
241 
242 
243 static int
244 IcmpAliasIn1(struct ip *pip)
245 {
246 /*
247     De-alias incoming echo and timestamp replies.
248     Alias incoming echo and timestamp requests.
249 */
250     struct alias_link *link;
251     struct icmp *ic;
252 
253     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
254 
255 /* Get source address from ICMP data field and restore original data */
256     link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id);
257     if (link != NULL)
258     {
259         u_short original_id;
260         int accumulate;
261 
262         original_id = GetOriginalPort(link);
263 
264 /* Adjust ICMP checksum */
265         accumulate  = ic->icmp_id;
266         accumulate -= original_id;
267         ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
268 
269 /* Put original sequence number back in */
270         ic->icmp_id = original_id;
271 
272 /* Put original address back into IP header */
273         {
274             struct in_addr original_address;
275 
276             original_address = GetOriginalAddress(link);
277             DifferentialChecksum(&pip->ip_sum,
278                                  (u_short *) &original_address,
279                                  (u_short *) &pip->ip_dst,
280                                  2);
281             pip->ip_dst = original_address;
282         }
283 
284         return(PKT_ALIAS_OK);
285     }
286     return(PKT_ALIAS_IGNORED);
287 }
288 
289 static int
290 IcmpAliasIn2(struct ip *pip)
291 {
292 /*
293     Alias incoming ICMP error messages containing
294     IP header and first 64 bits of datagram.
295 */
296     struct ip *ip;
297     struct icmp *ic, *ic2;
298     struct udphdr *ud;
299     struct tcphdr *tc;
300     struct alias_link *link;
301 
302     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
303     ip = &ic->icmp_ip;
304 
305     ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
306     tc = (struct tcphdr *) ud;
307     ic2 = (struct icmp *) ud;
308 
309     if (ip->ip_p == IPPROTO_UDP)
310         link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
311                             ud->uh_dport, ud->uh_sport,
312                             IPPROTO_UDP);
313     else if (ip->ip_p == IPPROTO_TCP)
314         link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
315                             tc->th_dport, tc->th_sport,
316                             IPPROTO_TCP);
317     else if (ip->ip_p == IPPROTO_ICMP) {
318         if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
319             link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id);
320         else
321             link = NULL;
322     } else
323         link = NULL;
324 
325     if (link != NULL)
326     {
327         if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
328         {
329             u_short *sptr;
330             int accumulate;
331             struct in_addr original_address;
332             u_short original_port;
333 
334             original_address = GetOriginalAddress(link);
335             original_port = GetOriginalPort(link);
336 
337 /* Adjust ICMP checksum */
338             sptr = (u_short *) &(ip->ip_src);
339             accumulate  = *sptr++;
340             accumulate += *sptr;
341             sptr = (u_short *) &original_address;
342             accumulate -= *sptr++;
343             accumulate -= *sptr;
344             accumulate += ud->uh_sport;
345             accumulate -= original_port;
346             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
347 
348 /* Un-alias address in IP header */
349             DifferentialChecksum(&pip->ip_sum,
350                                  (u_short *) &original_address,
351                                  (u_short *) &pip->ip_dst,
352                                  2);
353             pip->ip_dst = original_address;
354 
355 /* Un-alias address and port number of original IP packet
356 fragment contained in ICMP data section */
357             ip->ip_src = original_address;
358             ud->uh_sport = original_port;
359         }
360         else if (ip->ip_p == IPPROTO_ICMP)
361         {
362             u_short *sptr;
363             int accumulate;
364             struct in_addr original_address;
365             u_short original_id;
366 
367             original_address = GetOriginalAddress(link);
368             original_id = GetOriginalPort(link);
369 
370 /* Adjust ICMP checksum */
371             sptr = (u_short *) &(ip->ip_src);
372             accumulate  = *sptr++;
373             accumulate += *sptr;
374             sptr = (u_short *) &original_address;
375             accumulate -= *sptr++;
376             accumulate -= *sptr;
377             accumulate += ic2->icmp_id;
378             accumulate -= original_id;
379             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
380 
381 /* Un-alias address in IP header */
382             DifferentialChecksum(&pip->ip_sum,
383                                  (u_short *) &original_address,
384                                  (u_short *) &pip->ip_dst,
385                                  2);
386             pip->ip_dst = original_address;
387 
388 /* Un-alias address of original IP packet and sequence number of
389    embedded ICMP datagram */
390             ip->ip_src = original_address;
391             ic2->icmp_id = original_id;
392         }
393         return(PKT_ALIAS_OK);
394     }
395     return(PKT_ALIAS_IGNORED);
396 }
397 
398 
399 static int
400 IcmpAliasIn(struct ip *pip)
401 {
402     int iresult;
403     struct icmp *ic;
404 
405 /* Return if proxy-only mode is enabled */
406     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
407         return PKT_ALIAS_OK;
408 
409     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
410 
411     iresult = PKT_ALIAS_IGNORED;
412     switch (ic->icmp_type)
413     {
414         case ICMP_ECHOREPLY:
415         case ICMP_TSTAMPREPLY:
416             if (ic->icmp_code == 0)
417             {
418                 iresult = IcmpAliasIn1(pip);
419             }
420             break;
421         case ICMP_UNREACH:
422         case ICMP_SOURCEQUENCH:
423         case ICMP_TIMXCEED:
424         case ICMP_PARAMPROB:
425             iresult = IcmpAliasIn2(pip);
426             break;
427         case ICMP_ECHO:
428         case ICMP_TSTAMP:
429             iresult = IcmpAliasIn1(pip);
430             break;
431     }
432     return(iresult);
433 }
434 
435 
436 static int
437 IcmpAliasOut1(struct ip *pip)
438 {
439 /*
440     Alias outgoing echo and timestamp requests.
441     De-alias outgoing echo and timestamp replies.
442 */
443     struct alias_link *link;
444     struct icmp *ic;
445 
446     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
447 
448 /* Save overwritten data for when echo packet returns */
449     link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id);
450     if (link != NULL)
451     {
452         u_short alias_id;
453         int accumulate;
454 
455         alias_id = GetAliasPort(link);
456 
457 /* Since data field is being modified, adjust ICMP checksum */
458         accumulate  = ic->icmp_id;
459         accumulate -= alias_id;
460         ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
461 
462 /* Alias sequence number */
463         ic->icmp_id = alias_id;
464 
465 /* Change source address */
466         {
467             struct in_addr alias_address;
468 
469             alias_address = GetAliasAddress(link);
470             DifferentialChecksum(&pip->ip_sum,
471                                  (u_short *) &alias_address,
472                                  (u_short *) &pip->ip_src,
473                                  2);
474             pip->ip_src = alias_address;
475         }
476 
477         return(PKT_ALIAS_OK);
478     }
479     return(PKT_ALIAS_IGNORED);
480 }
481 
482 
483 static int
484 IcmpAliasOut2(struct ip *pip)
485 {
486 /*
487     Alias outgoing ICMP error messages containing
488     IP header and first 64 bits of datagram.
489 */
490     struct ip *ip;
491     struct icmp *ic, *ic2;
492     struct udphdr *ud;
493     struct tcphdr *tc;
494     struct alias_link *link;
495 
496     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
497     ip = &ic->icmp_ip;
498 
499     ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
500     tc = (struct tcphdr *) ud;
501     ic2 = (struct icmp *) ud;
502 
503     if (ip->ip_p == IPPROTO_UDP)
504         link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
505                             ud->uh_dport, ud->uh_sport,
506                             IPPROTO_UDP);
507     else if (ip->ip_p == IPPROTO_TCP)
508         link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
509                             tc->th_dport, tc->th_sport,
510                             IPPROTO_TCP);
511     else if (ip->ip_p == IPPROTO_ICMP) {
512         if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
513             link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id);
514         else
515             link = NULL;
516     } else
517         link = NULL;
518 
519     if (link != NULL)
520     {
521         if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
522         {
523             u_short *sptr;
524             int accumulate;
525             struct in_addr alias_address;
526             u_short alias_port;
527 
528             alias_address = GetAliasAddress(link);
529             alias_port = GetAliasPort(link);
530 
531 /* Adjust ICMP checksum */
532             sptr = (u_short *) &(ip->ip_dst);
533             accumulate  = *sptr++;
534             accumulate += *sptr;
535             sptr = (u_short *) &alias_address;
536             accumulate -= *sptr++;
537             accumulate -= *sptr;
538             accumulate += ud->uh_dport;
539             accumulate -= alias_port;
540             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
541 
542 /*
543  * Alias address in IP header if it comes from the host
544  * the original TCP/UDP packet was destined for.
545  */
546 	    if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
547 		DifferentialChecksum(&pip->ip_sum,
548 				     (u_short *) &alias_address,
549 				     (u_short *) &pip->ip_src,
550 				     2);
551 		pip->ip_src = alias_address;
552 	    }
553 
554 /* Alias address and port number of original IP packet
555 fragment contained in ICMP data section */
556             ip->ip_dst = alias_address;
557             ud->uh_dport = alias_port;
558         }
559         else if (ip->ip_p == IPPROTO_ICMP)
560         {
561             u_short *sptr;
562             int accumulate;
563             struct in_addr alias_address;
564             u_short alias_id;
565 
566             alias_address = GetAliasAddress(link);
567             alias_id = GetAliasPort(link);
568 
569 /* Adjust ICMP checksum */
570             sptr = (u_short *) &(ip->ip_dst);
571             accumulate  = *sptr++;
572             accumulate += *sptr;
573             sptr = (u_short *) &alias_address;
574             accumulate -= *sptr++;
575             accumulate -= *sptr;
576             accumulate += ic2->icmp_id;
577             accumulate -= alias_id;
578             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
579 
580 /*
581  * Alias address in IP header if it comes from the host
582  * the original ICMP message was destined for.
583  */
584 	    if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
585 		DifferentialChecksum(&pip->ip_sum,
586 				     (u_short *) &alias_address,
587 				     (u_short *) &pip->ip_src,
588 				     2);
589 		pip->ip_src = alias_address;
590 	    }
591 
592 /* Alias address of original IP packet and sequence number of
593    embedded ICMP datagram */
594             ip->ip_dst = alias_address;
595             ic2->icmp_id = alias_id;
596         }
597         return(PKT_ALIAS_OK);
598     }
599     return(PKT_ALIAS_IGNORED);
600 }
601 
602 
603 static int
604 IcmpAliasOut(struct ip *pip)
605 {
606     int iresult;
607     struct icmp *ic;
608 
609 /* Return if proxy-only mode is enabled */
610     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
611         return PKT_ALIAS_OK;
612 
613     ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
614 
615     iresult = PKT_ALIAS_IGNORED;
616     switch (ic->icmp_type)
617     {
618         case ICMP_ECHO:
619         case ICMP_TSTAMP:
620             if (ic->icmp_code == 0)
621             {
622                 iresult = IcmpAliasOut1(pip);
623             }
624             break;
625         case ICMP_UNREACH:
626         case ICMP_SOURCEQUENCH:
627         case ICMP_TIMXCEED:
628         case ICMP_PARAMPROB:
629             iresult = IcmpAliasOut2(pip);
630             break;
631         case ICMP_ECHOREPLY:
632         case ICMP_TSTAMPREPLY:
633             iresult = IcmpAliasOut1(pip);
634     }
635     return(iresult);
636 }
637 
638 
639 
640 static int
641 ProtoAliasIn(struct ip *pip)
642 {
643 /*
644   Handle incoming IP packets. The
645   only thing which is done in this case is to alias
646   the dest IP address of the packet to our inside
647   machine.
648 */
649     struct alias_link *link;
650 
651 /* Return if proxy-only mode is enabled */
652     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
653         return PKT_ALIAS_OK;
654 
655     link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
656     if (link != NULL)
657     {
658         struct in_addr original_address;
659 
660         original_address = GetOriginalAddress(link);
661 
662 /* Restore original IP address */
663         DifferentialChecksum(&pip->ip_sum,
664                              (u_short *) &original_address,
665                              (u_short *) &pip->ip_dst,
666                              2);
667         pip->ip_dst = original_address;
668 
669 	return(PKT_ALIAS_OK);
670     }
671     return(PKT_ALIAS_IGNORED);
672 }
673 
674 
675 static int
676 ProtoAliasOut(struct ip *pip)
677 {
678 /*
679   Handle outgoing IP packets. The
680   only thing which is done in this case is to alias
681   the source IP address of the packet.
682 */
683     struct alias_link *link;
684 
685 /* Return if proxy-only mode is enabled */
686     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
687         return PKT_ALIAS_OK;
688 
689     link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
690     if (link != NULL)
691     {
692         struct in_addr alias_address;
693 
694         alias_address = GetAliasAddress(link);
695 
696 /* Change source address */
697         DifferentialChecksum(&pip->ip_sum,
698                              (u_short *) &alias_address,
699                              (u_short *) &pip->ip_src,
700                              2);
701         pip->ip_src = alias_address;
702 
703         return(PKT_ALIAS_OK);
704     }
705     return(PKT_ALIAS_IGNORED);
706 }
707 
708 
709 static int
710 GreAliasIn(struct ip *pip)
711 {
712     u_short call_id;
713     struct alias_link *link;
714 
715 /* Return if proxy-only mode is enabled. */
716     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
717         return (PKT_ALIAS_OK);
718 
719     if (PptpGetCallID(pip, &call_id)) {
720 	if ((link = FindPptpIn(pip->ip_src, pip->ip_dst, call_id)) != NULL) {
721 	    struct in_addr alias_address;
722 	    struct in_addr original_address;
723 
724 	    alias_address = GetAliasAddress(link);
725 	    original_address = GetOriginalAddress(link);
726 	    PptpSetCallID(pip, GetOriginalPort(link));
727 
728 	    /* Restore original IP address. */
729 	    DifferentialChecksum(&pip->ip_sum,
730 				 (u_short *)&original_address,
731 				 (u_short *)&pip->ip_dst,
732 				 2);
733 	    pip->ip_dst = original_address;
734 
735 	    return (PKT_ALIAS_OK);
736 	} else
737 	    return (PKT_ALIAS_IGNORED);
738     } else
739 	return ProtoAliasIn(pip);
740 }
741 
742 
743 static int
744 UdpAliasIn(struct ip *pip)
745 {
746     struct udphdr *ud;
747     struct alias_link *link;
748 
749 /* Return if proxy-only mode is enabled */
750     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
751         return PKT_ALIAS_OK;
752 
753     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
754 
755     link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
756                         ud->uh_sport, ud->uh_dport,
757                         IPPROTO_UDP);
758     if (link != NULL)
759     {
760         struct in_addr alias_address;
761         struct in_addr original_address;
762         u_short alias_port;
763         int accumulate;
764         u_short *sptr;
765 	int r = 0;
766 
767         alias_address = GetAliasAddress(link);
768         original_address = GetOriginalAddress(link);
769         alias_port = ud->uh_dport;
770         ud->uh_dport = GetOriginalPort(link);
771 
772 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
773 		if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
774          || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
775 		{
776             r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
777 		} else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
778          || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER )
779 		{
780             r = AliasHandleUdpNbtNS(pip, link,
781 								&alias_address,
782 								&alias_port,
783 								&original_address,
784 								&ud->uh_dport );
785 		}
786 
787         if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
788             AliasHandleCUSeeMeIn(pip, original_address);
789 
790 /* If UDP checksum is not zero, then adjust since destination port */
791 /* is being unaliased and destination port is being altered.       */
792         if (ud->uh_sum != 0)
793         {
794             accumulate  = alias_port;
795             accumulate -= ud->uh_dport;
796             sptr = (u_short *) &alias_address;
797             accumulate += *sptr++;
798             accumulate += *sptr;
799             sptr = (u_short *) &original_address;
800             accumulate -= *sptr++;
801             accumulate -= *sptr;
802             ADJUST_CHECKSUM(accumulate, ud->uh_sum)
803         }
804 
805 /* Restore original IP address */
806         DifferentialChecksum(&pip->ip_sum,
807                              (u_short *) &original_address,
808                              (u_short *) &pip->ip_dst,
809                              2);
810         pip->ip_dst = original_address;
811 
812 	/*
813 	 * If we cannot figure out the packet, ignore it.
814 	 */
815 	if (r < 0)
816 	    return(PKT_ALIAS_IGNORED);
817 	else
818 	    return(PKT_ALIAS_OK);
819     }
820     return(PKT_ALIAS_IGNORED);
821 }
822 
823 static int
824 UdpAliasOut(struct ip *pip)
825 {
826     struct udphdr *ud;
827     struct alias_link *link;
828 
829 /* Return if proxy-only mode is enabled */
830     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
831         return PKT_ALIAS_OK;
832 
833     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
834 
835     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
836                          ud->uh_sport, ud->uh_dport,
837                          IPPROTO_UDP);
838     if (link != NULL)
839     {
840         u_short alias_port;
841         struct in_addr alias_address;
842 
843         alias_address = GetAliasAddress(link);
844         alias_port = GetAliasPort(link);
845 
846         if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
847             AliasHandleCUSeeMeOut(pip, link);
848 
849 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
850 		if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
851          || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
852 		{
853             AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
854 		} else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
855          || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER )
856 		{
857             AliasHandleUdpNbtNS(pip, link,
858 								&pip->ip_src,
859 								&ud->uh_sport,
860 							    &alias_address,
861 							 	&alias_port);
862 		}
863 
864 /* If UDP checksum is not zero, adjust since source port is */
865 /* being aliased and source address is being altered        */
866         if (ud->uh_sum != 0)
867         {
868             int accumulate;
869             u_short *sptr;
870 
871             accumulate  = ud->uh_sport;
872             accumulate -= alias_port;
873             sptr = (u_short *) &(pip->ip_src);
874             accumulate += *sptr++;
875             accumulate += *sptr;
876             sptr = (u_short *) &alias_address;
877             accumulate -= *sptr++;
878             accumulate -= *sptr;
879             ADJUST_CHECKSUM(accumulate, ud->uh_sum)
880         }
881 
882 /* Put alias port in UDP header */
883         ud->uh_sport = alias_port;
884 
885 /* Change source address */
886         DifferentialChecksum(&pip->ip_sum,
887                              (u_short *) &alias_address,
888                              (u_short *) &pip->ip_src,
889                              2);
890         pip->ip_src = alias_address;
891 
892         return(PKT_ALIAS_OK);
893     }
894     return(PKT_ALIAS_IGNORED);
895 }
896 
897 
898 
899 static int
900 TcpAliasIn(struct ip *pip)
901 {
902     struct tcphdr *tc;
903     struct alias_link *link;
904 
905     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
906 
907     link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
908                         tc->th_sport, tc->th_dport,
909                         IPPROTO_TCP);
910     if (link != NULL)
911     {
912         struct in_addr alias_address;
913         struct in_addr original_address;
914         struct in_addr proxy_address;
915         u_short alias_port;
916         u_short proxy_port;
917         int accumulate;
918         u_short *sptr;
919 
920 /* Special processing for IP encoding protocols */
921         if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
922          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
923             AliasHandlePptpIn(pip, link);
924 
925         alias_address = GetAliasAddress(link);
926         original_address = GetOriginalAddress(link);
927         proxy_address = GetProxyAddress(link);
928         alias_port = tc->th_dport;
929         tc->th_dport = GetOriginalPort(link);
930         proxy_port = GetProxyPort(link);
931 
932 /* Adjust TCP checksum since destination port is being unaliased */
933 /* and destination port is being altered.                        */
934         accumulate  = alias_port;
935         accumulate -= tc->th_dport;
936         sptr = (u_short *) &alias_address;
937         accumulate += *sptr++;
938         accumulate += *sptr;
939         sptr = (u_short *) &original_address;
940         accumulate -= *sptr++;
941         accumulate -= *sptr;
942 
943 /* If this is a proxy, then modify the TCP source port and
944    checksum accumulation */
945         if (proxy_port != 0)
946         {
947             accumulate += tc->th_sport;
948             tc->th_sport = proxy_port;
949             accumulate -= tc->th_sport;
950 
951             sptr = (u_short *) &pip->ip_src;
952             accumulate += *sptr++;
953             accumulate += *sptr;
954             sptr = (u_short *) &proxy_address;
955             accumulate -= *sptr++;
956             accumulate -= *sptr;
957         }
958 
959 /* See if ACK number needs to be modified */
960         if (GetAckModified(link) == 1)
961         {
962             int delta;
963 
964             delta = GetDeltaAckIn(pip, link);
965             if (delta != 0)
966             {
967                 sptr = (u_short *) &tc->th_ack;
968                 accumulate += *sptr++;
969                 accumulate += *sptr;
970                 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
971                 sptr = (u_short *) &tc->th_ack;
972                 accumulate -= *sptr++;
973                 accumulate -= *sptr;
974             }
975         }
976 
977         ADJUST_CHECKSUM(accumulate, tc->th_sum);
978 
979 /* Restore original IP address */
980         sptr = (u_short *) &pip->ip_dst;
981         accumulate  = *sptr++;
982         accumulate += *sptr;
983         pip->ip_dst = original_address;
984         sptr = (u_short *) &pip->ip_dst;
985         accumulate -= *sptr++;
986         accumulate -= *sptr;
987 
988 /* If this is a transparent proxy packet, then modify the source
989    address */
990         if (proxy_address.s_addr != 0)
991         {
992             sptr = (u_short *) &pip->ip_src;
993             accumulate += *sptr++;
994             accumulate += *sptr;
995             pip->ip_src = proxy_address;
996             sptr = (u_short *) &pip->ip_src;
997             accumulate -= *sptr++;
998             accumulate -= *sptr;
999         }
1000 
1001         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1002 
1003 /* Monitor TCP connection state */
1004         TcpMonitorIn(pip, link);
1005 
1006         return(PKT_ALIAS_OK);
1007     }
1008     return(PKT_ALIAS_IGNORED);
1009 }
1010 
1011 static int
1012 TcpAliasOut(struct ip *pip, int maxpacketsize)
1013 {
1014     int proxy_type;
1015     u_short dest_port;
1016     u_short proxy_server_port;
1017     struct in_addr dest_address;
1018     struct in_addr proxy_server_address;
1019     struct tcphdr *tc;
1020     struct alias_link *link;
1021 
1022     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1023 
1024     proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1025 
1026     if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1027         return PKT_ALIAS_OK;
1028 
1029 /* If this is a transparent proxy, save original destination,
1030    then alter the destination and adjust checksums */
1031     dest_port = tc->th_dport;
1032     dest_address = pip->ip_dst;
1033     if (proxy_type != 0)
1034     {
1035         int accumulate;
1036         u_short *sptr;
1037 
1038         accumulate = tc->th_dport;
1039         tc->th_dport = proxy_server_port;
1040         accumulate -= tc->th_dport;
1041 
1042         sptr = (u_short *) &(pip->ip_dst);
1043         accumulate += *sptr++;
1044         accumulate += *sptr;
1045         sptr = (u_short *) &proxy_server_address;
1046         accumulate -= *sptr++;
1047         accumulate -= *sptr;
1048 
1049         ADJUST_CHECKSUM(accumulate, tc->th_sum);
1050 
1051         sptr = (u_short *) &(pip->ip_dst);
1052         accumulate  = *sptr++;
1053         accumulate += *sptr;
1054         pip->ip_dst = proxy_server_address;
1055         sptr = (u_short *) &(pip->ip_dst);
1056         accumulate -= *sptr++;
1057         accumulate -= *sptr;
1058 
1059         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1060     }
1061 
1062     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1063                          tc->th_sport, tc->th_dport,
1064                          IPPROTO_TCP);
1065     if (link !=NULL)
1066     {
1067         u_short alias_port;
1068         struct in_addr alias_address;
1069         int accumulate;
1070         u_short *sptr;
1071 
1072 /* Save original destination address, if this is a proxy packet.
1073    Also modify packet to include destination encoding. */
1074         if (proxy_type != 0)
1075         {
1076             SetProxyPort(link, dest_port);
1077             SetProxyAddress(link, dest_address);
1078             ProxyModify(link, pip, maxpacketsize, proxy_type);
1079         }
1080 
1081 /* Get alias address and port */
1082         alias_port = GetAliasPort(link);
1083         alias_address = GetAliasAddress(link);
1084 
1085 /* Monitor TCP connection state */
1086         TcpMonitorOut(pip, link);
1087 
1088 /* Special processing for IP encoding protocols */
1089         if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1090          || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1091             AliasHandleFtpOut(pip, link, maxpacketsize);
1092         else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1093          || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1094             AliasHandleIrcOut(pip, link, maxpacketsize);
1095         else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1096          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1097          || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1098          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1099             AliasHandleRtspOut(pip, link, maxpacketsize);
1100         else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1101          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1102             AliasHandlePptpOut(pip, link);
1103 
1104 /* Adjust TCP checksum since source port is being aliased */
1105 /* and source address is being altered                    */
1106         accumulate  = tc->th_sport;
1107         tc->th_sport = alias_port;
1108         accumulate -= tc->th_sport;
1109 
1110         sptr = (u_short *) &(pip->ip_src);
1111         accumulate += *sptr++;
1112         accumulate += *sptr;
1113         sptr = (u_short *) &alias_address;
1114         accumulate -= *sptr++;
1115         accumulate -= *sptr;
1116 
1117 /* Modify sequence number if necessary */
1118         if (GetAckModified(link) == 1)
1119         {
1120             int delta;
1121 
1122             delta = GetDeltaSeqOut(pip, link);
1123             if (delta != 0)
1124             {
1125                 sptr = (u_short *) &tc->th_seq;
1126                 accumulate += *sptr++;
1127                 accumulate += *sptr;
1128                 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1129                 sptr = (u_short *) &tc->th_seq;
1130                 accumulate -= *sptr++;
1131                 accumulate -= *sptr;
1132             }
1133         }
1134 
1135         ADJUST_CHECKSUM(accumulate, tc->th_sum)
1136 
1137 /* Change source address */
1138         sptr = (u_short *) &(pip->ip_src);
1139         accumulate  = *sptr++;
1140         accumulate += *sptr;
1141         pip->ip_src = alias_address;
1142         sptr = (u_short *) &(pip->ip_src);
1143         accumulate -= *sptr++;
1144         accumulate -= *sptr;
1145 
1146         ADJUST_CHECKSUM(accumulate, pip->ip_sum)
1147 
1148         return(PKT_ALIAS_OK);
1149     }
1150     return(PKT_ALIAS_IGNORED);
1151 }
1152 
1153 
1154 
1155 
1156 /* Fragment Handling
1157 
1158     FragmentIn()
1159     FragmentOut()
1160 
1161 The packet aliasing module has a limited ability for handling IP
1162 fragments.  If the ICMP, TCP or UDP header is in the first fragment
1163 received, then the ID number of the IP packet is saved, and other
1164 fragments are identified according to their ID number and IP address
1165 they were sent from.  Pointers to unresolved fragments can also be
1166 saved and recalled when a header fragment is seen.
1167 */
1168 
1169 /* Local prototypes */
1170 static int FragmentIn(struct ip *);
1171 static int FragmentOut(struct ip *);
1172 
1173 
1174 static int
1175 FragmentIn(struct ip *pip)
1176 {
1177     struct alias_link *link;
1178 
1179     link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1180     if (link != NULL)
1181     {
1182         struct in_addr original_address;
1183 
1184         GetFragmentAddr(link, &original_address);
1185         DifferentialChecksum(&pip->ip_sum,
1186                              (u_short *) &original_address,
1187                              (u_short *) &pip->ip_dst,
1188                              2);
1189         pip->ip_dst = original_address;
1190 
1191         return(PKT_ALIAS_OK);
1192     }
1193     return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1194 }
1195 
1196 
1197 static int
1198 FragmentOut(struct ip *pip)
1199 {
1200     struct in_addr alias_address;
1201 
1202     alias_address = FindAliasAddress(pip->ip_src);
1203     DifferentialChecksum(&pip->ip_sum,
1204                          (u_short *) &alias_address,
1205                          (u_short *) &pip->ip_src,
1206                           2);
1207     pip->ip_src = alias_address;
1208 
1209     return(PKT_ALIAS_OK);
1210 }
1211 
1212 
1213 
1214 
1215 
1216 
1217 /* Outside World Access
1218 
1219         PacketAliasSaveFragment()
1220         PacketAliasGetFragment()
1221         PacketAliasFragmentIn()
1222         PacketAliasIn()
1223         PacketAliasOut()
1224         PacketUnaliasOut()
1225 
1226 (prototypes in alias.h)
1227 */
1228 
1229 
1230 int
1231 PacketAliasSaveFragment(char *ptr)
1232 {
1233     int iresult;
1234     struct alias_link *link;
1235     struct ip *pip;
1236 
1237     pip = (struct ip *) ptr;
1238     link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1239     iresult = PKT_ALIAS_ERROR;
1240     if (link != NULL)
1241     {
1242         SetFragmentPtr(link, ptr);
1243         iresult = PKT_ALIAS_OK;
1244     }
1245     return(iresult);
1246 }
1247 
1248 
1249 char *
1250 PacketAliasGetFragment(char *ptr)
1251 {
1252     struct alias_link *link;
1253     char *fptr;
1254     struct ip *pip;
1255 
1256     pip = (struct ip *) ptr;
1257     link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1258     if (link != NULL)
1259     {
1260         GetFragmentPtr(link, &fptr);
1261         SetFragmentPtr(link, NULL);
1262         SetExpire(link, 0); /* Deletes link */
1263 
1264         return(fptr);
1265     }
1266     else
1267     {
1268         return(NULL);
1269     }
1270 }
1271 
1272 
1273 void
1274 PacketAliasFragmentIn(char *ptr,          /* Points to correctly de-aliased
1275                                              header fragment */
1276                       char *ptr_fragment  /* Points to fragment which must
1277                                              be de-aliased   */
1278                      )
1279 {
1280     struct ip *pip;
1281     struct ip *fpip;
1282 
1283     pip = (struct ip *) ptr;
1284     fpip = (struct ip *) ptr_fragment;
1285 
1286     DifferentialChecksum(&fpip->ip_sum,
1287                          (u_short *) &pip->ip_dst,
1288                          (u_short *) &fpip->ip_dst,
1289                          2);
1290     fpip->ip_dst = pip->ip_dst;
1291 }
1292 
1293 
1294 int
1295 PacketAliasIn(char *ptr, int maxpacketsize)
1296 {
1297     struct in_addr alias_addr;
1298     struct ip *pip;
1299     int iresult;
1300 
1301     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1302         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1303         iresult = PacketAliasOut(ptr, maxpacketsize);
1304         packetAliasMode |= PKT_ALIAS_REVERSE;
1305         return iresult;
1306     }
1307 
1308     HouseKeeping();
1309     ClearCheckNewLink();
1310     pip = (struct ip *) ptr;
1311     alias_addr = pip->ip_dst;
1312 
1313     /* Defense against mangled packets */
1314     if (ntohs(pip->ip_len) > maxpacketsize
1315      || (pip->ip_hl<<2) > maxpacketsize)
1316         return PKT_ALIAS_IGNORED;
1317 
1318     iresult = PKT_ALIAS_IGNORED;
1319     if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1320     {
1321         switch (pip->ip_p)
1322         {
1323             case IPPROTO_ICMP:
1324                 iresult = IcmpAliasIn(pip);
1325                 break;
1326             case IPPROTO_UDP:
1327                 iresult = UdpAliasIn(pip);
1328                 break;
1329             case IPPROTO_TCP:
1330                 iresult = TcpAliasIn(pip);
1331                 break;
1332             case IPPROTO_GRE:
1333                 iresult = GreAliasIn(pip);
1334                 break;
1335 	    default:
1336 		iresult = ProtoAliasIn(pip);
1337                 break;
1338         }
1339 
1340         if (ntohs(pip->ip_off) & IP_MF)
1341         {
1342             struct alias_link *link;
1343 
1344             link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1345             if (link != NULL)
1346             {
1347                 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1348                 SetFragmentAddr(link, pip->ip_dst);
1349             }
1350             else
1351             {
1352                 iresult = PKT_ALIAS_ERROR;
1353             }
1354         }
1355     }
1356     else
1357     {
1358         iresult = FragmentIn(pip);
1359     }
1360 
1361     return(iresult);
1362 }
1363 
1364 
1365 
1366 /* Unregistered address ranges */
1367 
1368 /* 10.0.0.0   ->   10.255.255.255 */
1369 #define UNREG_ADDR_A_LOWER 0x0a000000
1370 #define UNREG_ADDR_A_UPPER 0x0affffff
1371 
1372 /* 172.16.0.0  ->  172.31.255.255 */
1373 #define UNREG_ADDR_B_LOWER 0xac100000
1374 #define UNREG_ADDR_B_UPPER 0xac1fffff
1375 
1376 /* 192.168.0.0 -> 192.168.255.255 */
1377 #define UNREG_ADDR_C_LOWER 0xc0a80000
1378 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1379 
1380 int
1381 PacketAliasOut(char *ptr,           /* valid IP packet */
1382                int  maxpacketsize   /* How much the packet data may grow
1383                                        (FTP and IRC inline changes) */
1384               )
1385 {
1386     int iresult;
1387     struct in_addr addr_save;
1388     struct ip *pip;
1389 
1390     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1391         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1392         iresult = PacketAliasIn(ptr, maxpacketsize);
1393         packetAliasMode |= PKT_ALIAS_REVERSE;
1394         return iresult;
1395     }
1396 
1397     HouseKeeping();
1398     ClearCheckNewLink();
1399     pip = (struct ip *) ptr;
1400 
1401     /* Defense against mangled packets */
1402     if (ntohs(pip->ip_len) > maxpacketsize
1403      || (pip->ip_hl<<2) > maxpacketsize)
1404         return PKT_ALIAS_IGNORED;
1405 
1406     addr_save = GetDefaultAliasAddress();
1407     if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1408     {
1409         u_long addr;
1410         int iclass;
1411 
1412         iclass = 0;
1413         addr = ntohl(pip->ip_src.s_addr);
1414         if      (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1415             iclass = 3;
1416         else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1417             iclass = 2;
1418         else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1419             iclass = 1;
1420 
1421         if (iclass == 0)
1422         {
1423             SetDefaultAliasAddress(pip->ip_src);
1424         }
1425     }
1426 
1427     iresult = PKT_ALIAS_IGNORED;
1428     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1429     {
1430         switch (pip->ip_p)
1431         {
1432             case IPPROTO_ICMP:
1433                 iresult = IcmpAliasOut(pip);
1434                 break;
1435             case IPPROTO_UDP:
1436                 iresult = UdpAliasOut(pip);
1437                 break;
1438             case IPPROTO_TCP:
1439                 iresult = TcpAliasOut(pip, maxpacketsize);
1440                 break;
1441 	    default:
1442 		iresult = ProtoAliasOut(pip);
1443                 break;
1444         }
1445     }
1446     else
1447     {
1448         iresult = FragmentOut(pip);
1449     }
1450 
1451     SetDefaultAliasAddress(addr_save);
1452     return(iresult);
1453 }
1454 
1455 int
1456 PacketUnaliasOut(char *ptr,           /* valid IP packet */
1457                  int  maxpacketsize   /* for error checking */
1458                 )
1459 {
1460     struct ip		*pip;
1461     struct icmp 	*ic;
1462     struct udphdr	*ud;
1463     struct tcphdr 	*tc;
1464     struct alias_link 	*link;
1465     int 		iresult = PKT_ALIAS_IGNORED;
1466 
1467     pip = (struct ip *) ptr;
1468 
1469     /* Defense against mangled packets */
1470     if (ntohs(pip->ip_len) > maxpacketsize
1471      || (pip->ip_hl<<2) > maxpacketsize)
1472         return(iresult);
1473 
1474     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1475     tc = (struct tcphdr *) ud;
1476     ic = (struct icmp *) ud;
1477 
1478     /* Find a link */
1479     if (pip->ip_p == IPPROTO_UDP)
1480         link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src,
1481                             ud->uh_dport, ud->uh_sport,
1482                             IPPROTO_UDP);
1483     else if (pip->ip_p == IPPROTO_TCP)
1484         link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src,
1485                             tc->th_dport, tc->th_sport,
1486                             IPPROTO_TCP);
1487     else if (pip->ip_p == IPPROTO_ICMP)
1488         link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id);
1489     else
1490         link = NULL;
1491 
1492     /* Change it from an aliased packet to an unaliased packet */
1493     if (link != NULL)
1494     {
1495         if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1496         {
1497             u_short        *sptr;
1498             int 	   accumulate;
1499             struct in_addr original_address;
1500             u_short        original_port;
1501 
1502             original_address = GetOriginalAddress(link);
1503             original_port = GetOriginalPort(link);
1504 
1505             /* Adjust TCP/UDP checksum */
1506             sptr = (u_short *) &(pip->ip_src);
1507             accumulate  = *sptr++;
1508             accumulate += *sptr;
1509             sptr = (u_short *) &original_address;
1510             accumulate -= *sptr++;
1511             accumulate -= *sptr;
1512 
1513             if (pip->ip_p == IPPROTO_UDP) {
1514                 accumulate += ud->uh_sport;
1515                 accumulate -= original_port;
1516                 ADJUST_CHECKSUM(accumulate, ud->uh_sum)
1517 	    } else {
1518                 accumulate += tc->th_sport;
1519                 accumulate -= original_port;
1520                 ADJUST_CHECKSUM(accumulate, tc->th_sum)
1521 	    }
1522 
1523             /* Adjust IP checksum */
1524             DifferentialChecksum(&pip->ip_sum,
1525                                  (u_short *) &original_address,
1526                                  (u_short *) &pip->ip_src,
1527                                  2);
1528 
1529             /* Un-alias source address and port number */
1530             pip->ip_src = original_address;
1531             if (pip->ip_p == IPPROTO_UDP)
1532                 ud->uh_sport = original_port;
1533 	    else
1534                 tc->th_sport = original_port;
1535 
1536 	    iresult = PKT_ALIAS_OK;
1537 
1538         } else if (pip->ip_p == IPPROTO_ICMP) {
1539 
1540             u_short        *sptr;
1541             int            accumulate;
1542             struct in_addr original_address;
1543             u_short        original_id;
1544 
1545             original_address = GetOriginalAddress(link);
1546             original_id = GetOriginalPort(link);
1547 
1548             /* Adjust ICMP checksum */
1549             sptr = (u_short *) &(pip->ip_src);
1550             accumulate  = *sptr++;
1551             accumulate += *sptr;
1552             sptr = (u_short *) &original_address;
1553             accumulate -= *sptr++;
1554             accumulate -= *sptr;
1555             accumulate += ic->icmp_id;
1556             accumulate -= original_id;
1557             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
1558 
1559             /* Adjust IP checksum */
1560             DifferentialChecksum(&pip->ip_sum,
1561                                  (u_short *) &original_address,
1562                                  (u_short *) &pip->ip_src,
1563                                  2);
1564 
1565             /* Un-alias source address and port number */
1566             pip->ip_src = original_address;
1567             ic->icmp_id = original_id;
1568 
1569 	    iresult = PKT_ALIAS_OK;
1570         }
1571     }
1572     return(iresult);
1573 
1574 }
1575