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