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