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