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