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