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