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