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. */ 1062 if (proxy_type != 0) 1063 { 1064 SetProxyPort(link, dest_port); 1065 SetProxyAddress(link, dest_address); 1066 ProxyModify(link, pip, maxpacketsize, proxy_type); 1067 } 1068 1069 /* Get alias address and port */ 1070 alias_port = GetAliasPort(link); 1071 alias_address = GetAliasAddress(link); 1072 1073 /* Monitor TCP connection state */ 1074 TcpMonitorOut(pip, link); 1075 1076 /* Special processing for IP encoding protocols */ 1077 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER 1078 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) 1079 AliasHandleFtpOut(pip, link, maxpacketsize); 1080 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 1081 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) 1082 AliasHandleIrcOut(pip, link, maxpacketsize); 1083 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1 1084 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1 1085 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2 1086 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 1087 AliasHandleRtspOut(pip, link, maxpacketsize); 1088 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 1089 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 1090 AliasHandlePptpOut(pip, link); 1091 1092 /* Adjust TCP checksum since source port is being aliased */ 1093 /* and source address is being altered */ 1094 accumulate = tc->th_sport; 1095 tc->th_sport = alias_port; 1096 accumulate -= tc->th_sport; 1097 1098 sptr = (u_short *) &(pip->ip_src); 1099 accumulate += *sptr++; 1100 accumulate += *sptr; 1101 sptr = (u_short *) &alias_address; 1102 accumulate -= *sptr++; 1103 accumulate -= *sptr; 1104 1105 /* Modify sequence number if necessary */ 1106 if (GetAckModified(link) == 1) 1107 { 1108 int delta; 1109 1110 delta = GetDeltaSeqOut(pip, link); 1111 if (delta != 0) 1112 { 1113 sptr = (u_short *) &tc->th_seq; 1114 accumulate += *sptr++; 1115 accumulate += *sptr; 1116 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1117 sptr = (u_short *) &tc->th_seq; 1118 accumulate -= *sptr++; 1119 accumulate -= *sptr; 1120 } 1121 } 1122 1123 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1124 1125 /* Change source address */ 1126 sptr = (u_short *) &(pip->ip_src); 1127 accumulate = *sptr++; 1128 accumulate += *sptr; 1129 pip->ip_src = alias_address; 1130 sptr = (u_short *) &(pip->ip_src); 1131 accumulate -= *sptr++; 1132 accumulate -= *sptr; 1133 1134 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1135 1136 return(PKT_ALIAS_OK); 1137 } 1138 return(PKT_ALIAS_IGNORED); 1139 } 1140 1141 1142 1143 1144 /* Fragment Handling 1145 1146 FragmentIn() 1147 FragmentOut() 1148 1149 The packet aliasing module has a limited ability for handling IP 1150 fragments. If the ICMP, TCP or UDP header is in the first fragment 1151 received, then the ID number of the IP packet is saved, and other 1152 fragments are identified according to their ID number and IP address 1153 they were sent from. Pointers to unresolved fragments can also be 1154 saved and recalled when a header fragment is seen. 1155 */ 1156 1157 /* Local prototypes */ 1158 static int FragmentIn(struct ip *); 1159 static int FragmentOut(struct ip *); 1160 1161 1162 static int 1163 FragmentIn(struct ip *pip) 1164 { 1165 struct alias_link *link; 1166 1167 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id); 1168 if (link != NULL) 1169 { 1170 struct in_addr original_address; 1171 1172 GetFragmentAddr(link, &original_address); 1173 DifferentialChecksum(&pip->ip_sum, 1174 (u_short *) &original_address, 1175 (u_short *) &pip->ip_dst, 1176 2); 1177 pip->ip_dst = original_address; 1178 1179 return(PKT_ALIAS_OK); 1180 } 1181 return(PKT_ALIAS_UNRESOLVED_FRAGMENT); 1182 } 1183 1184 1185 static int 1186 FragmentOut(struct ip *pip) 1187 { 1188 struct in_addr alias_address; 1189 1190 alias_address = FindAliasAddress(pip->ip_src); 1191 DifferentialChecksum(&pip->ip_sum, 1192 (u_short *) &alias_address, 1193 (u_short *) &pip->ip_src, 1194 2); 1195 pip->ip_src = alias_address; 1196 1197 return(PKT_ALIAS_OK); 1198 } 1199 1200 1201 1202 1203 1204 1205 /* Outside World Access 1206 1207 PacketAliasSaveFragment() 1208 PacketAliasGetFragment() 1209 PacketAliasFragmentIn() 1210 PacketAliasIn() 1211 PacketAliasOut() 1212 PacketUnaliasOut() 1213 1214 (prototypes in alias.h) 1215 */ 1216 1217 1218 int 1219 PacketAliasSaveFragment(char *ptr) 1220 { 1221 int iresult; 1222 struct alias_link *link; 1223 struct ip *pip; 1224 1225 pip = (struct ip *) ptr; 1226 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id); 1227 iresult = PKT_ALIAS_ERROR; 1228 if (link != NULL) 1229 { 1230 SetFragmentPtr(link, ptr); 1231 iresult = PKT_ALIAS_OK; 1232 } 1233 return(iresult); 1234 } 1235 1236 1237 char * 1238 PacketAliasGetFragment(char *ptr) 1239 { 1240 struct alias_link *link; 1241 char *fptr; 1242 struct ip *pip; 1243 1244 pip = (struct ip *) ptr; 1245 link = FindFragmentPtr(pip->ip_src, pip->ip_id); 1246 if (link != NULL) 1247 { 1248 GetFragmentPtr(link, &fptr); 1249 SetFragmentPtr(link, NULL); 1250 SetExpire(link, 0); /* Deletes link */ 1251 1252 return(fptr); 1253 } 1254 else 1255 { 1256 return(NULL); 1257 } 1258 } 1259 1260 1261 void 1262 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased 1263 header fragment */ 1264 char *ptr_fragment /* Points to fragment which must 1265 be de-aliased */ 1266 ) 1267 { 1268 struct ip *pip; 1269 struct ip *fpip; 1270 1271 pip = (struct ip *) ptr; 1272 fpip = (struct ip *) ptr_fragment; 1273 1274 DifferentialChecksum(&fpip->ip_sum, 1275 (u_short *) &pip->ip_dst, 1276 (u_short *) &fpip->ip_dst, 1277 2); 1278 fpip->ip_dst = pip->ip_dst; 1279 } 1280 1281 1282 int 1283 PacketAliasIn(char *ptr, int maxpacketsize) 1284 { 1285 struct in_addr alias_addr; 1286 struct ip *pip; 1287 int iresult; 1288 1289 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1290 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1291 iresult = PacketAliasOut(ptr, maxpacketsize); 1292 packetAliasMode |= PKT_ALIAS_REVERSE; 1293 return iresult; 1294 } 1295 1296 HouseKeeping(); 1297 ClearCheckNewLink(); 1298 pip = (struct ip *) ptr; 1299 alias_addr = pip->ip_dst; 1300 1301 /* Defense against mangled packets */ 1302 if (ntohs(pip->ip_len) > maxpacketsize 1303 || (pip->ip_hl<<2) > maxpacketsize) 1304 return PKT_ALIAS_IGNORED; 1305 1306 iresult = PKT_ALIAS_IGNORED; 1307 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 ) 1308 { 1309 switch (pip->ip_p) 1310 { 1311 case IPPROTO_ICMP: 1312 iresult = IcmpAliasIn(pip); 1313 break; 1314 case IPPROTO_UDP: 1315 iresult = UdpAliasIn(pip); 1316 break; 1317 case IPPROTO_TCP: 1318 iresult = TcpAliasIn(pip); 1319 break; 1320 case IPPROTO_GRE: 1321 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY || 1322 AliasHandlePptpGreIn(pip) == 0) 1323 iresult = PKT_ALIAS_OK; 1324 else 1325 iresult = ProtoAliasIn(pip); 1326 break; 1327 default: 1328 iresult = ProtoAliasIn(pip); 1329 break; 1330 } 1331 1332 if (ntohs(pip->ip_off) & IP_MF) 1333 { 1334 struct alias_link *link; 1335 1336 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id); 1337 if (link != NULL) 1338 { 1339 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1340 SetFragmentAddr(link, pip->ip_dst); 1341 } 1342 else 1343 { 1344 iresult = PKT_ALIAS_ERROR; 1345 } 1346 } 1347 } 1348 else 1349 { 1350 iresult = FragmentIn(pip); 1351 } 1352 1353 return(iresult); 1354 } 1355 1356 1357 1358 /* Unregistered address ranges */ 1359 1360 /* 10.0.0.0 -> 10.255.255.255 */ 1361 #define UNREG_ADDR_A_LOWER 0x0a000000 1362 #define UNREG_ADDR_A_UPPER 0x0affffff 1363 1364 /* 172.16.0.0 -> 172.31.255.255 */ 1365 #define UNREG_ADDR_B_LOWER 0xac100000 1366 #define UNREG_ADDR_B_UPPER 0xac1fffff 1367 1368 /* 192.168.0.0 -> 192.168.255.255 */ 1369 #define UNREG_ADDR_C_LOWER 0xc0a80000 1370 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1371 1372 int 1373 PacketAliasOut(char *ptr, /* valid IP packet */ 1374 int maxpacketsize /* How much the packet data may grow 1375 (FTP and IRC inline changes) */ 1376 ) 1377 { 1378 int iresult; 1379 struct in_addr addr_save; 1380 struct ip *pip; 1381 1382 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1383 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1384 iresult = PacketAliasIn(ptr, maxpacketsize); 1385 packetAliasMode |= PKT_ALIAS_REVERSE; 1386 return iresult; 1387 } 1388 1389 HouseKeeping(); 1390 ClearCheckNewLink(); 1391 pip = (struct ip *) ptr; 1392 1393 /* Defense against mangled packets */ 1394 if (ntohs(pip->ip_len) > maxpacketsize 1395 || (pip->ip_hl<<2) > maxpacketsize) 1396 return PKT_ALIAS_IGNORED; 1397 1398 addr_save = GetDefaultAliasAddress(); 1399 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) 1400 { 1401 u_long addr; 1402 int iclass; 1403 1404 iclass = 0; 1405 addr = ntohl(pip->ip_src.s_addr); 1406 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1407 iclass = 3; 1408 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1409 iclass = 2; 1410 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1411 iclass = 1; 1412 1413 if (iclass == 0) 1414 { 1415 SetDefaultAliasAddress(pip->ip_src); 1416 } 1417 } 1418 1419 iresult = PKT_ALIAS_IGNORED; 1420 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) 1421 { 1422 switch (pip->ip_p) 1423 { 1424 case IPPROTO_ICMP: 1425 iresult = IcmpAliasOut(pip); 1426 break; 1427 case IPPROTO_UDP: 1428 iresult = UdpAliasOut(pip); 1429 break; 1430 case IPPROTO_TCP: 1431 iresult = TcpAliasOut(pip, maxpacketsize); 1432 break; 1433 case IPPROTO_GRE: 1434 if (AliasHandlePptpGreOut(pip) == 0) 1435 iresult = PKT_ALIAS_OK; 1436 else 1437 iresult = ProtoAliasOut(pip); 1438 break; 1439 default: 1440 iresult = ProtoAliasOut(pip); 1441 break; 1442 } 1443 } 1444 else 1445 { 1446 iresult = FragmentOut(pip); 1447 } 1448 1449 SetDefaultAliasAddress(addr_save); 1450 return(iresult); 1451 } 1452 1453 int 1454 PacketUnaliasOut(char *ptr, /* valid IP packet */ 1455 int maxpacketsize /* for error checking */ 1456 ) 1457 { 1458 struct ip *pip; 1459 struct icmp *ic; 1460 struct udphdr *ud; 1461 struct tcphdr *tc; 1462 struct alias_link *link; 1463 int iresult = PKT_ALIAS_IGNORED; 1464 1465 pip = (struct ip *) ptr; 1466 1467 /* Defense against mangled packets */ 1468 if (ntohs(pip->ip_len) > maxpacketsize 1469 || (pip->ip_hl<<2) > maxpacketsize) 1470 return(iresult); 1471 1472 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 1473 tc = (struct tcphdr *) ud; 1474 ic = (struct icmp *) ud; 1475 1476 /* Find a link */ 1477 if (pip->ip_p == IPPROTO_UDP) 1478 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src, 1479 ud->uh_dport, ud->uh_sport, 1480 IPPROTO_UDP, 0); 1481 else if (pip->ip_p == IPPROTO_TCP) 1482 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src, 1483 tc->th_dport, tc->th_sport, 1484 IPPROTO_TCP, 0); 1485 else if (pip->ip_p == IPPROTO_ICMP) 1486 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1487 else 1488 link = NULL; 1489 1490 /* Change it from an aliased packet to an unaliased packet */ 1491 if (link != NULL) 1492 { 1493 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) 1494 { 1495 u_short *sptr; 1496 int accumulate; 1497 struct in_addr original_address; 1498 u_short original_port; 1499 1500 original_address = GetOriginalAddress(link); 1501 original_port = GetOriginalPort(link); 1502 1503 /* Adjust TCP/UDP checksum */ 1504 sptr = (u_short *) &(pip->ip_src); 1505 accumulate = *sptr++; 1506 accumulate += *sptr; 1507 sptr = (u_short *) &original_address; 1508 accumulate -= *sptr++; 1509 accumulate -= *sptr; 1510 1511 if (pip->ip_p == IPPROTO_UDP) { 1512 accumulate += ud->uh_sport; 1513 accumulate -= original_port; 1514 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1515 } else { 1516 accumulate += tc->th_sport; 1517 accumulate -= original_port; 1518 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1519 } 1520 1521 /* Adjust IP checksum */ 1522 DifferentialChecksum(&pip->ip_sum, 1523 (u_short *) &original_address, 1524 (u_short *) &pip->ip_src, 1525 2); 1526 1527 /* Un-alias source address and port number */ 1528 pip->ip_src = original_address; 1529 if (pip->ip_p == IPPROTO_UDP) 1530 ud->uh_sport = original_port; 1531 else 1532 tc->th_sport = original_port; 1533 1534 iresult = PKT_ALIAS_OK; 1535 1536 } else if (pip->ip_p == IPPROTO_ICMP) { 1537 1538 u_short *sptr; 1539 int accumulate; 1540 struct in_addr original_address; 1541 u_short original_id; 1542 1543 original_address = GetOriginalAddress(link); 1544 original_id = GetOriginalPort(link); 1545 1546 /* Adjust ICMP checksum */ 1547 sptr = (u_short *) &(pip->ip_src); 1548 accumulate = *sptr++; 1549 accumulate += *sptr; 1550 sptr = (u_short *) &original_address; 1551 accumulate -= *sptr++; 1552 accumulate -= *sptr; 1553 accumulate += ic->icmp_id; 1554 accumulate -= original_id; 1555 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1556 1557 /* Adjust IP checksum */ 1558 DifferentialChecksum(&pip->ip_sum, 1559 (u_short *) &original_address, 1560 (u_short *) &pip->ip_src, 1561 2); 1562 1563 /* Un-alias source address and port number */ 1564 pip->ip_src = original_address; 1565 ic->icmp_id = original_id; 1566 1567 iresult = PKT_ALIAS_OK; 1568 } 1569 } 1570 return(iresult); 1571 1572 } 1573