xref: /freebsd/sys/netinet/libalias/alias.c (revision d1ba25f456132eabc6f1244e4bbbf3d19e8f3a31)
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 /* Special processing for IP encoding protocols */
773 	if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
774 	    AliasHandleCUSeeMeIn(pip, original_address);
775 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
776 	else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
777 	      || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
778 	    r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
779 	else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
780 	      || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
781 	    r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
782 				    &original_address, &ud->uh_dport);
783 
784 /* If UDP checksum is not zero, then adjust since destination port */
785 /* is being unaliased and destination address is being altered.    */
786         if (ud->uh_sum != 0)
787         {
788             accumulate  = alias_port;
789             accumulate -= ud->uh_dport;
790             sptr = (u_short *) &alias_address;
791             accumulate += *sptr++;
792             accumulate += *sptr;
793             sptr = (u_short *) &original_address;
794             accumulate -= *sptr++;
795             accumulate -= *sptr;
796             ADJUST_CHECKSUM(accumulate, ud->uh_sum)
797         }
798 
799 /* Restore original IP address */
800         DifferentialChecksum(&pip->ip_sum,
801                              (u_short *) &original_address,
802                              (u_short *) &pip->ip_dst,
803                              2);
804         pip->ip_dst = original_address;
805 
806 	/*
807 	 * If we cannot figure out the packet, ignore it.
808 	 */
809 	if (r < 0)
810 	    return(PKT_ALIAS_IGNORED);
811 	else
812 	    return(PKT_ALIAS_OK);
813     }
814     return(PKT_ALIAS_IGNORED);
815 }
816 
817 static int
818 UdpAliasOut(struct ip *pip)
819 {
820     struct udphdr *ud;
821     struct alias_link *link;
822 
823 /* Return if proxy-only mode is enabled */
824     if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
825         return PKT_ALIAS_OK;
826 
827     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
828 
829     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
830                          ud->uh_sport, ud->uh_dport,
831                          IPPROTO_UDP);
832     if (link != NULL)
833     {
834         u_short alias_port;
835         struct in_addr alias_address;
836 
837         alias_address = GetAliasAddress(link);
838         alias_port = GetAliasPort(link);
839 
840 /* Special processing for IP encoding protocols */
841 	if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
842 	    AliasHandleCUSeeMeOut(pip, link);
843 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
844 	else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
845 	      || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
846 	    AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
847 	else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
848 	      || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
849 	    AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
850 				&alias_address, &alias_port);
851 
852 /* If UDP checksum is not zero, adjust since source port is */
853 /* being aliased and source address is being altered        */
854         if (ud->uh_sum != 0)
855         {
856             int accumulate;
857             u_short *sptr;
858 
859             accumulate  = ud->uh_sport;
860             accumulate -= alias_port;
861             sptr = (u_short *) &(pip->ip_src);
862             accumulate += *sptr++;
863             accumulate += *sptr;
864             sptr = (u_short *) &alias_address;
865             accumulate -= *sptr++;
866             accumulate -= *sptr;
867             ADJUST_CHECKSUM(accumulate, ud->uh_sum)
868         }
869 
870 /* Put alias port in UDP header */
871         ud->uh_sport = alias_port;
872 
873 /* Change source address */
874         DifferentialChecksum(&pip->ip_sum,
875                              (u_short *) &alias_address,
876                              (u_short *) &pip->ip_src,
877                              2);
878         pip->ip_src = alias_address;
879 
880         return(PKT_ALIAS_OK);
881     }
882     return(PKT_ALIAS_IGNORED);
883 }
884 
885 
886 
887 static int
888 TcpAliasIn(struct ip *pip)
889 {
890     struct tcphdr *tc;
891     struct alias_link *link;
892 
893     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
894 
895     link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
896                         tc->th_sport, tc->th_dport,
897                         IPPROTO_TCP);
898     if (link != NULL)
899     {
900         struct in_addr alias_address;
901         struct in_addr original_address;
902         struct in_addr proxy_address;
903         u_short alias_port;
904         u_short proxy_port;
905         int accumulate;
906         u_short *sptr;
907 
908 /* Special processing for IP encoding protocols */
909         if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
910          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
911             AliasHandlePptpIn(pip, link);
912 
913         alias_address = GetAliasAddress(link);
914         original_address = GetOriginalAddress(link);
915         proxy_address = GetProxyAddress(link);
916         alias_port = tc->th_dport;
917         tc->th_dport = GetOriginalPort(link);
918         proxy_port = GetProxyPort(link);
919 
920 /* Adjust TCP checksum since destination port is being unaliased */
921 /* and destination port is being altered.                        */
922         accumulate  = alias_port;
923         accumulate -= tc->th_dport;
924         sptr = (u_short *) &alias_address;
925         accumulate += *sptr++;
926         accumulate += *sptr;
927         sptr = (u_short *) &original_address;
928         accumulate -= *sptr++;
929         accumulate -= *sptr;
930 
931 /* If this is a proxy, then modify the TCP source port and
932    checksum accumulation */
933         if (proxy_port != 0)
934         {
935             accumulate += tc->th_sport;
936             tc->th_sport = proxy_port;
937             accumulate -= tc->th_sport;
938 
939             sptr = (u_short *) &pip->ip_src;
940             accumulate += *sptr++;
941             accumulate += *sptr;
942             sptr = (u_short *) &proxy_address;
943             accumulate -= *sptr++;
944             accumulate -= *sptr;
945         }
946 
947 /* See if ACK number needs to be modified */
948         if (GetAckModified(link) == 1)
949         {
950             int delta;
951 
952             delta = GetDeltaAckIn(pip, link);
953             if (delta != 0)
954             {
955                 sptr = (u_short *) &tc->th_ack;
956                 accumulate += *sptr++;
957                 accumulate += *sptr;
958                 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
959                 sptr = (u_short *) &tc->th_ack;
960                 accumulate -= *sptr++;
961                 accumulate -= *sptr;
962             }
963         }
964 
965         ADJUST_CHECKSUM(accumulate, tc->th_sum);
966 
967 /* Restore original IP address */
968         sptr = (u_short *) &pip->ip_dst;
969         accumulate  = *sptr++;
970         accumulate += *sptr;
971         pip->ip_dst = original_address;
972         sptr = (u_short *) &pip->ip_dst;
973         accumulate -= *sptr++;
974         accumulate -= *sptr;
975 
976 /* If this is a transparent proxy packet, then modify the source
977    address */
978         if (proxy_address.s_addr != 0)
979         {
980             sptr = (u_short *) &pip->ip_src;
981             accumulate += *sptr++;
982             accumulate += *sptr;
983             pip->ip_src = proxy_address;
984             sptr = (u_short *) &pip->ip_src;
985             accumulate -= *sptr++;
986             accumulate -= *sptr;
987         }
988 
989         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
990 
991 /* Monitor TCP connection state */
992         TcpMonitorIn(pip, link);
993 
994         return(PKT_ALIAS_OK);
995     }
996     return(PKT_ALIAS_IGNORED);
997 }
998 
999 static int
1000 TcpAliasOut(struct ip *pip, int maxpacketsize)
1001 {
1002     int proxy_type;
1003     u_short dest_port;
1004     u_short proxy_server_port;
1005     struct in_addr dest_address;
1006     struct in_addr proxy_server_address;
1007     struct tcphdr *tc;
1008     struct alias_link *link;
1009 
1010     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1011 
1012     proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1013 
1014     if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1015         return PKT_ALIAS_OK;
1016 
1017 /* If this is a transparent proxy, save original destination,
1018    then alter the destination and adjust checksums */
1019     dest_port = tc->th_dport;
1020     dest_address = pip->ip_dst;
1021     if (proxy_type != 0)
1022     {
1023         int accumulate;
1024         u_short *sptr;
1025 
1026         accumulate = tc->th_dport;
1027         tc->th_dport = proxy_server_port;
1028         accumulate -= tc->th_dport;
1029 
1030         sptr = (u_short *) &(pip->ip_dst);
1031         accumulate += *sptr++;
1032         accumulate += *sptr;
1033         sptr = (u_short *) &proxy_server_address;
1034         accumulate -= *sptr++;
1035         accumulate -= *sptr;
1036 
1037         ADJUST_CHECKSUM(accumulate, tc->th_sum);
1038 
1039         sptr = (u_short *) &(pip->ip_dst);
1040         accumulate  = *sptr++;
1041         accumulate += *sptr;
1042         pip->ip_dst = proxy_server_address;
1043         sptr = (u_short *) &(pip->ip_dst);
1044         accumulate -= *sptr++;
1045         accumulate -= *sptr;
1046 
1047         ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1048     }
1049 
1050     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1051                          tc->th_sport, tc->th_dport,
1052                          IPPROTO_TCP);
1053     if (link !=NULL)
1054     {
1055         u_short alias_port;
1056         struct in_addr alias_address;
1057         int accumulate;
1058         u_short *sptr;
1059 
1060 /* Save original destination address, if this is a proxy packet.
1061    Also modify packet to include destination encoding. */
1062         if (proxy_type != 0)
1063         {
1064             SetProxyPort(link, dest_port);
1065             SetProxyAddress(link, dest_address);
1066             ProxyModify(link, pip, maxpacketsize, proxy_type);
1067         }
1068 
1069 /* Get alias address and port */
1070         alias_port = GetAliasPort(link);
1071         alias_address = GetAliasAddress(link);
1072 
1073 /* Monitor TCP connection state */
1074         TcpMonitorOut(pip, link);
1075 
1076 /* Special processing for IP encoding protocols */
1077         if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1078          || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1079             AliasHandleFtpOut(pip, link, maxpacketsize);
1080         else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1081          || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1082             AliasHandleIrcOut(pip, link, maxpacketsize);
1083         else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1084          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1085          || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1086          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1087             AliasHandleRtspOut(pip, link, maxpacketsize);
1088         else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1089          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1090             AliasHandlePptpOut(pip, link);
1091 
1092 /* Adjust TCP checksum since source port is being aliased */
1093 /* and source address is being altered                    */
1094         accumulate  = tc->th_sport;
1095         tc->th_sport = alias_port;
1096         accumulate -= tc->th_sport;
1097 
1098         sptr = (u_short *) &(pip->ip_src);
1099         accumulate += *sptr++;
1100         accumulate += *sptr;
1101         sptr = (u_short *) &alias_address;
1102         accumulate -= *sptr++;
1103         accumulate -= *sptr;
1104 
1105 /* Modify sequence number if necessary */
1106         if (GetAckModified(link) == 1)
1107         {
1108             int delta;
1109 
1110             delta = GetDeltaSeqOut(pip, link);
1111             if (delta != 0)
1112             {
1113                 sptr = (u_short *) &tc->th_seq;
1114                 accumulate += *sptr++;
1115                 accumulate += *sptr;
1116                 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1117                 sptr = (u_short *) &tc->th_seq;
1118                 accumulate -= *sptr++;
1119                 accumulate -= *sptr;
1120             }
1121         }
1122 
1123         ADJUST_CHECKSUM(accumulate, tc->th_sum)
1124 
1125 /* Change source address */
1126         sptr = (u_short *) &(pip->ip_src);
1127         accumulate  = *sptr++;
1128         accumulate += *sptr;
1129         pip->ip_src = alias_address;
1130         sptr = (u_short *) &(pip->ip_src);
1131         accumulate -= *sptr++;
1132         accumulate -= *sptr;
1133 
1134         ADJUST_CHECKSUM(accumulate, pip->ip_sum)
1135 
1136         return(PKT_ALIAS_OK);
1137     }
1138     return(PKT_ALIAS_IGNORED);
1139 }
1140 
1141 
1142 
1143 
1144 /* Fragment Handling
1145 
1146     FragmentIn()
1147     FragmentOut()
1148 
1149 The packet aliasing module has a limited ability for handling IP
1150 fragments.  If the ICMP, TCP or UDP header is in the first fragment
1151 received, then the ID number of the IP packet is saved, and other
1152 fragments are identified according to their ID number and IP address
1153 they were sent from.  Pointers to unresolved fragments can also be
1154 saved and recalled when a header fragment is seen.
1155 */
1156 
1157 /* Local prototypes */
1158 static int FragmentIn(struct ip *);
1159 static int FragmentOut(struct ip *);
1160 
1161 
1162 static int
1163 FragmentIn(struct ip *pip)
1164 {
1165     struct alias_link *link;
1166 
1167     link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1168     if (link != NULL)
1169     {
1170         struct in_addr original_address;
1171 
1172         GetFragmentAddr(link, &original_address);
1173         DifferentialChecksum(&pip->ip_sum,
1174                              (u_short *) &original_address,
1175                              (u_short *) &pip->ip_dst,
1176                              2);
1177         pip->ip_dst = original_address;
1178 
1179         return(PKT_ALIAS_OK);
1180     }
1181     return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1182 }
1183 
1184 
1185 static int
1186 FragmentOut(struct ip *pip)
1187 {
1188     struct in_addr alias_address;
1189 
1190     alias_address = FindAliasAddress(pip->ip_src);
1191     DifferentialChecksum(&pip->ip_sum,
1192                          (u_short *) &alias_address,
1193                          (u_short *) &pip->ip_src,
1194                           2);
1195     pip->ip_src = alias_address;
1196 
1197     return(PKT_ALIAS_OK);
1198 }
1199 
1200 
1201 
1202 
1203 
1204 
1205 /* Outside World Access
1206 
1207         PacketAliasSaveFragment()
1208         PacketAliasGetFragment()
1209         PacketAliasFragmentIn()
1210         PacketAliasIn()
1211         PacketAliasOut()
1212         PacketUnaliasOut()
1213 
1214 (prototypes in alias.h)
1215 */
1216 
1217 
1218 int
1219 PacketAliasSaveFragment(char *ptr)
1220 {
1221     int iresult;
1222     struct alias_link *link;
1223     struct ip *pip;
1224 
1225     pip = (struct ip *) ptr;
1226     link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1227     iresult = PKT_ALIAS_ERROR;
1228     if (link != NULL)
1229     {
1230         SetFragmentPtr(link, ptr);
1231         iresult = PKT_ALIAS_OK;
1232     }
1233     return(iresult);
1234 }
1235 
1236 
1237 char *
1238 PacketAliasGetFragment(char *ptr)
1239 {
1240     struct alias_link *link;
1241     char *fptr;
1242     struct ip *pip;
1243 
1244     pip = (struct ip *) ptr;
1245     link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1246     if (link != NULL)
1247     {
1248         GetFragmentPtr(link, &fptr);
1249         SetFragmentPtr(link, NULL);
1250         SetExpire(link, 0); /* Deletes link */
1251 
1252         return(fptr);
1253     }
1254     else
1255     {
1256         return(NULL);
1257     }
1258 }
1259 
1260 
1261 void
1262 PacketAliasFragmentIn(char *ptr,          /* Points to correctly de-aliased
1263                                              header fragment */
1264                       char *ptr_fragment  /* Points to fragment which must
1265                                              be de-aliased   */
1266                      )
1267 {
1268     struct ip *pip;
1269     struct ip *fpip;
1270 
1271     pip = (struct ip *) ptr;
1272     fpip = (struct ip *) ptr_fragment;
1273 
1274     DifferentialChecksum(&fpip->ip_sum,
1275                          (u_short *) &pip->ip_dst,
1276                          (u_short *) &fpip->ip_dst,
1277                          2);
1278     fpip->ip_dst = pip->ip_dst;
1279 }
1280 
1281 
1282 int
1283 PacketAliasIn(char *ptr, int maxpacketsize)
1284 {
1285     struct in_addr alias_addr;
1286     struct ip *pip;
1287     int iresult;
1288 
1289     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1290         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1291         iresult = PacketAliasOut(ptr, maxpacketsize);
1292         packetAliasMode |= PKT_ALIAS_REVERSE;
1293         return iresult;
1294     }
1295 
1296     HouseKeeping();
1297     ClearCheckNewLink();
1298     pip = (struct ip *) ptr;
1299     alias_addr = pip->ip_dst;
1300 
1301     /* Defense against mangled packets */
1302     if (ntohs(pip->ip_len) > maxpacketsize
1303      || (pip->ip_hl<<2) > maxpacketsize)
1304         return PKT_ALIAS_IGNORED;
1305 
1306     iresult = PKT_ALIAS_IGNORED;
1307     if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1308     {
1309         switch (pip->ip_p)
1310         {
1311             case IPPROTO_ICMP:
1312                 iresult = IcmpAliasIn(pip);
1313                 break;
1314             case IPPROTO_UDP:
1315                 iresult = UdpAliasIn(pip);
1316                 break;
1317             case IPPROTO_TCP:
1318                 iresult = TcpAliasIn(pip);
1319                 break;
1320             case IPPROTO_GRE:
1321                 iresult = GreAliasIn(pip);
1322                 break;
1323 	    default:
1324 		iresult = ProtoAliasIn(pip);
1325                 break;
1326         }
1327 
1328         if (ntohs(pip->ip_off) & IP_MF)
1329         {
1330             struct alias_link *link;
1331 
1332             link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1333             if (link != NULL)
1334             {
1335                 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1336                 SetFragmentAddr(link, pip->ip_dst);
1337             }
1338             else
1339             {
1340                 iresult = PKT_ALIAS_ERROR;
1341             }
1342         }
1343     }
1344     else
1345     {
1346         iresult = FragmentIn(pip);
1347     }
1348 
1349     return(iresult);
1350 }
1351 
1352 
1353 
1354 /* Unregistered address ranges */
1355 
1356 /* 10.0.0.0   ->   10.255.255.255 */
1357 #define UNREG_ADDR_A_LOWER 0x0a000000
1358 #define UNREG_ADDR_A_UPPER 0x0affffff
1359 
1360 /* 172.16.0.0  ->  172.31.255.255 */
1361 #define UNREG_ADDR_B_LOWER 0xac100000
1362 #define UNREG_ADDR_B_UPPER 0xac1fffff
1363 
1364 /* 192.168.0.0 -> 192.168.255.255 */
1365 #define UNREG_ADDR_C_LOWER 0xc0a80000
1366 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1367 
1368 int
1369 PacketAliasOut(char *ptr,           /* valid IP packet */
1370                int  maxpacketsize   /* How much the packet data may grow
1371                                        (FTP and IRC inline changes) */
1372               )
1373 {
1374     int iresult;
1375     struct in_addr addr_save;
1376     struct ip *pip;
1377 
1378     if (packetAliasMode & PKT_ALIAS_REVERSE) {
1379         packetAliasMode &= ~PKT_ALIAS_REVERSE;
1380         iresult = PacketAliasIn(ptr, maxpacketsize);
1381         packetAliasMode |= PKT_ALIAS_REVERSE;
1382         return iresult;
1383     }
1384 
1385     HouseKeeping();
1386     ClearCheckNewLink();
1387     pip = (struct ip *) ptr;
1388 
1389     /* Defense against mangled packets */
1390     if (ntohs(pip->ip_len) > maxpacketsize
1391      || (pip->ip_hl<<2) > maxpacketsize)
1392         return PKT_ALIAS_IGNORED;
1393 
1394     addr_save = GetDefaultAliasAddress();
1395     if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1396     {
1397         u_long addr;
1398         int iclass;
1399 
1400         iclass = 0;
1401         addr = ntohl(pip->ip_src.s_addr);
1402         if      (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1403             iclass = 3;
1404         else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1405             iclass = 2;
1406         else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1407             iclass = 1;
1408 
1409         if (iclass == 0)
1410         {
1411             SetDefaultAliasAddress(pip->ip_src);
1412         }
1413     }
1414 
1415     iresult = PKT_ALIAS_IGNORED;
1416     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1417     {
1418         switch (pip->ip_p)
1419         {
1420             case IPPROTO_ICMP:
1421                 iresult = IcmpAliasOut(pip);
1422                 break;
1423             case IPPROTO_UDP:
1424                 iresult = UdpAliasOut(pip);
1425                 break;
1426             case IPPROTO_TCP:
1427                 iresult = TcpAliasOut(pip, maxpacketsize);
1428                 break;
1429 	    default:
1430 		iresult = ProtoAliasOut(pip);
1431                 break;
1432         }
1433     }
1434     else
1435     {
1436         iresult = FragmentOut(pip);
1437     }
1438 
1439     SetDefaultAliasAddress(addr_save);
1440     return(iresult);
1441 }
1442 
1443 int
1444 PacketUnaliasOut(char *ptr,           /* valid IP packet */
1445                  int  maxpacketsize   /* for error checking */
1446                 )
1447 {
1448     struct ip		*pip;
1449     struct icmp 	*ic;
1450     struct udphdr	*ud;
1451     struct tcphdr 	*tc;
1452     struct alias_link 	*link;
1453     int 		iresult = PKT_ALIAS_IGNORED;
1454 
1455     pip = (struct ip *) ptr;
1456 
1457     /* Defense against mangled packets */
1458     if (ntohs(pip->ip_len) > maxpacketsize
1459      || (pip->ip_hl<<2) > maxpacketsize)
1460         return(iresult);
1461 
1462     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1463     tc = (struct tcphdr *) ud;
1464     ic = (struct icmp *) ud;
1465 
1466     /* Find a link */
1467     if (pip->ip_p == IPPROTO_UDP)
1468         link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src,
1469                             ud->uh_dport, ud->uh_sport,
1470                             IPPROTO_UDP);
1471     else if (pip->ip_p == IPPROTO_TCP)
1472         link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src,
1473                             tc->th_dport, tc->th_sport,
1474                             IPPROTO_TCP);
1475     else if (pip->ip_p == IPPROTO_ICMP)
1476         link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id);
1477     else
1478         link = NULL;
1479 
1480     /* Change it from an aliased packet to an unaliased packet */
1481     if (link != NULL)
1482     {
1483         if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1484         {
1485             u_short        *sptr;
1486             int 	   accumulate;
1487             struct in_addr original_address;
1488             u_short        original_port;
1489 
1490             original_address = GetOriginalAddress(link);
1491             original_port = GetOriginalPort(link);
1492 
1493             /* Adjust TCP/UDP checksum */
1494             sptr = (u_short *) &(pip->ip_src);
1495             accumulate  = *sptr++;
1496             accumulate += *sptr;
1497             sptr = (u_short *) &original_address;
1498             accumulate -= *sptr++;
1499             accumulate -= *sptr;
1500 
1501             if (pip->ip_p == IPPROTO_UDP) {
1502                 accumulate += ud->uh_sport;
1503                 accumulate -= original_port;
1504                 ADJUST_CHECKSUM(accumulate, ud->uh_sum)
1505 	    } else {
1506                 accumulate += tc->th_sport;
1507                 accumulate -= original_port;
1508                 ADJUST_CHECKSUM(accumulate, tc->th_sum)
1509 	    }
1510 
1511             /* Adjust IP checksum */
1512             DifferentialChecksum(&pip->ip_sum,
1513                                  (u_short *) &original_address,
1514                                  (u_short *) &pip->ip_src,
1515                                  2);
1516 
1517             /* Un-alias source address and port number */
1518             pip->ip_src = original_address;
1519             if (pip->ip_p == IPPROTO_UDP)
1520                 ud->uh_sport = original_port;
1521 	    else
1522                 tc->th_sport = original_port;
1523 
1524 	    iresult = PKT_ALIAS_OK;
1525 
1526         } else if (pip->ip_p == IPPROTO_ICMP) {
1527 
1528             u_short        *sptr;
1529             int            accumulate;
1530             struct in_addr original_address;
1531             u_short        original_id;
1532 
1533             original_address = GetOriginalAddress(link);
1534             original_id = GetOriginalPort(link);
1535 
1536             /* Adjust ICMP checksum */
1537             sptr = (u_short *) &(pip->ip_src);
1538             accumulate  = *sptr++;
1539             accumulate += *sptr;
1540             sptr = (u_short *) &original_address;
1541             accumulate -= *sptr++;
1542             accumulate -= *sptr;
1543             accumulate += ic->icmp_id;
1544             accumulate -= original_id;
1545             ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
1546 
1547             /* Adjust IP checksum */
1548             DifferentialChecksum(&pip->ip_sum,
1549                                  (u_short *) &original_address,
1550                                  (u_short *) &pip->ip_src,
1551                                  2);
1552 
1553             /* Un-alias source address and port number */
1554             pip->ip_src = original_address;
1555             ic->icmp_id = original_id;
1556 
1557 	    iresult = PKT_ALIAS_OK;
1558         }
1559     }
1560     return(iresult);
1561 
1562 }
1563