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