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