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