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