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