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