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