network_cmds-511.tar.gz
[apple/network_cmds.git] / alias / alias.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*-
23 * Copyright (c) 2001 Charles Mott <cmott@scientech.com>
24 * All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 *
47 * Based upon:
48 * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.7 2001/08/21 03:50:25 brian Exp $
49 */
50
51 /*
52 Alias.c provides supervisory control for the functions of the
53 packet aliasing software. It consists of routines to monitor
54 TCP connection state, protocol-specific aliasing routines,
55 fragment handling and the following outside world functional
56 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
57 PacketAliasIn and PacketAliasOut.
58
59 The other C program files are briefly described. The data
60 structure framework which holds information needed to translate
61 packets is encapsulated in alias_db.c. Data is accessed by
62 function calls, so other segments of the program need not know
63 about the underlying data structures. Alias_ftp.c contains
64 special code for modifying the ftp PORT command used to establish
65 data connections, while alias_irc.c does the same for IRC
66 DCC. Alias_util.c contains a few utility routines.
67
68 Version 1.0 August, 1996 (cjm)
69
70 Version 1.1 August 20, 1996 (cjm)
71 PPP host accepts incoming connections for ports 0 to 1023.
72 (Gary Roberts pointed out the need to handle incoming
73 connections.)
74
75 Version 1.2 September 7, 1996 (cjm)
76 Fragment handling error in alias_db.c corrected.
77 (Tom Torrance helped fix this problem.)
78
79 Version 1.4 September 16, 1996 (cjm)
80 - A more generalized method for handling incoming
81 connections, without the 0-1023 restriction, is
82 implemented in alias_db.c
83 - Improved ICMP support in alias.c. Traceroute
84 packet streams can now be correctly aliased.
85 - TCP connection closing logic simplified in
86 alias.c and now allows for additional 1 minute
87 "grace period" after FIN or RST is observed.
88
89 Version 1.5 September 17, 1996 (cjm)
90 Corrected error in handling incoming UDP packets with 0 checksum.
91 (Tom Torrance helped fix this problem.)
92
93 Version 1.6 September 18, 1996 (cjm)
94 Simplified ICMP aliasing scheme. Should now support
95 traceroute from Win95 as well as FreeBSD.
96
97 Version 1.7 January 9, 1997 (cjm)
98 - Out-of-order fragment handling.
99 - IP checksum error fixed for ftp transfers
100 from aliasing host.
101 - Integer return codes added to all
102 aliasing/de-aliasing functions.
103 - Some obsolete comments cleaned up.
104 - Differential checksum computations for
105 IP header (TCP, UDP and ICMP were already
106 differential).
107
108 Version 2.1 May 1997 (cjm)
109 - Added support for outgoing ICMP error
110 messages.
111 - Added two functions PacketAliasIn2()
112 and PacketAliasOut2() for dynamic address
113 control (e.g. round-robin allocation of
114 incoming packets).
115
116 Version 2.2 July 1997 (cjm)
117 - Rationalized API function names to begin
118 with "PacketAlias..."
119 - Eliminated PacketAliasIn2() and
120 PacketAliasOut2() as poorly conceived.
121
122 Version 2.3 Dec 1998 (dillon)
123 - Major bounds checking additions, see FreeBSD/CVS
124
125 Version 3.1 May, 2000 (salander)
126 - Added hooks to handle PPTP.
127
128 Version 3.2 July, 2000 (salander and satoh)
129 - Added PacketUnaliasOut routine.
130 - Added hooks to handle RTSP/RTP.
131
132 See HISTORY file for additional revisions.
133 */
134
135 #include <sys/types.h>
136
137 #include <netinet/in_systm.h>
138 #include <netinet/in.h>
139 #include <netinet/ip.h>
140 #include <netinet/ip_icmp.h>
141 #include <netinet/tcp.h>
142 #include <netinet/udp.h>
143
144 #include <stdio.h>
145
146 #include "alias_local.h"
147 #include "alias.h"
148
149 #define NETBIOS_NS_PORT_NUMBER 137
150 #define NETBIOS_DGM_PORT_NUMBER 138
151 #define FTP_CONTROL_PORT_NUMBER 21
152 #define IRC_CONTROL_PORT_NUMBER_1 6667
153 #define IRC_CONTROL_PORT_NUMBER_2 6668
154 #define CUSEEME_PORT_NUMBER 7648
155 #define RTSP_CONTROL_PORT_NUMBER_1 554
156 #define RTSP_CONTROL_PORT_NUMBER_2 7070
157 #define PPTP_CONTROL_PORT_NUMBER 1723
158
159
160
161
162 /* TCP Handling Routines
163
164 TcpMonitorIn() -- These routines monitor TCP connections, and
165 TcpMonitorOut() delete a link when a connection is closed.
166
167 DoMSSClamp() -- Clamps the MSS of the given TCP header to the
168 value in packetAliasMSS.
169
170 These routines look for SYN, FIN and RST flags to determine when TCP
171 connections open and close. When a TCP connection closes, the data
172 structure containing packet aliasing information is deleted after
173 a timeout period.
174 */
175
176 /* Local prototypes */
177 static void TcpMonitorIn(struct ip *, struct alias_link *);
178
179 static void TcpMonitorOut(struct ip *, struct alias_link *);
180
181
182 static u_short packetAliasMSS;
183
184 void PacketAliasClampMSS(u_short mss)
185 {
186 packetAliasMSS = mss;
187 }
188
189 static void DoMSSClamp(struct tcphdr *tc)
190 {
191 u_char *option = (u_char *) tc + sizeof(*tc);
192 u_char *optionEnd = option + ((tc->th_off << 2) - sizeof(*tc));
193
194 #define TEST_5618045 0
195 #if TEST_5618045
196 if ((ntohs(tc->th_dport) == 8080 || ntohs(tc->th_sport) == 8080) && tc->th_off > 5) {
197 option[0] = 0xF4;
198 option[1] = 0;
199 }
200 #endif
201
202 while (optionEnd > option)
203 {
204 /* Bounds checking to avoid infinite loops */
205 if (option[0] == TCPOPT_EOL)
206 break;
207
208 if (option[0] == TCPOPT_NOP) {
209 ++option;
210 continue;
211 } else {
212 if (optionEnd - option < 2)
213 break;
214 if (option[1] < 2 || option + option[1] >= optionEnd)
215 break;
216 }
217
218 switch (option[0])
219 {
220 case TCPOPT_MAXSEG:
221 if (option[1] == 4)
222 {
223 u_short *mssPtr = (u_short *) option + 1;
224 u_short mssVal = ntohs(*mssPtr);
225
226 if (packetAliasMSS < mssVal)
227 {
228 int accumulate = mssVal;
229 int accnetorder = 0 ;
230
231 accumulate -= packetAliasMSS;
232 *mssPtr = htons(packetAliasMSS);
233 accnetorder = htons(accumulate);
234 ADJUST_CHECKSUM(accnetorder, tc->th_sum);
235 }
236
237 option = optionEnd;
238 }
239 break;
240
241 default:
242 option += option[1];
243 break;
244 }
245 }
246 }
247
248 static void
249 TcpMonitorIn(struct ip *pip, struct alias_link *link)
250 {
251 struct tcphdr *tc;
252
253 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
254
255 switch (GetStateIn(link))
256 {
257 case ALIAS_TCP_STATE_NOT_CONNECTED:
258 if (tc->th_flags & TH_RST)
259 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
260 else if (tc->th_flags & TH_SYN)
261 {
262 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
263
264 if (packetAliasMSS)
265 DoMSSClamp(tc);
266 }
267 break;
268 case ALIAS_TCP_STATE_CONNECTED:
269 if (tc->th_flags & (TH_FIN | TH_RST))
270 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
271 break;
272 }
273 }
274
275 static void
276 TcpMonitorOut(struct ip *pip, struct alias_link *link)
277 {
278 struct tcphdr *tc;
279
280 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
281
282 switch (GetStateOut(link))
283 {
284 case ALIAS_TCP_STATE_NOT_CONNECTED:
285 if (tc->th_flags & TH_RST)
286 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
287 else if (tc->th_flags & TH_SYN)
288 {
289 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
290
291 if (packetAliasMSS)
292 DoMSSClamp(tc);
293 }
294 break;
295 case ALIAS_TCP_STATE_CONNECTED:
296 if (tc->th_flags & (TH_FIN | TH_RST))
297 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
298 break;
299 }
300 }
301
302
303
304
305
306 /* Protocol Specific Packet Aliasing Routines
307
308 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
309 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
310 ProtoAliasIn(), ProtoAliasOut()
311 UdpAliasIn(), UdpAliasOut()
312 TcpAliasIn(), TcpAliasOut()
313
314 These routines handle protocol specific details of packet aliasing.
315 One may observe a certain amount of repetitive arithmetic in these
316 functions, the purpose of which is to compute a revised checksum
317 without actually summing over the entire data packet, which could be
318 unnecessarily time consuming.
319
320 The purpose of the packet aliasing routines is to replace the source
321 address of the outgoing packet and then correctly put it back for
322 any incoming packets. For TCP and UDP, ports are also re-mapped.
323
324 For ICMP echo/timestamp requests and replies, the following scheme
325 is used: the ID number is replaced by an alias for the outgoing
326 packet.
327
328 ICMP error messages are handled by looking at the IP fragment
329 in the data section of the message.
330
331 For TCP and UDP protocols, a port number is chosen for an outgoing
332 packet, and then incoming packets are identified by IP address and
333 port numbers. For TCP packets, there is additional logic in the event
334 that sequence and ACK numbers have been altered (as in the case for
335 FTP data port commands).
336
337 The port numbers used by the packet aliasing module are not true
338 ports in the Unix sense. No sockets are actually bound to ports.
339 They are more correctly thought of as placeholders.
340
341 All packets go through the aliasing mechanism, whether they come from
342 the gateway machine or other machines on a local area network.
343 */
344
345
346 /* Local prototypes */
347 static int IcmpAliasIn1(struct ip *);
348 static int IcmpAliasIn2(struct ip *);
349 static int IcmpAliasIn (struct ip *);
350
351 static int IcmpAliasOut1(struct ip *);
352 static int IcmpAliasOut2(struct ip *);
353 static int IcmpAliasOut (struct ip *);
354
355 static int ProtoAliasIn(struct ip *);
356 static int ProtoAliasOut(struct ip *);
357
358 static int UdpAliasOut(struct ip *);
359 static int UdpAliasIn (struct ip *);
360
361 static int TcpAliasOut(struct ip *, int);
362 static int TcpAliasIn (struct ip *);
363
364
365 static int
366 IcmpAliasIn1(struct ip *pip)
367 {
368 /*
369 De-alias incoming echo and timestamp replies.
370 Alias incoming echo and timestamp requests.
371 */
372 struct alias_link *link;
373 struct icmp *ic;
374
375 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
376
377 /* Get source address from ICMP data field and restore original data */
378 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
379 if (link != NULL)
380 {
381 u_short original_id;
382 int accumulate;
383
384 original_id = GetOriginalPort(link);
385
386 /* Adjust ICMP checksum */
387 accumulate = ic->icmp_id;
388 accumulate -= original_id;
389 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
390
391 /* Put original sequence number back in */
392 ic->icmp_id = original_id;
393
394 /* Put original address back into IP header */
395 {
396 struct in_addr original_address;
397
398 original_address = GetOriginalAddress(link);
399 DifferentialChecksum(&pip->ip_sum,
400 (u_short *) &original_address,
401 (u_short *) &pip->ip_dst,
402 2);
403 pip->ip_dst = original_address;
404 }
405
406 return(PKT_ALIAS_OK);
407 }
408 return(PKT_ALIAS_IGNORED);
409 }
410
411 static int
412 IcmpAliasIn2(struct ip *pip)
413 {
414 /*
415 Alias incoming ICMP error messages containing
416 IP header and first 64 bits of datagram.
417 */
418 struct ip *ip;
419 struct icmp *ic, *ic2;
420 struct udphdr *ud;
421 struct tcphdr *tc;
422 struct alias_link *link;
423
424 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
425 ip = &ic->icmp_ip;
426
427 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
428 tc = (struct tcphdr *) ud;
429 ic2 = (struct icmp *) ud;
430
431 if (ip->ip_p == IPPROTO_UDP)
432 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
433 ud->uh_dport, ud->uh_sport,
434 IPPROTO_UDP, 0);
435 else if (ip->ip_p == IPPROTO_TCP)
436 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
437 tc->th_dport, tc->th_sport,
438 IPPROTO_TCP, 0);
439 else if (ip->ip_p == IPPROTO_ICMP) {
440 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
441 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
442 else
443 link = NULL;
444 } else
445 link = NULL;
446
447 if (link != NULL)
448 {
449 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
450 {
451 u_short *sptr;
452 int accumulate;
453 struct in_addr original_address;
454 u_short original_port;
455
456 original_address = GetOriginalAddress(link);
457 original_port = GetOriginalPort(link);
458
459 /* Adjust ICMP checksum */
460 sptr = (u_short *) &(ip->ip_src);
461 accumulate = *sptr++;
462 accumulate += *sptr;
463 sptr = (u_short *) &original_address;
464 accumulate -= *sptr++;
465 accumulate -= *sptr;
466 accumulate += ud->uh_sport;
467 accumulate -= original_port;
468 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
469
470 /* Un-alias address in IP header */
471 DifferentialChecksum(&pip->ip_sum,
472 (u_short *) &original_address,
473 (u_short *) &pip->ip_dst,
474 2);
475 pip->ip_dst = original_address;
476
477 /* Un-alias address and port number of original IP packet
478 fragment contained in ICMP data section */
479 ip->ip_src = original_address;
480 ud->uh_sport = original_port;
481 }
482 else if (ip->ip_p == IPPROTO_ICMP)
483 {
484 u_short *sptr;
485 int accumulate;
486 struct in_addr original_address;
487 u_short original_id;
488
489 original_address = GetOriginalAddress(link);
490 original_id = GetOriginalPort(link);
491
492 /* Adjust ICMP checksum */
493 sptr = (u_short *) &(ip->ip_src);
494 accumulate = *sptr++;
495 accumulate += *sptr;
496 sptr = (u_short *) &original_address;
497 accumulate -= *sptr++;
498 accumulate -= *sptr;
499 accumulate += ic2->icmp_id;
500 accumulate -= original_id;
501 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
502
503 /* Un-alias address in IP header */
504 DifferentialChecksum(&pip->ip_sum,
505 (u_short *) &original_address,
506 (u_short *) &pip->ip_dst,
507 2);
508 pip->ip_dst = original_address;
509
510 /* Un-alias address of original IP packet and sequence number of
511 embedded ICMP datagram */
512 ip->ip_src = original_address;
513 ic2->icmp_id = original_id;
514 }
515 return(PKT_ALIAS_OK);
516 }
517 return(PKT_ALIAS_IGNORED);
518 }
519
520
521 static int
522 IcmpAliasIn(struct ip *pip)
523 {
524 int iresult;
525 struct icmp *ic;
526
527 /* Return if proxy-only mode is enabled */
528 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
529 return PKT_ALIAS_OK;
530
531 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
532
533 iresult = PKT_ALIAS_IGNORED;
534 switch (ic->icmp_type)
535 {
536 case ICMP_ECHOREPLY:
537 case ICMP_TSTAMPREPLY:
538 if (ic->icmp_code == 0)
539 {
540 iresult = IcmpAliasIn1(pip);
541 }
542 break;
543 case ICMP_UNREACH:
544 case ICMP_SOURCEQUENCH:
545 case ICMP_TIMXCEED:
546 case ICMP_PARAMPROB:
547 iresult = IcmpAliasIn2(pip);
548 break;
549 case ICMP_ECHO:
550 case ICMP_TSTAMP:
551 iresult = IcmpAliasIn1(pip);
552 break;
553 }
554 return(iresult);
555 }
556
557
558 static int
559 IcmpAliasOut1(struct ip *pip)
560 {
561 /*
562 Alias outgoing echo and timestamp requests.
563 De-alias outgoing echo and timestamp replies.
564 */
565 struct alias_link *link;
566 struct icmp *ic;
567
568 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
569
570 /* Save overwritten data for when echo packet returns */
571 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
572 if (link != NULL)
573 {
574 u_short alias_id;
575 int accumulate;
576
577 alias_id = GetAliasPort(link);
578
579 /* Since data field is being modified, adjust ICMP checksum */
580 accumulate = ic->icmp_id;
581 accumulate -= alias_id;
582 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
583
584 /* Alias sequence number */
585 ic->icmp_id = alias_id;
586
587 /* Change source address */
588 {
589 struct in_addr alias_address;
590
591 alias_address = GetAliasAddress(link);
592 DifferentialChecksum(&pip->ip_sum,
593 (u_short *) &alias_address,
594 (u_short *) &pip->ip_src,
595 2);
596 pip->ip_src = alias_address;
597 }
598
599 return(PKT_ALIAS_OK);
600 }
601 return(PKT_ALIAS_IGNORED);
602 }
603
604
605 static int
606 IcmpAliasOut2(struct ip *pip)
607 {
608 /*
609 Alias outgoing ICMP error messages containing
610 IP header and first 64 bits of datagram.
611 */
612 struct ip *ip;
613 struct icmp *ic, *ic2;
614 struct udphdr *ud;
615 struct tcphdr *tc;
616 struct alias_link *link;
617
618 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
619 ip = &ic->icmp_ip;
620
621 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
622 tc = (struct tcphdr *) ud;
623 ic2 = (struct icmp *) ud;
624
625 if (ip->ip_p == IPPROTO_UDP)
626 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
627 ud->uh_dport, ud->uh_sport,
628 IPPROTO_UDP, 0);
629 else if (ip->ip_p == IPPROTO_TCP)
630 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
631 tc->th_dport, tc->th_sport,
632 IPPROTO_TCP, 0);
633 else if (ip->ip_p == IPPROTO_ICMP) {
634 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
635 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
636 else
637 link = NULL;
638 } else
639 link = NULL;
640
641 if (link != NULL)
642 {
643 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
644 {
645 u_short *sptr;
646 int accumulate;
647 struct in_addr alias_address;
648 u_short alias_port;
649
650 alias_address = GetAliasAddress(link);
651 alias_port = GetAliasPort(link);
652
653 /* Adjust ICMP checksum */
654 sptr = (u_short *) &(ip->ip_dst);
655 accumulate = *sptr++;
656 accumulate += *sptr;
657 sptr = (u_short *) &alias_address;
658 accumulate -= *sptr++;
659 accumulate -= *sptr;
660 accumulate += ud->uh_dport;
661 accumulate -= alias_port;
662 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
663
664 /*
665 * Alias address in IP header if it comes from the host
666 * the original TCP/UDP packet was destined for.
667 */
668 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
669 DifferentialChecksum(&pip->ip_sum,
670 (u_short *) &alias_address,
671 (u_short *) &pip->ip_src,
672 2);
673 pip->ip_src = alias_address;
674 }
675
676 /* Alias address and port number of original IP packet
677 fragment contained in ICMP data section */
678 ip->ip_dst = alias_address;
679 ud->uh_dport = alias_port;
680 }
681 else if (ip->ip_p == IPPROTO_ICMP)
682 {
683 u_short *sptr;
684 int accumulate;
685 struct in_addr alias_address;
686 u_short alias_id;
687
688 alias_address = GetAliasAddress(link);
689 alias_id = GetAliasPort(link);
690
691 /* Adjust ICMP checksum */
692 sptr = (u_short *) &(ip->ip_dst);
693 accumulate = *sptr++;
694 accumulate += *sptr;
695 sptr = (u_short *) &alias_address;
696 accumulate -= *sptr++;
697 accumulate -= *sptr;
698 accumulate += ic2->icmp_id;
699 accumulate -= alias_id;
700 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
701
702 /*
703 * Alias address in IP header if it comes from the host
704 * the original ICMP message was destined for.
705 */
706 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
707 DifferentialChecksum(&pip->ip_sum,
708 (u_short *) &alias_address,
709 (u_short *) &pip->ip_src,
710 2);
711 pip->ip_src = alias_address;
712 }
713
714 /* Alias address of original IP packet and sequence number of
715 embedded ICMP datagram */
716 ip->ip_dst = alias_address;
717 ic2->icmp_id = alias_id;
718 }
719 return(PKT_ALIAS_OK);
720 }
721 return(PKT_ALIAS_IGNORED);
722 }
723
724
725 static int
726 IcmpAliasOut(struct ip *pip)
727 {
728 int iresult;
729 struct icmp *ic;
730
731 /* Return if proxy-only mode is enabled */
732 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
733 return PKT_ALIAS_OK;
734
735 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
736
737 iresult = PKT_ALIAS_IGNORED;
738 switch (ic->icmp_type)
739 {
740 case ICMP_ECHO:
741 case ICMP_TSTAMP:
742 if (ic->icmp_code == 0)
743 {
744 iresult = IcmpAliasOut1(pip);
745 }
746 break;
747 case ICMP_UNREACH:
748 case ICMP_SOURCEQUENCH:
749 case ICMP_TIMXCEED:
750 case ICMP_PARAMPROB:
751 iresult = IcmpAliasOut2(pip);
752 break;
753 case ICMP_ECHOREPLY:
754 case ICMP_TSTAMPREPLY:
755 iresult = IcmpAliasOut1(pip);
756 }
757 return(iresult);
758 }
759
760
761
762 static int
763 ProtoAliasIn(struct ip *pip)
764 {
765 /*
766 Handle incoming IP packets. The
767 only thing which is done in this case is to alias
768 the dest IP address of the packet to our inside
769 machine.
770 */
771 struct alias_link *link;
772
773 /* Return if proxy-only mode is enabled */
774 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
775 return PKT_ALIAS_OK;
776
777 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
778 if (link != NULL)
779 {
780 struct in_addr original_address;
781
782 original_address = GetOriginalAddress(link);
783
784 /* Restore original IP address */
785 DifferentialChecksum(&pip->ip_sum,
786 (u_short *) &original_address,
787 (u_short *) &pip->ip_dst,
788 2);
789 pip->ip_dst = original_address;
790
791 return(PKT_ALIAS_OK);
792 }
793 return(PKT_ALIAS_IGNORED);
794 }
795
796
797 static int
798 ProtoAliasOut(struct ip *pip)
799 {
800 /*
801 Handle outgoing IP packets. The
802 only thing which is done in this case is to alias
803 the source IP address of the packet.
804 */
805 struct alias_link *link;
806
807 /* Return if proxy-only mode is enabled */
808 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
809 return PKT_ALIAS_OK;
810
811 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
812 if (link != NULL)
813 {
814 struct in_addr alias_address;
815
816 alias_address = GetAliasAddress(link);
817
818 /* Change source address */
819 DifferentialChecksum(&pip->ip_sum,
820 (u_short *) &alias_address,
821 (u_short *) &pip->ip_src,
822 2);
823 pip->ip_src = alias_address;
824
825 return(PKT_ALIAS_OK);
826 }
827 return(PKT_ALIAS_IGNORED);
828 }
829
830
831 static int
832 UdpAliasIn(struct ip *pip)
833 {
834 struct udphdr *ud;
835 struct alias_link *link;
836
837 /* Return if proxy-only mode is enabled */
838 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
839 return PKT_ALIAS_OK;
840
841 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
842
843 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
844 ud->uh_sport, ud->uh_dport,
845 IPPROTO_UDP, 1);
846 if (link != NULL)
847 {
848 struct in_addr alias_address;
849 struct in_addr original_address;
850 u_short alias_port;
851 int accumulate;
852 u_short *sptr;
853 int r = 0;
854
855 alias_address = GetAliasAddress(link);
856 original_address = GetOriginalAddress(link);
857 alias_port = ud->uh_dport;
858 ud->uh_dport = GetOriginalPort(link);
859
860 /* Special processing for IP encoding protocols */
861 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
862 AliasHandleCUSeeMeIn(pip, original_address);
863 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
864 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
865 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
866 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
867 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
868 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
869 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
870 &original_address, &ud->uh_dport);
871
872 /* If UDP checksum is not zero, then adjust since destination port */
873 /* is being unaliased and destination address is being altered. */
874 if (ud->uh_sum != 0)
875 {
876 accumulate = alias_port;
877 accumulate -= ud->uh_dport;
878 sptr = (u_short *) &alias_address;
879 accumulate += *sptr++;
880 accumulate += *sptr;
881 sptr = (u_short *) &original_address;
882 accumulate -= *sptr++;
883 accumulate -= *sptr;
884 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
885 }
886
887 /* Restore original IP address */
888 DifferentialChecksum(&pip->ip_sum,
889 (u_short *) &original_address,
890 (u_short *) &pip->ip_dst,
891 2);
892 pip->ip_dst = original_address;
893
894 /*
895 * If we cannot figure out the packet, ignore it.
896 */
897 if (r < 0)
898 return(PKT_ALIAS_IGNORED);
899 else
900 return(PKT_ALIAS_OK);
901 }
902 return(PKT_ALIAS_IGNORED);
903 }
904
905 static int
906 UdpAliasOut(struct ip *pip)
907 {
908 struct udphdr *ud;
909 struct alias_link *link;
910
911 /* Return if proxy-only mode is enabled */
912 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
913 return PKT_ALIAS_OK;
914
915 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
916
917 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
918 ud->uh_sport, ud->uh_dport,
919 IPPROTO_UDP, 1);
920 if (link != NULL)
921 {
922 u_short alias_port;
923 struct in_addr alias_address;
924
925 alias_address = GetAliasAddress(link);
926 alias_port = GetAliasPort(link);
927
928 /* Special processing for IP encoding protocols */
929 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
930 AliasHandleCUSeeMeOut(pip, link);
931 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
932 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
933 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
934 AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
935 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
936 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
937 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
938 &alias_address, &alias_port);
939
940 /* If UDP checksum is not zero, adjust since source port is */
941 /* being aliased and source address is being altered */
942 if (ud->uh_sum != 0)
943 {
944 int accumulate;
945 u_short *sptr;
946
947 accumulate = ud->uh_sport;
948 accumulate -= alias_port;
949 sptr = (u_short *) &(pip->ip_src);
950 accumulate += *sptr++;
951 accumulate += *sptr;
952 sptr = (u_short *) &alias_address;
953 accumulate -= *sptr++;
954 accumulate -= *sptr;
955 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
956 }
957
958 /* Put alias port in UDP header */
959 ud->uh_sport = alias_port;
960
961 /* Change source address */
962 DifferentialChecksum(&pip->ip_sum,
963 (u_short *) &alias_address,
964 (u_short *) &pip->ip_src,
965 2);
966 pip->ip_src = alias_address;
967
968 return(PKT_ALIAS_OK);
969 }
970 return(PKT_ALIAS_IGNORED);
971 }
972
973
974
975 static int
976 TcpAliasIn(struct ip *pip)
977 {
978 struct tcphdr *tc;
979 struct alias_link *link;
980
981 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
982
983 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
984 tc->th_sport, tc->th_dport,
985 IPPROTO_TCP,
986 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
987 if (link != NULL)
988 {
989 struct in_addr alias_address;
990 struct in_addr original_address;
991 struct in_addr proxy_address;
992 u_short alias_port;
993 u_short proxy_port;
994 int accumulate;
995 u_short *sptr;
996
997 /* Special processing for IP encoding protocols */
998 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
999 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1000 AliasHandlePptpIn(pip, link);
1001
1002 alias_address = GetAliasAddress(link);
1003 original_address = GetOriginalAddress(link);
1004 proxy_address = GetProxyAddress(link);
1005 alias_port = tc->th_dport;
1006 tc->th_dport = GetOriginalPort(link);
1007 proxy_port = GetProxyPort(link);
1008
1009 /* Adjust TCP checksum since destination port is being unaliased */
1010 /* and destination port is being altered. */
1011 accumulate = alias_port;
1012 accumulate -= tc->th_dport;
1013 sptr = (u_short *) &alias_address;
1014 accumulate += *sptr++;
1015 accumulate += *sptr;
1016 sptr = (u_short *) &original_address;
1017 accumulate -= *sptr++;
1018 accumulate -= *sptr;
1019
1020 /* If this is a proxy, then modify the TCP source port and
1021 checksum accumulation */
1022 if (proxy_port != 0)
1023 {
1024 accumulate += tc->th_sport;
1025 tc->th_sport = proxy_port;
1026 accumulate -= tc->th_sport;
1027
1028 sptr = (u_short *) &pip->ip_src;
1029 accumulate += *sptr++;
1030 accumulate += *sptr;
1031 sptr = (u_short *) &proxy_address;
1032 accumulate -= *sptr++;
1033 accumulate -= *sptr;
1034 }
1035
1036 /* See if ACK number needs to be modified */
1037 if (GetAckModified(link) == 1)
1038 {
1039 int delta;
1040
1041 delta = GetDeltaAckIn(pip, link);
1042 if (delta != 0)
1043 {
1044 sptr = (u_short *) &tc->th_ack;
1045 accumulate += *sptr++;
1046 accumulate += *sptr;
1047 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
1048 sptr = (u_short *) &tc->th_ack;
1049 accumulate -= *sptr++;
1050 accumulate -= *sptr;
1051 }
1052 }
1053
1054 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1055
1056 /* Restore original IP address */
1057 sptr = (u_short *) &pip->ip_dst;
1058 accumulate = *sptr++;
1059 accumulate += *sptr;
1060 pip->ip_dst = original_address;
1061 sptr = (u_short *) &pip->ip_dst;
1062 accumulate -= *sptr++;
1063 accumulate -= *sptr;
1064
1065 /* If this is a transparent proxy packet, then modify the source
1066 address */
1067 if (proxy_address.s_addr != 0)
1068 {
1069 sptr = (u_short *) &pip->ip_src;
1070 accumulate += *sptr++;
1071 accumulate += *sptr;
1072 pip->ip_src = proxy_address;
1073 sptr = (u_short *) &pip->ip_src;
1074 accumulate -= *sptr++;
1075 accumulate -= *sptr;
1076 }
1077
1078 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1079
1080 /* Monitor TCP connection state */
1081 TcpMonitorIn(pip, link);
1082
1083 return(PKT_ALIAS_OK);
1084 }
1085 return(PKT_ALIAS_IGNORED);
1086 }
1087
1088 static int
1089 TcpAliasOut(struct ip *pip, int maxpacketsize)
1090 {
1091 int proxy_type;
1092 u_short dest_port;
1093 u_short proxy_server_port;
1094 struct in_addr dest_address;
1095 struct in_addr proxy_server_address;
1096 struct tcphdr *tc;
1097 struct alias_link *link;
1098
1099 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1100
1101 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1102
1103 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1104 return PKT_ALIAS_OK;
1105
1106 /* If this is a transparent proxy, save original destination,
1107 then alter the destination and adjust checksums */
1108 dest_port = tc->th_dport;
1109 dest_address = pip->ip_dst;
1110 if (proxy_type != 0)
1111 {
1112 int accumulate;
1113 u_short *sptr;
1114
1115 accumulate = tc->th_dport;
1116 tc->th_dport = proxy_server_port;
1117 accumulate -= tc->th_dport;
1118
1119 sptr = (u_short *) &(pip->ip_dst);
1120 accumulate += *sptr++;
1121 accumulate += *sptr;
1122 sptr = (u_short *) &proxy_server_address;
1123 accumulate -= *sptr++;
1124 accumulate -= *sptr;
1125
1126 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1127
1128 sptr = (u_short *) &(pip->ip_dst);
1129 accumulate = *sptr++;
1130 accumulate += *sptr;
1131 pip->ip_dst = proxy_server_address;
1132 sptr = (u_short *) &(pip->ip_dst);
1133 accumulate -= *sptr++;
1134 accumulate -= *sptr;
1135
1136 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1137 }
1138
1139 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1140 tc->th_sport, tc->th_dport,
1141 IPPROTO_TCP, 1);
1142 if (link !=NULL)
1143 {
1144 u_short alias_port;
1145 struct in_addr alias_address;
1146 int accumulate;
1147 u_short *sptr;
1148
1149 /* Save original destination address, if this is a proxy packet.
1150 Also modify packet to include destination encoding. */
1151 if (proxy_type != 0)
1152 {
1153 SetProxyPort(link, dest_port);
1154 SetProxyAddress(link, dest_address);
1155 ProxyModify(link, pip, maxpacketsize, proxy_type);
1156 }
1157
1158 /* Get alias address and port */
1159 alias_port = GetAliasPort(link);
1160 alias_address = GetAliasAddress(link);
1161
1162 /* Monitor TCP connection state */
1163 TcpMonitorOut(pip, link);
1164
1165 /* Special processing for IP encoding protocols */
1166 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1167 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1168 AliasHandleFtpOut(pip, link, maxpacketsize);
1169 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1170 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1171 AliasHandleIrcOut(pip, link, maxpacketsize);
1172 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1173 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1174 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1175 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1176 AliasHandleRtspOut(pip, link, maxpacketsize);
1177 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1178 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1179 AliasHandlePptpOut(pip, link);
1180
1181 /* Adjust TCP checksum since source port is being aliased */
1182 /* and source address is being altered */
1183 accumulate = tc->th_sport;
1184 tc->th_sport = alias_port;
1185 accumulate -= tc->th_sport;
1186
1187 sptr = (u_short *) &(pip->ip_src);
1188 accumulate += *sptr++;
1189 accumulate += *sptr;
1190 sptr = (u_short *) &alias_address;
1191 accumulate -= *sptr++;
1192 accumulate -= *sptr;
1193
1194 /* Modify sequence number if necessary */
1195 if (GetAckModified(link) == 1)
1196 {
1197 int delta;
1198
1199 delta = GetDeltaSeqOut(pip, link);
1200 if (delta != 0)
1201 {
1202 sptr = (u_short *) &tc->th_seq;
1203 accumulate += *sptr++;
1204 accumulate += *sptr;
1205 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1206 sptr = (u_short *) &tc->th_seq;
1207 accumulate -= *sptr++;
1208 accumulate -= *sptr;
1209 }
1210 }
1211
1212 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1213
1214 /* Change source address */
1215 sptr = (u_short *) &(pip->ip_src);
1216 accumulate = *sptr++;
1217 accumulate += *sptr;
1218 pip->ip_src = alias_address;
1219 sptr = (u_short *) &(pip->ip_src);
1220 accumulate -= *sptr++;
1221 accumulate -= *sptr;
1222
1223 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1224
1225 return(PKT_ALIAS_OK);
1226 }
1227 return(PKT_ALIAS_IGNORED);
1228 }
1229
1230
1231
1232
1233 /* Fragment Handling
1234
1235 FragmentIn()
1236 FragmentOut()
1237
1238 The packet aliasing module has a limited ability for handling IP
1239 fragments. If the ICMP, TCP or UDP header is in the first fragment
1240 received, then the ID number of the IP packet is saved, and other
1241 fragments are identified according to their ID number and IP address
1242 they were sent from. Pointers to unresolved fragments can also be
1243 saved and recalled when a header fragment is seen.
1244 */
1245
1246 /* Local prototypes */
1247 static int FragmentIn(struct ip *);
1248 static int FragmentOut(struct ip *);
1249
1250
1251 static int
1252 FragmentIn(struct ip *pip)
1253 {
1254 struct alias_link *link;
1255
1256 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1257 if (link != NULL)
1258 {
1259 struct in_addr original_address;
1260
1261 GetFragmentAddr(link, &original_address);
1262 DifferentialChecksum(&pip->ip_sum,
1263 (u_short *) &original_address,
1264 (u_short *) &pip->ip_dst,
1265 2);
1266 pip->ip_dst = original_address;
1267
1268 return(PKT_ALIAS_OK);
1269 }
1270 return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1271 }
1272
1273
1274 static int
1275 FragmentOut(struct ip *pip)
1276 {
1277 struct in_addr alias_address;
1278
1279 alias_address = FindAliasAddress(pip->ip_src);
1280 DifferentialChecksum(&pip->ip_sum,
1281 (u_short *) &alias_address,
1282 (u_short *) &pip->ip_src,
1283 2);
1284 pip->ip_src = alias_address;
1285
1286 return(PKT_ALIAS_OK);
1287 }
1288
1289
1290
1291
1292
1293
1294 /* Outside World Access
1295
1296 PacketAliasSaveFragment()
1297 PacketAliasGetFragment()
1298 PacketAliasFragmentIn()
1299 PacketAliasIn()
1300 PacketAliasOut()
1301 PacketUnaliasOut()
1302
1303 (prototypes in alias.h)
1304 */
1305
1306
1307 int
1308 PacketAliasSaveFragment(char *ptr)
1309 {
1310 int iresult;
1311 struct alias_link *link;
1312 struct ip *pip;
1313
1314 pip = (struct ip *) ptr;
1315 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1316 iresult = PKT_ALIAS_ERROR;
1317 if (link != NULL)
1318 {
1319 SetFragmentPtr(link, ptr);
1320 iresult = PKT_ALIAS_OK;
1321 }
1322 return(iresult);
1323 }
1324
1325
1326 char *
1327 PacketAliasGetFragment(char *ptr)
1328 {
1329 struct alias_link *link;
1330 char *fptr;
1331 struct ip *pip;
1332
1333 pip = (struct ip *) ptr;
1334 link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1335 if (link != NULL)
1336 {
1337 GetFragmentPtr(link, &fptr);
1338 SetFragmentPtr(link, NULL);
1339 SetExpire(link, 0); /* Deletes link */
1340
1341 return(fptr);
1342 }
1343 else
1344 {
1345 return(NULL);
1346 }
1347 }
1348
1349
1350 void
1351 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased
1352 header fragment */
1353 char *ptr_fragment /* Points to fragment which must
1354 be de-aliased */
1355 )
1356 {
1357 struct ip *pip;
1358 struct ip *fpip;
1359
1360 pip = (struct ip *) ptr;
1361 fpip = (struct ip *) ptr_fragment;
1362
1363 DifferentialChecksum(&fpip->ip_sum,
1364 (u_short *) &pip->ip_dst,
1365 (u_short *) &fpip->ip_dst,
1366 2);
1367 fpip->ip_dst = pip->ip_dst;
1368 }
1369
1370
1371 int
1372 PacketAliasIn(char *ptr, int maxpacketsize)
1373 {
1374 struct in_addr alias_addr;
1375 struct ip *pip;
1376 int iresult;
1377
1378 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1379 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1380 iresult = PacketAliasOut(ptr, maxpacketsize);
1381 packetAliasMode |= PKT_ALIAS_REVERSE;
1382 return iresult;
1383 }
1384
1385 HouseKeeping();
1386 ClearCheckNewLink();
1387 pip = (struct ip *) ptr;
1388 alias_addr = pip->ip_dst;
1389
1390 /* Defense against mangled packets */
1391 if (ntohs(pip->ip_len) > maxpacketsize
1392 || (pip->ip_hl<<2) > maxpacketsize)
1393 return PKT_ALIAS_IGNORED;
1394
1395 iresult = PKT_ALIAS_IGNORED;
1396 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1397 {
1398 switch (pip->ip_p)
1399 {
1400 case IPPROTO_ICMP:
1401 iresult = IcmpAliasIn(pip);
1402 break;
1403 case IPPROTO_UDP:
1404 iresult = UdpAliasIn(pip);
1405 break;
1406 case IPPROTO_TCP:
1407 iresult = TcpAliasIn(pip);
1408 break;
1409 case IPPROTO_GRE:
1410 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1411 AliasHandlePptpGreIn(pip) == 0)
1412 iresult = PKT_ALIAS_OK;
1413 else
1414 iresult = ProtoAliasIn(pip);
1415 break;
1416 default:
1417 iresult = ProtoAliasIn(pip);
1418 break;
1419 }
1420
1421 if (ntohs(pip->ip_off) & IP_MF)
1422 {
1423 struct alias_link *link;
1424
1425 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1426 if (link != NULL)
1427 {
1428 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1429 SetFragmentAddr(link, pip->ip_dst);
1430 }
1431 else
1432 {
1433 iresult = PKT_ALIAS_ERROR;
1434 }
1435 }
1436 }
1437 else
1438 {
1439 iresult = FragmentIn(pip);
1440 }
1441
1442 return(iresult);
1443 }
1444
1445
1446
1447 /* Unregistered address ranges */
1448
1449 /* 10.0.0.0 -> 10.255.255.255 */
1450 #define UNREG_ADDR_A_LOWER 0x0a000000
1451 #define UNREG_ADDR_A_UPPER 0x0affffff
1452
1453 /* 172.16.0.0 -> 172.31.255.255 */
1454 #define UNREG_ADDR_B_LOWER 0xac100000
1455 #define UNREG_ADDR_B_UPPER 0xac1fffff
1456
1457 /* 192.168.0.0 -> 192.168.255.255 */
1458 #define UNREG_ADDR_C_LOWER 0xc0a80000
1459 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1460
1461 int
1462 PacketAliasOut(char *ptr, /* valid IP packet */
1463 int maxpacketsize /* How much the packet data may grow
1464 (FTP and IRC inline changes) */
1465 )
1466 {
1467 int iresult;
1468 struct in_addr addr_save;
1469 struct ip *pip;
1470
1471 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1472 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1473 iresult = PacketAliasIn(ptr, maxpacketsize);
1474 packetAliasMode |= PKT_ALIAS_REVERSE;
1475 return iresult;
1476 }
1477
1478 HouseKeeping();
1479 ClearCheckNewLink();
1480 pip = (struct ip *) ptr;
1481
1482 /* Defense against mangled packets */
1483 if (ntohs(pip->ip_len) > maxpacketsize
1484 || (pip->ip_hl<<2) > maxpacketsize)
1485 return PKT_ALIAS_IGNORED;
1486
1487 addr_save = GetDefaultAliasAddress();
1488 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1489 {
1490 in_addr_t addr;
1491 int iclass;
1492
1493 iclass = 0;
1494 addr = ntohl(pip->ip_src.s_addr);
1495 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1496 iclass = 3;
1497 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1498 iclass = 2;
1499 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1500 iclass = 1;
1501
1502 if (iclass == 0)
1503 {
1504 SetDefaultAliasAddress(pip->ip_src);
1505 }
1506 }
1507
1508 iresult = PKT_ALIAS_IGNORED;
1509 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1510 {
1511 switch (pip->ip_p)
1512 {
1513 case IPPROTO_ICMP:
1514 iresult = IcmpAliasOut(pip);
1515 break;
1516 case IPPROTO_UDP:
1517 iresult = UdpAliasOut(pip);
1518 break;
1519 case IPPROTO_TCP:
1520 iresult = TcpAliasOut(pip, maxpacketsize);
1521 break;
1522 case IPPROTO_GRE:
1523 if (AliasHandlePptpGreOut(pip) == 0)
1524 iresult = PKT_ALIAS_OK;
1525 else
1526 iresult = ProtoAliasOut(pip);
1527 break;
1528 default:
1529 iresult = ProtoAliasOut(pip);
1530 break;
1531 }
1532 }
1533 else
1534 {
1535 iresult = FragmentOut(pip);
1536 }
1537
1538 SetDefaultAliasAddress(addr_save);
1539 return(iresult);
1540 }
1541
1542 int
1543 PacketUnaliasOut(char *ptr, /* valid IP packet */
1544 int maxpacketsize /* for error checking */
1545 )
1546 {
1547 struct ip *pip;
1548 struct icmp *ic;
1549 struct udphdr *ud;
1550 struct tcphdr *tc;
1551 struct alias_link *link;
1552 int iresult = PKT_ALIAS_IGNORED;
1553
1554 pip = (struct ip *) ptr;
1555
1556 /* Defense against mangled packets */
1557 if (ntohs(pip->ip_len) > maxpacketsize
1558 || (pip->ip_hl<<2) > maxpacketsize)
1559 return(iresult);
1560
1561 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1562 tc = (struct tcphdr *) ud;
1563 ic = (struct icmp *) ud;
1564
1565 /* Find a link */
1566 if (pip->ip_p == IPPROTO_UDP)
1567 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1568 ud->uh_dport, ud->uh_sport,
1569 IPPROTO_UDP, 0);
1570 else if (pip->ip_p == IPPROTO_TCP)
1571 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1572 tc->th_dport, tc->th_sport,
1573 IPPROTO_TCP, 0);
1574 else if (pip->ip_p == IPPROTO_ICMP)
1575 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1576 else
1577 link = NULL;
1578
1579 /* Change it from an aliased packet to an unaliased packet */
1580 if (link != NULL)
1581 {
1582 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1583 {
1584 u_short *sptr;
1585 int accumulate;
1586 struct in_addr original_address;
1587 u_short original_port;
1588
1589 original_address = GetOriginalAddress(link);
1590 original_port = GetOriginalPort(link);
1591
1592 /* Adjust TCP/UDP checksum */
1593 sptr = (u_short *) &(pip->ip_src);
1594 accumulate = *sptr++;
1595 accumulate += *sptr;
1596 sptr = (u_short *) &original_address;
1597 accumulate -= *sptr++;
1598 accumulate -= *sptr;
1599
1600 if (pip->ip_p == IPPROTO_UDP) {
1601 accumulate += ud->uh_sport;
1602 accumulate -= original_port;
1603 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1604 } else {
1605 accumulate += tc->th_sport;
1606 accumulate -= original_port;
1607 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1608 }
1609
1610 /* Adjust IP checksum */
1611 DifferentialChecksum(&pip->ip_sum,
1612 (u_short *) &original_address,
1613 (u_short *) &pip->ip_src,
1614 2);
1615
1616 /* Un-alias source address and port number */
1617 pip->ip_src = original_address;
1618 if (pip->ip_p == IPPROTO_UDP)
1619 ud->uh_sport = original_port;
1620 else
1621 tc->th_sport = original_port;
1622
1623 iresult = PKT_ALIAS_OK;
1624
1625 } else if (pip->ip_p == IPPROTO_ICMP) {
1626
1627 u_short *sptr;
1628 int accumulate;
1629 struct in_addr original_address;
1630 u_short original_id;
1631
1632 original_address = GetOriginalAddress(link);
1633 original_id = GetOriginalPort(link);
1634
1635 /* Adjust ICMP checksum */
1636 sptr = (u_short *) &(pip->ip_src);
1637 accumulate = *sptr++;
1638 accumulate += *sptr;
1639 sptr = (u_short *) &original_address;
1640 accumulate -= *sptr++;
1641 accumulate -= *sptr;
1642 accumulate += ic->icmp_id;
1643 accumulate -= original_id;
1644 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1645
1646 /* Adjust IP checksum */
1647 DifferentialChecksum(&pip->ip_sum,
1648 (u_short *) &original_address,
1649 (u_short *) &pip->ip_src,
1650 2);
1651
1652 /* Un-alias source address and port number */
1653 pip->ip_src = original_address;
1654 ic->icmp_id = original_id;
1655
1656 iresult = PKT_ALIAS_OK;
1657 }
1658 }
1659 return(iresult);
1660
1661 }