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