]> git.saurik.com Git - apple/network_cmds.git/blob - alias/alias.c
network_cmds-245.12.tar.gz
[apple/network_cmds.git] / alias / alias.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*-
23 * Copyright (c) 2001 Charles Mott <cmott@scientech.com>
24 * All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 *
47 * Based upon:
48 * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.7 2001/08/21 03:50:25 brian Exp $
49 */
50
51 /*
52 Alias.c provides supervisory control for the functions of the
53 packet aliasing software. It consists of routines to monitor
54 TCP connection state, protocol-specific aliasing routines,
55 fragment handling and the following outside world functional
56 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
57 PacketAliasIn and PacketAliasOut.
58
59 The other C program files are briefly described. The data
60 structure framework which holds information needed to translate
61 packets is encapsulated in alias_db.c. Data is accessed by
62 function calls, so other segments of the program need not know
63 about the underlying data structures. Alias_ftp.c contains
64 special code for modifying the ftp PORT command used to establish
65 data connections, while alias_irc.c does the same for IRC
66 DCC. Alias_util.c contains a few utility routines.
67
68 Version 1.0 August, 1996 (cjm)
69
70 Version 1.1 August 20, 1996 (cjm)
71 PPP host accepts incoming connections for ports 0 to 1023.
72 (Gary Roberts pointed out the need to handle incoming
73 connections.)
74
75 Version 1.2 September 7, 1996 (cjm)
76 Fragment handling error in alias_db.c corrected.
77 (Tom Torrance helped fix this problem.)
78
79 Version 1.4 September 16, 1996 (cjm)
80 - A more generalized method for handling incoming
81 connections, without the 0-1023 restriction, is
82 implemented in alias_db.c
83 - Improved ICMP support in alias.c. Traceroute
84 packet streams can now be correctly aliased.
85 - TCP connection closing logic simplified in
86 alias.c and now allows for additional 1 minute
87 "grace period" after FIN or RST is observed.
88
89 Version 1.5 September 17, 1996 (cjm)
90 Corrected error in handling incoming UDP packets with 0 checksum.
91 (Tom Torrance helped fix this problem.)
92
93 Version 1.6 September 18, 1996 (cjm)
94 Simplified ICMP aliasing scheme. Should now support
95 traceroute from Win95 as well as FreeBSD.
96
97 Version 1.7 January 9, 1997 (cjm)
98 - Out-of-order fragment handling.
99 - IP checksum error fixed for ftp transfers
100 from aliasing host.
101 - Integer return codes added to all
102 aliasing/de-aliasing functions.
103 - Some obsolete comments cleaned up.
104 - Differential checksum computations for
105 IP header (TCP, UDP and ICMP were already
106 differential).
107
108 Version 2.1 May 1997 (cjm)
109 - Added support for outgoing ICMP error
110 messages.
111 - Added two functions PacketAliasIn2()
112 and PacketAliasOut2() for dynamic address
113 control (e.g. round-robin allocation of
114 incoming packets).
115
116 Version 2.2 July 1997 (cjm)
117 - Rationalized API function names to begin
118 with "PacketAlias..."
119 - Eliminated PacketAliasIn2() and
120 PacketAliasOut2() as poorly conceived.
121
122 Version 2.3 Dec 1998 (dillon)
123 - Major bounds checking additions, see FreeBSD/CVS
124
125 Version 3.1 May, 2000 (salander)
126 - Added hooks to handle PPTP.
127
128 Version 3.2 July, 2000 (salander and satoh)
129 - Added PacketUnaliasOut routine.
130 - Added hooks to handle RTSP/RTP.
131
132 See HISTORY file for additional revisions.
133 */
134
135 #include <sys/types.h>
136
137 #include <netinet/in_systm.h>
138 #include <netinet/in.h>
139 #include <netinet/ip.h>
140 #include <netinet/ip_icmp.h>
141 #include <netinet/tcp.h>
142 #include <netinet/udp.h>
143
144 #include <stdio.h>
145
146 #include "alias_local.h"
147 #include "alias.h"
148
149 #define NETBIOS_NS_PORT_NUMBER 137
150 #define NETBIOS_DGM_PORT_NUMBER 138
151 #define FTP_CONTROL_PORT_NUMBER 21
152 #define IRC_CONTROL_PORT_NUMBER_1 6667
153 #define IRC_CONTROL_PORT_NUMBER_2 6668
154 #define CUSEEME_PORT_NUMBER 7648
155 #define RTSP_CONTROL_PORT_NUMBER_1 554
156 #define RTSP_CONTROL_PORT_NUMBER_2 7070
157 #define PPTP_CONTROL_PORT_NUMBER 1723
158
159
160
161
162 /* TCP Handling Routines
163
164 TcpMonitorIn() -- These routines monitor TCP connections, and
165 TcpMonitorOut() delete a link when a connection is closed.
166
167 DoMSSClamp() -- Clamps the MSS of the given TCP header to the
168 value in packetAliasMSS.
169
170 These routines look for SYN, FIN and RST flags to determine when TCP
171 connections open and close. When a TCP connection closes, the data
172 structure containing packet aliasing information is deleted after
173 a timeout period.
174 */
175
176 /* Local prototypes */
177 static void TcpMonitorIn(struct ip *, struct alias_link *);
178
179 static void TcpMonitorOut(struct ip *, struct alias_link *);
180
181
182 static u_short packetAliasMSS;
183
184 void PacketAliasClampMSS(u_short mss)
185 {
186 packetAliasMSS = mss;
187 }
188
189 static void DoMSSClamp(struct tcphdr *tc)
190 {
191 u_char *option = (u_char *) tc + sizeof(*tc);
192 u_char *optionEnd = option + ((tc->th_off << 2) - sizeof(*tc));
193
194 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;
215 int accnetorder = 0 ;
216 accumulate -= packetAliasMSS;
217 *mssPtr = htons(packetAliasMSS);
218 accnetorder = htons(accumulate);
219 ADJUST_CHECKSUM(accnetorder, tc->th_sum);
220 }
221
222 option = optionEnd;
223 }
224 break;
225
226 default:
227 option += option[1];
228 break;
229 }
230 }
231 }
232
233 static void
234 TcpMonitorIn(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:
243 if (tc->th_flags & TH_RST)
244 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
245 else if (tc->th_flags & TH_SYN)
246 {
247 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
248
249 if (packetAliasMSS)
250 DoMSSClamp(tc);
251 }
252 break;
253 case ALIAS_TCP_STATE_CONNECTED:
254 if (tc->th_flags & (TH_FIN | TH_RST))
255 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
256 break;
257 }
258 }
259
260 static void
261 TcpMonitorOut(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:
270 if (tc->th_flags & TH_RST)
271 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
272 else if (tc->th_flags & TH_SYN)
273 {
274 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
275
276 if (packetAliasMSS)
277 DoMSSClamp(tc);
278 }
279 break;
280 case ALIAS_TCP_STATE_CONNECTED:
281 if (tc->th_flags & (TH_FIN | TH_RST))
282 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
283 break;
284 }
285 }
286
287
288
289
290
291 /* Protocol Specific Packet Aliasing Routines
292
293 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
294 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
295 ProtoAliasIn(), ProtoAliasOut()
296 UdpAliasIn(), UdpAliasOut()
297 TcpAliasIn(), TcpAliasOut()
298
299 These routines handle protocol specific details of packet aliasing.
300 One may observe a certain amount of repetitive arithmetic in these
301 functions, the purpose of which is to compute a revised checksum
302 without actually summing over the entire data packet, which could be
303 unnecessarily time consuming.
304
305 The purpose of the packet aliasing routines is to replace the source
306 address of the outgoing packet and then correctly put it back for
307 any incoming packets. For TCP and UDP, ports are also re-mapped.
308
309 For ICMP echo/timestamp requests and replies, the following scheme
310 is used: the ID number is replaced by an alias for the outgoing
311 packet.
312
313 ICMP error messages are handled by looking at the IP fragment
314 in the data section of the message.
315
316 For TCP and UDP protocols, a port number is chosen for an outgoing
317 packet, and then incoming packets are identified by IP address and
318 port numbers. For TCP packets, there is additional logic in the event
319 that sequence and ACK numbers have been altered (as in the case for
320 FTP data port commands).
321
322 The port numbers used by the packet aliasing module are not true
323 ports in the Unix sense. No sockets are actually bound to ports.
324 They are more correctly thought of as placeholders.
325
326 All packets go through the aliasing mechanism, whether they come from
327 the gateway machine or other machines on a local area network.
328 */
329
330
331 /* Local prototypes */
332 static int IcmpAliasIn1(struct ip *);
333 static int IcmpAliasIn2(struct ip *);
334 static int IcmpAliasIn (struct ip *);
335
336 static int IcmpAliasOut1(struct ip *);
337 static int IcmpAliasOut2(struct ip *);
338 static int IcmpAliasOut (struct ip *);
339
340 static int ProtoAliasIn(struct ip *);
341 static int ProtoAliasOut(struct ip *);
342
343 static int UdpAliasOut(struct ip *);
344 static int UdpAliasIn (struct ip *);
345
346 static int TcpAliasOut(struct ip *, int);
347 static int TcpAliasIn (struct ip *);
348
349
350 static int
351 IcmpAliasIn1(struct ip *pip)
352 {
353 /*
354 De-alias incoming echo and timestamp replies.
355 Alias incoming echo and timestamp requests.
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 */
363 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
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;
374 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
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
396 static int
397 IcmpAliasIn2(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));
410 ip = &ic->icmp_ip;
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,
419 IPPROTO_UDP, 0);
420 else if (ip->ip_p == IPPROTO_TCP)
421 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
422 tc->th_dport, tc->th_sport,
423 IPPROTO_TCP, 0);
424 else if (ip->ip_p == IPPROTO_ICMP) {
425 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
426 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
427 else
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;
453 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
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
463 fragment contained in ICMP data section */
464 ip->ip_src = original_address;
465 ud->uh_sport = original_port;
466 }
467 else if (ip->ip_p == IPPROTO_ICMP)
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;
486 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
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
495 /* Un-alias address of original IP packet and sequence number of
496 embedded ICMP datagram */
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
505
506 static int
507 IcmpAliasIn(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:
536 iresult = IcmpAliasIn1(pip);
537 break;
538 }
539 return(iresult);
540 }
541
542
543 static int
544 IcmpAliasOut1(struct ip *pip)
545 {
546 /*
547 Alias outgoing echo and timestamp requests.
548 De-alias outgoing echo and timestamp replies.
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 */
556 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
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;
567 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
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
590 static int
591 IcmpAliasOut2(struct ip *pip)
592 {
593 /*
594 Alias outgoing ICMP error messages containing
595 IP header and first 64 bits of datagram.
596 */
597 struct ip *ip;
598 struct icmp *ic, *ic2;
599 struct udphdr *ud;
600 struct tcphdr *tc;
601 struct alias_link *link;
602
603 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
604 ip = &ic->icmp_ip;
605
606 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
607 tc = (struct tcphdr *) ud;
608 ic2 = (struct icmp *) ud;
609
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;
625
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;
634
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);
648
649 /*
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
662 fragment 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;
672
673 alias_address = GetAliasAddress(link);
674 alias_id = GetAliasPort(link);
675
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);
707 }
708
709
710 static int
711 IcmpAliasOut(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:
740 iresult = IcmpAliasOut1(pip);
741 }
742 return(iresult);
743 }
744
745
746
747 static int
748 ProtoAliasIn(struct ip *pip)
749 {
750 /*
751 Handle incoming IP packets. The
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 */
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 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
763 if (link != NULL)
764 {
765 struct in_addr original_address;
766
767 original_address = GetOriginalAddress(link);
768
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);
779 }
780
781
782 static int
783 ProtoAliasOut(struct ip *pip)
784 {
785 /*
786 Handle outgoing IP packets. The
787 only thing which is done in this case is to alias
788 the source IP address of the packet.
789 */
790 struct alias_link *link;
791
792 /* Return if proxy-only mode is enabled */
793 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
794 return PKT_ALIAS_OK;
795
796 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
797 if (link != NULL)
798 {
799 struct in_addr alias_address;
800
801 alias_address = GetAliasAddress(link);
802
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;
809
810 return(PKT_ALIAS_OK);
811 }
812 return(PKT_ALIAS_IGNORED);
813 }
814
815
816 static int
817 UdpAliasIn(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,
830 IPPROTO_UDP, 1);
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
845 /* Special processing for IP encoding protocols */
846 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
847 AliasHandleCUSeeMeIn(pip, original_address);
848 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
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);
856
857 /* If UDP checksum is not zero, then adjust since destination port */
858 /* is being unaliased and destination address is being altered. */
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;
869 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
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
890 static int
891 UdpAliasOut(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,
904 IPPROTO_UDP, 1);
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
913 /* Special processing for IP encoding protocols */
914 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
915 AliasHandleCUSeeMeOut(pip, link);
916 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
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);
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;
940 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
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
960 static int
961 TcpAliasIn(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,
970 IPPROTO_TCP,
971 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
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
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
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
1005 /* If this is a proxy, then modify the TCP source port and
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
1021 /* See if ACK number needs to be modified */
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
1073 static int
1074 TcpAliasOut(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,
1092 then alter the destination and adjust checksums */
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,
1126 IPPROTO_TCP, 1);
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
1147 /* Monitor TCP connection state */
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);
1154 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1155 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1156 AliasHandleIrcOut(pip, link, maxpacketsize);
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);
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
1197 ADJUST_CHECKSUM(accumulate, tc->th_sum);
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
1208 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
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
1223 The packet aliasing module has a limited ability for handling IP
1224 fragments. If the ICMP, TCP or UDP header is in the first fragment
1225 received, then the ID number of the IP packet is saved, and other
1226 fragments are identified according to their ID number and IP address
1227 they were sent from. Pointers to unresolved fragments can also be
1228 saved and recalled when a header fragment is seen.
1229 */
1230
1231 /* Local prototypes */
1232 static int FragmentIn(struct ip *);
1233 static int FragmentOut(struct ip *);
1234
1235
1236 static int
1237 FragmentIn(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
1259 static int
1260 FragmentOut(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()
1286 PacketUnaliasOut()
1287
1288 (prototypes in alias.h)
1289 */
1290
1291
1292 int
1293 PacketAliasSaveFragment(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
1311 char *
1312 PacketAliasGetFragment(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
1335 void
1336 PacketAliasFragmentIn(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
1356 int
1357 PacketAliasIn(char *ptr, int maxpacketsize)
1358 {
1359 struct in_addr alias_addr;
1360 struct ip *pip;
1361 int iresult;
1362
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 }
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:
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);
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
1446 int
1447 PacketAliasOut(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
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 }
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 {
1475 u_long addr;
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;
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);
1515 break;
1516 }
1517 }
1518 else
1519 {
1520 iresult = FragmentOut(pip);
1521 }
1522
1523 SetDefaultAliasAddress(addr_save);
1524 return(iresult);
1525 }
1526
1527 int
1528 PacketUnaliasOut(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 }