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 * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.11 2002/07/25 12:31:37 ru Exp $ 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/param.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 static __inline int 141 twowords(void *p) 142 { 143 uint8_t *c = p; 144 145 #if BYTE_ORDER == LITTLE_ENDIAN 146 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0]; 147 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2]; 148 #else 149 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1]; 150 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3]; 151 #endif 152 return (s1 + s2); 153 } 154 155 /* TCP Handling Routines 156 157 TcpMonitorIn() -- These routines monitor TCP connections, and 158 TcpMonitorOut() delete a link when a connection is closed. 159 160 These routines look for SYN, FIN and RST flags to determine when TCP 161 connections open and close. When a TCP connection closes, the data 162 structure containing packet aliasing information is deleted after 163 a timeout period. 164 */ 165 166 /* Local prototypes */ 167 static void TcpMonitorIn(struct ip *, struct alias_link *); 168 169 static void TcpMonitorOut(struct ip *, struct alias_link *); 170 171 172 static void 173 TcpMonitorIn(struct ip *pip, struct alias_link *link) 174 { 175 struct tcphdr *tc; 176 177 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 178 179 switch (GetStateIn(link)) 180 { 181 case ALIAS_TCP_STATE_NOT_CONNECTED: 182 if (tc->th_flags & TH_RST) 183 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED); 184 else if (tc->th_flags & TH_SYN) 185 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED); 186 break; 187 case ALIAS_TCP_STATE_CONNECTED: 188 if (tc->th_flags & (TH_FIN | TH_RST)) 189 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED); 190 break; 191 } 192 } 193 194 static void 195 TcpMonitorOut(struct ip *pip, struct alias_link *link) 196 { 197 struct tcphdr *tc; 198 199 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 200 201 switch (GetStateOut(link)) 202 { 203 case ALIAS_TCP_STATE_NOT_CONNECTED: 204 if (tc->th_flags & TH_RST) 205 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED); 206 else if (tc->th_flags & TH_SYN) 207 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED); 208 break; 209 case ALIAS_TCP_STATE_CONNECTED: 210 if (tc->th_flags & (TH_FIN | TH_RST)) 211 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED); 212 break; 213 } 214 } 215 216 217 218 219 220 /* Protocol Specific Packet Aliasing Routines 221 222 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2() 223 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2() 224 ProtoAliasIn(), ProtoAliasOut() 225 UdpAliasIn(), UdpAliasOut() 226 TcpAliasIn(), TcpAliasOut() 227 228 These routines handle protocol specific details of packet aliasing. 229 One may observe a certain amount of repetitive arithmetic in these 230 functions, the purpose of which is to compute a revised checksum 231 without actually summing over the entire data packet, which could be 232 unnecessarily time consuming. 233 234 The purpose of the packet aliasing routines is to replace the source 235 address of the outgoing packet and then correctly put it back for 236 any incoming packets. For TCP and UDP, ports are also re-mapped. 237 238 For ICMP echo/timestamp requests and replies, the following scheme 239 is used: the ID number is replaced by an alias for the outgoing 240 packet. 241 242 ICMP error messages are handled by looking at the IP fragment 243 in the data section of the message. 244 245 For TCP and UDP protocols, a port number is chosen for an outgoing 246 packet, and then incoming packets are identified by IP address and 247 port numbers. For TCP packets, there is additional logic in the event 248 that sequence and ACK numbers have been altered (as in the case for 249 FTP data port commands). 250 251 The port numbers used by the packet aliasing module are not true 252 ports in the Unix sense. No sockets are actually bound to ports. 253 They are more correctly thought of as placeholders. 254 255 All packets go through the aliasing mechanism, whether they come from 256 the gateway machine or other machines on a local area network. 257 */ 258 259 260 /* Local prototypes */ 261 static int IcmpAliasIn1(struct ip *); 262 static int IcmpAliasIn2(struct ip *); 263 static int IcmpAliasIn (struct ip *); 264 265 static int IcmpAliasOut1(struct ip *); 266 static int IcmpAliasOut2(struct ip *); 267 static int IcmpAliasOut (struct ip *); 268 269 static int ProtoAliasIn(struct ip *); 270 static int ProtoAliasOut(struct ip *); 271 272 static int UdpAliasOut(struct ip *); 273 static int UdpAliasIn (struct ip *); 274 275 static int TcpAliasOut(struct ip *, int); 276 static int TcpAliasIn (struct ip *); 277 278 279 static int 280 IcmpAliasIn1(struct ip *pip) 281 { 282 /* 283 De-alias incoming echo and timestamp replies. 284 Alias incoming echo and timestamp requests. 285 */ 286 struct alias_link *link; 287 struct icmp *ic; 288 289 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 290 291 /* Get source address from ICMP data field and restore original data */ 292 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1); 293 if (link != NULL) 294 { 295 u_short original_id; 296 int accumulate; 297 298 original_id = GetOriginalPort(link); 299 300 /* Adjust ICMP checksum */ 301 accumulate = ic->icmp_id; 302 accumulate -= original_id; 303 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 304 305 /* Put original sequence number back in */ 306 ic->icmp_id = original_id; 307 308 /* Put original address back into IP header */ 309 { 310 struct in_addr original_address; 311 312 original_address = GetOriginalAddress(link); 313 DifferentialChecksum(&pip->ip_sum, 314 (u_short *) &original_address, 315 (u_short *) &pip->ip_dst, 316 2); 317 pip->ip_dst = original_address; 318 } 319 320 return(PKT_ALIAS_OK); 321 } 322 return(PKT_ALIAS_IGNORED); 323 } 324 325 static int 326 IcmpAliasIn2(struct ip *pip) 327 { 328 /* 329 Alias incoming ICMP error messages containing 330 IP header and first 64 bits of datagram. 331 */ 332 struct ip *ip; 333 struct icmp *ic, *ic2; 334 struct udphdr *ud; 335 struct tcphdr *tc; 336 struct alias_link *link; 337 338 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 339 ip = &ic->icmp_ip; 340 341 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); 342 tc = (struct tcphdr *) ud; 343 ic2 = (struct icmp *) ud; 344 345 if (ip->ip_p == IPPROTO_UDP) 346 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, 347 ud->uh_dport, ud->uh_sport, 348 IPPROTO_UDP, 0); 349 else if (ip->ip_p == IPPROTO_TCP) 350 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, 351 tc->th_dport, tc->th_sport, 352 IPPROTO_TCP, 0); 353 else if (ip->ip_p == IPPROTO_ICMP) { 354 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 355 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 356 else 357 link = NULL; 358 } else 359 link = NULL; 360 361 if (link != NULL) 362 { 363 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) 364 { 365 int accumulate, accumulate2; 366 struct in_addr original_address; 367 u_short original_port; 368 369 original_address = GetOriginalAddress(link); 370 original_port = GetOriginalPort(link); 371 372 /* Adjust ICMP checksum */ 373 accumulate = twowords(&ip->ip_src); 374 accumulate -= twowords(&original_address); 375 accumulate += ud->uh_sport; 376 accumulate -= original_port; 377 accumulate2 = accumulate; 378 accumulate2 += ip->ip_sum; 379 ADJUST_CHECKSUM(accumulate, ip->ip_sum); 380 accumulate2 -= ip->ip_sum; 381 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum); 382 383 /* Un-alias address in IP header */ 384 DifferentialChecksum(&pip->ip_sum, 385 (u_short *) &original_address, 386 (u_short *) &pip->ip_dst, 387 2); 388 pip->ip_dst = original_address; 389 390 /* Un-alias address and port number of original IP packet 391 fragment contained in ICMP data section */ 392 ip->ip_src = original_address; 393 ud->uh_sport = original_port; 394 } 395 else if (ip->ip_p == IPPROTO_ICMP) 396 { 397 int accumulate, accumulate2; 398 struct in_addr original_address; 399 u_short original_id; 400 401 original_address = GetOriginalAddress(link); 402 original_id = GetOriginalPort(link); 403 404 /* Adjust ICMP checksum */ 405 accumulate = twowords(&ip->ip_src); 406 accumulate -= twowords(&original_address); 407 accumulate += ic2->icmp_id; 408 accumulate -= original_id; 409 accumulate2 = accumulate; 410 accumulate2 += ip->ip_sum; 411 ADJUST_CHECKSUM(accumulate, ip->ip_sum); 412 accumulate2 -= ip->ip_sum; 413 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum); 414 415 /* Un-alias address in IP header */ 416 DifferentialChecksum(&pip->ip_sum, 417 (u_short *) &original_address, 418 (u_short *) &pip->ip_dst, 419 2); 420 pip->ip_dst = original_address; 421 422 /* Un-alias address of original IP packet and sequence number of 423 embedded ICMP datagram */ 424 ip->ip_src = original_address; 425 ic2->icmp_id = original_id; 426 } 427 return(PKT_ALIAS_OK); 428 } 429 return(PKT_ALIAS_IGNORED); 430 } 431 432 433 static int 434 IcmpAliasIn(struct ip *pip) 435 { 436 int iresult; 437 struct icmp *ic; 438 439 /* Return if proxy-only mode is enabled */ 440 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 441 return PKT_ALIAS_OK; 442 443 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 444 445 iresult = PKT_ALIAS_IGNORED; 446 switch (ic->icmp_type) 447 { 448 case ICMP_ECHOREPLY: 449 case ICMP_TSTAMPREPLY: 450 if (ic->icmp_code == 0) 451 { 452 iresult = IcmpAliasIn1(pip); 453 } 454 break; 455 case ICMP_UNREACH: 456 case ICMP_SOURCEQUENCH: 457 case ICMP_TIMXCEED: 458 case ICMP_PARAMPROB: 459 iresult = IcmpAliasIn2(pip); 460 break; 461 case ICMP_ECHO: 462 case ICMP_TSTAMP: 463 iresult = IcmpAliasIn1(pip); 464 break; 465 } 466 return(iresult); 467 } 468 469 470 static int 471 IcmpAliasOut1(struct ip *pip) 472 { 473 /* 474 Alias outgoing echo and timestamp requests. 475 De-alias outgoing echo and timestamp replies. 476 */ 477 struct alias_link *link; 478 struct icmp *ic; 479 480 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 481 482 /* Save overwritten data for when echo packet returns */ 483 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1); 484 if (link != NULL) 485 { 486 u_short alias_id; 487 int accumulate; 488 489 alias_id = GetAliasPort(link); 490 491 /* Since data field is being modified, adjust ICMP checksum */ 492 accumulate = ic->icmp_id; 493 accumulate -= alias_id; 494 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 495 496 /* Alias sequence number */ 497 ic->icmp_id = alias_id; 498 499 /* Change source address */ 500 { 501 struct in_addr alias_address; 502 503 alias_address = GetAliasAddress(link); 504 DifferentialChecksum(&pip->ip_sum, 505 (u_short *) &alias_address, 506 (u_short *) &pip->ip_src, 507 2); 508 pip->ip_src = alias_address; 509 } 510 511 return(PKT_ALIAS_OK); 512 } 513 return(PKT_ALIAS_IGNORED); 514 } 515 516 517 static int 518 IcmpAliasOut2(struct ip *pip) 519 { 520 /* 521 Alias outgoing ICMP error messages containing 522 IP header and first 64 bits of datagram. 523 */ 524 struct ip *ip; 525 struct icmp *ic, *ic2; 526 struct udphdr *ud; 527 struct tcphdr *tc; 528 struct alias_link *link; 529 530 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 531 ip = &ic->icmp_ip; 532 533 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); 534 tc = (struct tcphdr *) ud; 535 ic2 = (struct icmp *) ud; 536 537 if (ip->ip_p == IPPROTO_UDP) 538 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src, 539 ud->uh_dport, ud->uh_sport, 540 IPPROTO_UDP, 0); 541 else if (ip->ip_p == IPPROTO_TCP) 542 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src, 543 tc->th_dport, tc->th_sport, 544 IPPROTO_TCP, 0); 545 else if (ip->ip_p == IPPROTO_ICMP) { 546 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 547 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 548 else 549 link = NULL; 550 } else 551 link = NULL; 552 553 if (link != NULL) 554 { 555 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) 556 { 557 int accumulate; 558 struct in_addr alias_address; 559 u_short alias_port; 560 561 alias_address = GetAliasAddress(link); 562 alias_port = GetAliasPort(link); 563 564 /* Adjust ICMP checksum */ 565 accumulate = twowords(&ip->ip_dst); 566 accumulate -= twowords(&alias_address); 567 accumulate += ud->uh_dport; 568 accumulate -= alias_port; 569 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 570 571 /* 572 * Alias address in IP header if it comes from the host 573 * the original TCP/UDP packet was destined for. 574 */ 575 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 576 DifferentialChecksum(&pip->ip_sum, 577 (u_short *) &alias_address, 578 (u_short *) &pip->ip_src, 579 2); 580 pip->ip_src = alias_address; 581 } 582 583 /* Alias address and port number of original IP packet 584 fragment contained in ICMP data section */ 585 ip->ip_dst = alias_address; 586 ud->uh_dport = alias_port; 587 } 588 else if (ip->ip_p == IPPROTO_ICMP) 589 { 590 int accumulate; 591 struct in_addr alias_address; 592 u_short alias_id; 593 594 alias_address = GetAliasAddress(link); 595 alias_id = GetAliasPort(link); 596 597 /* Adjust ICMP checksum */ 598 accumulate = twowords(&ip->ip_dst); 599 accumulate -= twowords(&alias_address); 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 int r = 0; 755 756 alias_address = GetAliasAddress(link); 757 original_address = GetOriginalAddress(link); 758 alias_port = ud->uh_dport; 759 ud->uh_dport = GetOriginalPort(link); 760 761 /* Special processing for IP encoding protocols */ 762 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 763 AliasHandleCUSeeMeIn(pip, original_address); 764 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 765 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 766 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) 767 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport); 768 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 769 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) 770 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port, 771 &original_address, &ud->uh_dport); 772 773 /* If UDP checksum is not zero, then adjust since destination port */ 774 /* is being unaliased and destination address is being altered. */ 775 if (ud->uh_sum != 0) 776 { 777 accumulate = alias_port; 778 accumulate -= ud->uh_dport; 779 accumulate += twowords(&alias_address); 780 accumulate -= twowords(&original_address); 781 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 782 } 783 784 /* Restore original IP address */ 785 DifferentialChecksum(&pip->ip_sum, 786 (u_short *) &original_address, 787 (u_short *) &pip->ip_dst, 788 2); 789 pip->ip_dst = original_address; 790 791 /* 792 * If we cannot figure out the packet, ignore it. 793 */ 794 if (r < 0) 795 return(PKT_ALIAS_IGNORED); 796 else 797 return(PKT_ALIAS_OK); 798 } 799 return(PKT_ALIAS_IGNORED); 800 } 801 802 static int 803 UdpAliasOut(struct ip *pip) 804 { 805 struct udphdr *ud; 806 struct alias_link *link; 807 808 /* Return if proxy-only mode is enabled */ 809 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 810 return PKT_ALIAS_OK; 811 812 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 813 814 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 815 ud->uh_sport, ud->uh_dport, 816 IPPROTO_UDP, 1); 817 if (link != NULL) 818 { 819 u_short alias_port; 820 struct in_addr alias_address; 821 822 alias_address = GetAliasAddress(link); 823 alias_port = GetAliasPort(link); 824 825 /* Special processing for IP encoding protocols */ 826 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 827 AliasHandleCUSeeMeOut(pip, link); 828 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 829 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 830 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) 831 AliasHandleUdpNbt(pip, link, &alias_address, alias_port); 832 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 833 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) 834 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport, 835 &alias_address, &alias_port); 836 /* 837 * We don't know in advance what TID the TFTP server will choose, 838 * so we create a wilcard link (destination port is unspecified) 839 * that will match any TID from a given destination. 840 */ 841 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER) 842 FindRtspOut(pip->ip_src, pip->ip_dst, 843 ud->uh_sport, alias_port, IPPROTO_UDP); 844 845 /* If UDP checksum is not zero, adjust since source port is */ 846 /* being aliased and source address is being altered */ 847 if (ud->uh_sum != 0) 848 { 849 int accumulate; 850 851 accumulate = ud->uh_sport; 852 accumulate -= alias_port; 853 accumulate += twowords(&pip->ip_src); 854 accumulate -= twowords(&alias_address); 855 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 856 } 857 858 /* Put alias port in UDP header */ 859 ud->uh_sport = alias_port; 860 861 /* Change source address */ 862 DifferentialChecksum(&pip->ip_sum, 863 (u_short *) &alias_address, 864 (u_short *) &pip->ip_src, 865 2); 866 pip->ip_src = alias_address; 867 868 return(PKT_ALIAS_OK); 869 } 870 return(PKT_ALIAS_IGNORED); 871 } 872 873 874 875 static int 876 TcpAliasIn(struct ip *pip) 877 { 878 struct tcphdr *tc; 879 struct alias_link *link; 880 881 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 882 883 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 884 tc->th_sport, tc->th_dport, 885 IPPROTO_TCP, 886 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY)); 887 if (link != NULL) 888 { 889 struct in_addr alias_address; 890 struct in_addr original_address; 891 struct in_addr proxy_address; 892 u_short alias_port; 893 u_short proxy_port; 894 int accumulate; 895 896 /* Special processing for IP encoding protocols */ 897 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 898 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 899 AliasHandlePptpIn(pip, link); 900 901 alias_address = GetAliasAddress(link); 902 original_address = GetOriginalAddress(link); 903 proxy_address = GetProxyAddress(link); 904 alias_port = tc->th_dport; 905 tc->th_dport = GetOriginalPort(link); 906 proxy_port = GetProxyPort(link); 907 908 /* Adjust TCP checksum since destination port is being unaliased */ 909 /* and destination port is being altered. */ 910 accumulate = alias_port; 911 accumulate -= tc->th_dport; 912 accumulate += twowords(&alias_address); 913 accumulate -= twowords(&original_address); 914 915 /* If this is a proxy, then modify the TCP source port and 916 checksum accumulation */ 917 if (proxy_port != 0) 918 { 919 accumulate += tc->th_sport; 920 tc->th_sport = proxy_port; 921 accumulate -= tc->th_sport; 922 accumulate += twowords(&pip->ip_src); 923 accumulate -= twowords(&proxy_address); 924 } 925 926 /* See if ACK number needs to be modified */ 927 if (GetAckModified(link) == 1) 928 { 929 int delta; 930 931 delta = GetDeltaAckIn(pip, link); 932 if (delta != 0) 933 { 934 accumulate += twowords(&tc->th_ack); 935 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 936 accumulate -= twowords(&tc->th_ack); 937 } 938 } 939 940 ADJUST_CHECKSUM(accumulate, tc->th_sum); 941 942 /* Restore original IP address */ 943 accumulate = twowords(&pip->ip_dst); 944 pip->ip_dst = original_address; 945 accumulate -= twowords(&pip->ip_dst); 946 947 /* If this is a transparent proxy packet, then modify the source 948 address */ 949 if (proxy_address.s_addr != 0) 950 { 951 accumulate += twowords(&pip->ip_src); 952 pip->ip_src = proxy_address; 953 accumulate -= twowords(&pip->ip_src); 954 } 955 956 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 957 958 /* Monitor TCP connection state */ 959 TcpMonitorIn(pip, link); 960 961 return(PKT_ALIAS_OK); 962 } 963 return(PKT_ALIAS_IGNORED); 964 } 965 966 static int 967 TcpAliasOut(struct ip *pip, int maxpacketsize) 968 { 969 int proxy_type; 970 u_short dest_port; 971 u_short proxy_server_port; 972 struct in_addr dest_address; 973 struct in_addr proxy_server_address; 974 struct tcphdr *tc; 975 struct alias_link *link; 976 977 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 978 979 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port); 980 981 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 982 return PKT_ALIAS_OK; 983 984 /* If this is a transparent proxy, save original destination, 985 then alter the destination and adjust checksums */ 986 dest_port = tc->th_dport; 987 dest_address = pip->ip_dst; 988 if (proxy_type != 0) 989 { 990 int accumulate; 991 992 accumulate = tc->th_dport; 993 tc->th_dport = proxy_server_port; 994 accumulate -= tc->th_dport; 995 accumulate += twowords(&pip->ip_dst); 996 accumulate -= twowords(&proxy_server_address); 997 ADJUST_CHECKSUM(accumulate, tc->th_sum); 998 999 accumulate = twowords(&pip->ip_dst); 1000 pip->ip_dst = proxy_server_address; 1001 accumulate -= twowords(&pip->ip_dst); 1002 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1003 } 1004 1005 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 1006 tc->th_sport, tc->th_dport, 1007 IPPROTO_TCP, 1); 1008 if (link !=NULL) 1009 { 1010 u_short alias_port; 1011 struct in_addr alias_address; 1012 int accumulate; 1013 1014 /* Save original destination address, if this is a proxy packet. 1015 Also modify packet to include destination encoding. This may 1016 change the size of IP header. */ 1017 if (proxy_type != 0) 1018 { 1019 SetProxyPort(link, dest_port); 1020 SetProxyAddress(link, dest_address); 1021 ProxyModify(link, pip, maxpacketsize, proxy_type); 1022 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 1023 } 1024 1025 /* Get alias address and port */ 1026 alias_port = GetAliasPort(link); 1027 alias_address = GetAliasAddress(link); 1028 1029 /* Monitor TCP connection state */ 1030 TcpMonitorOut(pip, link); 1031 1032 /* Special processing for IP encoding protocols */ 1033 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER 1034 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) 1035 AliasHandleFtpOut(pip, link, maxpacketsize); 1036 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 1037 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) 1038 AliasHandleIrcOut(pip, link, maxpacketsize); 1039 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1 1040 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1 1041 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2 1042 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 1043 AliasHandleRtspOut(pip, link, maxpacketsize); 1044 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 1045 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 1046 AliasHandlePptpOut(pip, link); 1047 1048 /* Adjust TCP checksum since source port is being aliased */ 1049 /* and source address is being altered */ 1050 accumulate = tc->th_sport; 1051 tc->th_sport = alias_port; 1052 accumulate -= tc->th_sport; 1053 accumulate += twowords(&pip->ip_src); 1054 accumulate -= twowords(&alias_address); 1055 1056 /* Modify sequence number if necessary */ 1057 if (GetAckModified(link) == 1) 1058 { 1059 int delta; 1060 1061 delta = GetDeltaSeqOut(pip, link); 1062 if (delta != 0) 1063 { 1064 accumulate += twowords(&tc->th_seq); 1065 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1066 accumulate -= twowords(&tc->th_seq); 1067 } 1068 } 1069 1070 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1071 1072 /* Change source address */ 1073 accumulate = twowords(&pip->ip_src); 1074 pip->ip_src = alias_address; 1075 accumulate -= twowords(&pip->ip_src); 1076 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1077 1078 return(PKT_ALIAS_OK); 1079 } 1080 return(PKT_ALIAS_IGNORED); 1081 } 1082 1083 1084 1085 1086 /* Fragment Handling 1087 1088 FragmentIn() 1089 FragmentOut() 1090 1091 The packet aliasing module has a limited ability for handling IP 1092 fragments. If the ICMP, TCP or UDP header is in the first fragment 1093 received, then the ID number of the IP packet is saved, and other 1094 fragments are identified according to their ID number and IP address 1095 they were sent from. Pointers to unresolved fragments can also be 1096 saved and recalled when a header fragment is seen. 1097 */ 1098 1099 /* Local prototypes */ 1100 static int FragmentIn(struct ip *); 1101 static int FragmentOut(struct ip *); 1102 1103 1104 static int 1105 FragmentIn(struct ip *pip) 1106 { 1107 struct alias_link *link; 1108 1109 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id); 1110 if (link != NULL) 1111 { 1112 struct in_addr original_address; 1113 1114 GetFragmentAddr(link, &original_address); 1115 DifferentialChecksum(&pip->ip_sum, 1116 (u_short *) &original_address, 1117 (u_short *) &pip->ip_dst, 1118 2); 1119 pip->ip_dst = original_address; 1120 1121 return(PKT_ALIAS_OK); 1122 } 1123 return(PKT_ALIAS_UNRESOLVED_FRAGMENT); 1124 } 1125 1126 1127 static int 1128 FragmentOut(struct ip *pip) 1129 { 1130 struct in_addr alias_address; 1131 1132 alias_address = FindAliasAddress(pip->ip_src); 1133 DifferentialChecksum(&pip->ip_sum, 1134 (u_short *) &alias_address, 1135 (u_short *) &pip->ip_src, 1136 2); 1137 pip->ip_src = alias_address; 1138 1139 return(PKT_ALIAS_OK); 1140 } 1141 1142 1143 1144 1145 1146 1147 /* Outside World Access 1148 1149 PacketAliasSaveFragment() 1150 PacketAliasGetFragment() 1151 PacketAliasFragmentIn() 1152 PacketAliasIn() 1153 PacketAliasOut() 1154 PacketUnaliasOut() 1155 1156 (prototypes in alias.h) 1157 */ 1158 1159 1160 int 1161 PacketAliasSaveFragment(char *ptr) 1162 { 1163 int iresult; 1164 struct alias_link *link; 1165 struct ip *pip; 1166 1167 pip = (struct ip *) ptr; 1168 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id); 1169 iresult = PKT_ALIAS_ERROR; 1170 if (link != NULL) 1171 { 1172 SetFragmentPtr(link, ptr); 1173 iresult = PKT_ALIAS_OK; 1174 } 1175 return(iresult); 1176 } 1177 1178 1179 char * 1180 PacketAliasGetFragment(char *ptr) 1181 { 1182 struct alias_link *link; 1183 char *fptr; 1184 struct ip *pip; 1185 1186 pip = (struct ip *) ptr; 1187 link = FindFragmentPtr(pip->ip_src, pip->ip_id); 1188 if (link != NULL) 1189 { 1190 GetFragmentPtr(link, &fptr); 1191 SetFragmentPtr(link, NULL); 1192 SetExpire(link, 0); /* Deletes link */ 1193 1194 return(fptr); 1195 } 1196 else 1197 { 1198 return(NULL); 1199 } 1200 } 1201 1202 1203 void 1204 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased 1205 header fragment */ 1206 char *ptr_fragment /* Points to fragment which must 1207 be de-aliased */ 1208 ) 1209 { 1210 struct ip *pip; 1211 struct ip *fpip; 1212 1213 pip = (struct ip *) ptr; 1214 fpip = (struct ip *) ptr_fragment; 1215 1216 DifferentialChecksum(&fpip->ip_sum, 1217 (u_short *) &pip->ip_dst, 1218 (u_short *) &fpip->ip_dst, 1219 2); 1220 fpip->ip_dst = pip->ip_dst; 1221 } 1222 1223 1224 int 1225 PacketAliasIn(char *ptr, int maxpacketsize) 1226 { 1227 struct in_addr alias_addr; 1228 struct ip *pip; 1229 int iresult; 1230 1231 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1232 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1233 iresult = PacketAliasOut(ptr, maxpacketsize); 1234 packetAliasMode |= PKT_ALIAS_REVERSE; 1235 return iresult; 1236 } 1237 1238 HouseKeeping(); 1239 ClearCheckNewLink(); 1240 pip = (struct ip *) ptr; 1241 alias_addr = pip->ip_dst; 1242 1243 /* Defense against mangled packets */ 1244 if (ntohs(pip->ip_len) > maxpacketsize 1245 || (pip->ip_hl<<2) > maxpacketsize) 1246 return PKT_ALIAS_IGNORED; 1247 1248 iresult = PKT_ALIAS_IGNORED; 1249 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 ) 1250 { 1251 switch (pip->ip_p) 1252 { 1253 case IPPROTO_ICMP: 1254 iresult = IcmpAliasIn(pip); 1255 break; 1256 case IPPROTO_UDP: 1257 iresult = UdpAliasIn(pip); 1258 break; 1259 case IPPROTO_TCP: 1260 iresult = TcpAliasIn(pip); 1261 break; 1262 case IPPROTO_GRE: 1263 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY || 1264 AliasHandlePptpGreIn(pip) == 0) 1265 iresult = PKT_ALIAS_OK; 1266 else 1267 iresult = ProtoAliasIn(pip); 1268 break; 1269 default: 1270 iresult = ProtoAliasIn(pip); 1271 break; 1272 } 1273 1274 if (ntohs(pip->ip_off) & IP_MF) 1275 { 1276 struct alias_link *link; 1277 1278 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id); 1279 if (link != NULL) 1280 { 1281 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1282 SetFragmentAddr(link, pip->ip_dst); 1283 } 1284 else 1285 { 1286 iresult = PKT_ALIAS_ERROR; 1287 } 1288 } 1289 } 1290 else 1291 { 1292 iresult = FragmentIn(pip); 1293 } 1294 1295 return(iresult); 1296 } 1297 1298 1299 1300 /* Unregistered address ranges */ 1301 1302 /* 10.0.0.0 -> 10.255.255.255 */ 1303 #define UNREG_ADDR_A_LOWER 0x0a000000 1304 #define UNREG_ADDR_A_UPPER 0x0affffff 1305 1306 /* 172.16.0.0 -> 172.31.255.255 */ 1307 #define UNREG_ADDR_B_LOWER 0xac100000 1308 #define UNREG_ADDR_B_UPPER 0xac1fffff 1309 1310 /* 192.168.0.0 -> 192.168.255.255 */ 1311 #define UNREG_ADDR_C_LOWER 0xc0a80000 1312 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1313 1314 int 1315 PacketAliasOut(char *ptr, /* valid IP packet */ 1316 int maxpacketsize /* How much the packet data may grow 1317 (FTP and IRC inline changes) */ 1318 ) 1319 { 1320 int iresult; 1321 struct in_addr addr_save; 1322 struct ip *pip; 1323 1324 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1325 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1326 iresult = PacketAliasIn(ptr, maxpacketsize); 1327 packetAliasMode |= PKT_ALIAS_REVERSE; 1328 return iresult; 1329 } 1330 1331 HouseKeeping(); 1332 ClearCheckNewLink(); 1333 pip = (struct ip *) ptr; 1334 1335 /* Defense against mangled packets */ 1336 if (ntohs(pip->ip_len) > maxpacketsize 1337 || (pip->ip_hl<<2) > maxpacketsize) 1338 return PKT_ALIAS_IGNORED; 1339 1340 addr_save = GetDefaultAliasAddress(); 1341 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) 1342 { 1343 u_long addr; 1344 int iclass; 1345 1346 iclass = 0; 1347 addr = ntohl(pip->ip_src.s_addr); 1348 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1349 iclass = 3; 1350 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1351 iclass = 2; 1352 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1353 iclass = 1; 1354 1355 if (iclass == 0) 1356 { 1357 SetDefaultAliasAddress(pip->ip_src); 1358 } 1359 } 1360 1361 iresult = PKT_ALIAS_IGNORED; 1362 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) 1363 { 1364 switch (pip->ip_p) 1365 { 1366 case IPPROTO_ICMP: 1367 iresult = IcmpAliasOut(pip); 1368 break; 1369 case IPPROTO_UDP: 1370 iresult = UdpAliasOut(pip); 1371 break; 1372 case IPPROTO_TCP: 1373 iresult = TcpAliasOut(pip, maxpacketsize); 1374 break; 1375 case IPPROTO_GRE: 1376 if (AliasHandlePptpGreOut(pip) == 0) 1377 iresult = PKT_ALIAS_OK; 1378 else 1379 iresult = ProtoAliasOut(pip); 1380 break; 1381 default: 1382 iresult = ProtoAliasOut(pip); 1383 break; 1384 } 1385 } 1386 else 1387 { 1388 iresult = FragmentOut(pip); 1389 } 1390 1391 SetDefaultAliasAddress(addr_save); 1392 return(iresult); 1393 } 1394 1395 int 1396 PacketUnaliasOut(char *ptr, /* valid IP packet */ 1397 int maxpacketsize /* for error checking */ 1398 ) 1399 { 1400 struct ip *pip; 1401 struct icmp *ic; 1402 struct udphdr *ud; 1403 struct tcphdr *tc; 1404 struct alias_link *link; 1405 int iresult = PKT_ALIAS_IGNORED; 1406 1407 pip = (struct ip *) ptr; 1408 1409 /* Defense against mangled packets */ 1410 if (ntohs(pip->ip_len) > maxpacketsize 1411 || (pip->ip_hl<<2) > maxpacketsize) 1412 return(iresult); 1413 1414 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 1415 tc = (struct tcphdr *) ud; 1416 ic = (struct icmp *) ud; 1417 1418 /* Find a link */ 1419 if (pip->ip_p == IPPROTO_UDP) 1420 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src, 1421 ud->uh_dport, ud->uh_sport, 1422 IPPROTO_UDP, 0); 1423 else if (pip->ip_p == IPPROTO_TCP) 1424 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src, 1425 tc->th_dport, tc->th_sport, 1426 IPPROTO_TCP, 0); 1427 else if (pip->ip_p == IPPROTO_ICMP) 1428 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1429 else 1430 link = NULL; 1431 1432 /* Change it from an aliased packet to an unaliased packet */ 1433 if (link != NULL) 1434 { 1435 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) 1436 { 1437 int accumulate; 1438 struct in_addr original_address; 1439 u_short original_port; 1440 1441 original_address = GetOriginalAddress(link); 1442 original_port = GetOriginalPort(link); 1443 1444 /* Adjust TCP/UDP checksum */ 1445 accumulate = twowords(&pip->ip_src); 1446 accumulate -= twowords(&original_address); 1447 1448 if (pip->ip_p == IPPROTO_UDP) { 1449 accumulate += ud->uh_sport; 1450 accumulate -= original_port; 1451 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1452 } else { 1453 accumulate += tc->th_sport; 1454 accumulate -= original_port; 1455 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1456 } 1457 1458 /* Adjust IP checksum */ 1459 DifferentialChecksum(&pip->ip_sum, 1460 (u_short *) &original_address, 1461 (u_short *) &pip->ip_src, 1462 2); 1463 1464 /* Un-alias source address and port number */ 1465 pip->ip_src = original_address; 1466 if (pip->ip_p == IPPROTO_UDP) 1467 ud->uh_sport = original_port; 1468 else 1469 tc->th_sport = original_port; 1470 1471 iresult = PKT_ALIAS_OK; 1472 1473 } else if (pip->ip_p == IPPROTO_ICMP) { 1474 1475 int accumulate; 1476 struct in_addr original_address; 1477 u_short original_id; 1478 1479 original_address = GetOriginalAddress(link); 1480 original_id = GetOriginalPort(link); 1481 1482 /* Adjust ICMP checksum */ 1483 accumulate = twowords(&pip->ip_src); 1484 accumulate -= twowords(&original_address); 1485 accumulate += ic->icmp_id; 1486 accumulate -= original_id; 1487 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1488 1489 /* Adjust IP checksum */ 1490 DifferentialChecksum(&pip->ip_sum, 1491 (u_short *) &original_address, 1492 (u_short *) &pip->ip_src, 1493 2); 1494 1495 /* Un-alias source address and port number */ 1496 pip->ip_src = original_address; 1497 ic->icmp_id = original_id; 1498 1499 iresult = PKT_ALIAS_OK; 1500 } 1501 } 1502 return(iresult); 1503 1504 } 1505