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 GreAliasIn() 189 190 These routines handle protocol specific details of packet aliasing. 191 One may observe a certain amount of repetitive arithmetic in these 192 functions, the purpose of which is to compute a revised checksum 193 without actually summing over the entire data packet, which could be 194 unnecessarily time consuming. 195 196 The purpose of the packet aliasing routines is to replace the source 197 address of the outgoing packet and then correctly put it back for 198 any incoming packets. For TCP and UDP, ports are also re-mapped. 199 200 For ICMP echo/timestamp requests and replies, the following scheme 201 is used: the ID number is replaced by an alias for the outgoing 202 packet. 203 204 ICMP error messages are handled by looking at the IP fragment 205 in the data section of the message. 206 207 For TCP and UDP protocols, a port number is chosen for an outgoing 208 packet, and then incoming packets are identified by IP address and 209 port numbers. For TCP packets, there is additional logic in the event 210 that sequence and ACK numbers have been altered (as in the case for 211 FTP data port commands). 212 213 The port numbers used by the packet aliasing module are not true 214 ports in the Unix sense. No sockets are actually bound to ports. 215 They are more correctly thought of as placeholders. 216 217 All packets go through the aliasing mechanism, whether they come from 218 the gateway machine or other machines on a local area network. 219 */ 220 221 222 /* Local prototypes */ 223 static int IcmpAliasIn1(struct ip *); 224 static int IcmpAliasIn2(struct ip *); 225 static int IcmpAliasIn (struct ip *); 226 227 static int IcmpAliasOut1(struct ip *); 228 static int IcmpAliasOut2(struct ip *); 229 static int IcmpAliasOut (struct ip *); 230 231 static int ProtoAliasIn(struct ip *); 232 static int ProtoAliasOut(struct ip *); 233 234 static int UdpAliasOut(struct ip *); 235 static int UdpAliasIn (struct ip *); 236 237 static int TcpAliasOut(struct ip *, int); 238 static int TcpAliasIn (struct ip *); 239 240 static int GreAliasIn(struct ip *); 241 242 243 static int 244 IcmpAliasIn1(struct ip *pip) 245 { 246 /* 247 De-alias incoming echo and timestamp replies. 248 Alias incoming echo and timestamp requests. 249 */ 250 struct alias_link *link; 251 struct icmp *ic; 252 253 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 254 255 /* Get source address from ICMP data field and restore original data */ 256 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id); 257 if (link != NULL) 258 { 259 u_short original_id; 260 int accumulate; 261 262 original_id = GetOriginalPort(link); 263 264 /* Adjust ICMP checksum */ 265 accumulate = ic->icmp_id; 266 accumulate -= original_id; 267 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 268 269 /* Put original sequence number back in */ 270 ic->icmp_id = original_id; 271 272 /* Put original address back into IP header */ 273 { 274 struct in_addr original_address; 275 276 original_address = GetOriginalAddress(link); 277 DifferentialChecksum(&pip->ip_sum, 278 (u_short *) &original_address, 279 (u_short *) &pip->ip_dst, 280 2); 281 pip->ip_dst = original_address; 282 } 283 284 return(PKT_ALIAS_OK); 285 } 286 return(PKT_ALIAS_IGNORED); 287 } 288 289 static int 290 IcmpAliasIn2(struct ip *pip) 291 { 292 /* 293 Alias incoming ICMP error messages containing 294 IP header and first 64 bits of datagram. 295 */ 296 struct ip *ip; 297 struct icmp *ic, *ic2; 298 struct udphdr *ud; 299 struct tcphdr *tc; 300 struct alias_link *link; 301 302 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 303 ip = &ic->icmp_ip; 304 305 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); 306 tc = (struct tcphdr *) ud; 307 ic2 = (struct icmp *) ud; 308 309 if (ip->ip_p == IPPROTO_UDP) 310 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, 311 ud->uh_dport, ud->uh_sport, 312 IPPROTO_UDP); 313 else if (ip->ip_p == IPPROTO_TCP) 314 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, 315 tc->th_dport, tc->th_sport, 316 IPPROTO_TCP); 317 else if (ip->ip_p == IPPROTO_ICMP) { 318 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 319 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id); 320 else 321 link = NULL; 322 } else 323 link = NULL; 324 325 if (link != NULL) 326 { 327 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) 328 { 329 u_short *sptr; 330 int accumulate; 331 struct in_addr original_address; 332 u_short original_port; 333 334 original_address = GetOriginalAddress(link); 335 original_port = GetOriginalPort(link); 336 337 /* Adjust ICMP checksum */ 338 sptr = (u_short *) &(ip->ip_src); 339 accumulate = *sptr++; 340 accumulate += *sptr; 341 sptr = (u_short *) &original_address; 342 accumulate -= *sptr++; 343 accumulate -= *sptr; 344 accumulate += ud->uh_sport; 345 accumulate -= original_port; 346 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 347 348 /* Un-alias address in IP header */ 349 DifferentialChecksum(&pip->ip_sum, 350 (u_short *) &original_address, 351 (u_short *) &pip->ip_dst, 352 2); 353 pip->ip_dst = original_address; 354 355 /* Un-alias address and port number of original IP packet 356 fragment contained in ICMP data section */ 357 ip->ip_src = original_address; 358 ud->uh_sport = original_port; 359 } 360 else if (ip->ip_p == IPPROTO_ICMP) 361 { 362 u_short *sptr; 363 int accumulate; 364 struct in_addr original_address; 365 u_short original_id; 366 367 original_address = GetOriginalAddress(link); 368 original_id = GetOriginalPort(link); 369 370 /* Adjust ICMP checksum */ 371 sptr = (u_short *) &(ip->ip_src); 372 accumulate = *sptr++; 373 accumulate += *sptr; 374 sptr = (u_short *) &original_address; 375 accumulate -= *sptr++; 376 accumulate -= *sptr; 377 accumulate += ic2->icmp_id; 378 accumulate -= original_id; 379 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 380 381 /* Un-alias address in IP header */ 382 DifferentialChecksum(&pip->ip_sum, 383 (u_short *) &original_address, 384 (u_short *) &pip->ip_dst, 385 2); 386 pip->ip_dst = original_address; 387 388 /* Un-alias address of original IP packet and sequence number of 389 embedded ICMP datagram */ 390 ip->ip_src = original_address; 391 ic2->icmp_id = original_id; 392 } 393 return(PKT_ALIAS_OK); 394 } 395 return(PKT_ALIAS_IGNORED); 396 } 397 398 399 static int 400 IcmpAliasIn(struct ip *pip) 401 { 402 int iresult; 403 struct icmp *ic; 404 405 /* Return if proxy-only mode is enabled */ 406 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 407 return PKT_ALIAS_OK; 408 409 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 410 411 iresult = PKT_ALIAS_IGNORED; 412 switch (ic->icmp_type) 413 { 414 case ICMP_ECHOREPLY: 415 case ICMP_TSTAMPREPLY: 416 if (ic->icmp_code == 0) 417 { 418 iresult = IcmpAliasIn1(pip); 419 } 420 break; 421 case ICMP_UNREACH: 422 case ICMP_SOURCEQUENCH: 423 case ICMP_TIMXCEED: 424 case ICMP_PARAMPROB: 425 iresult = IcmpAliasIn2(pip); 426 break; 427 case ICMP_ECHO: 428 case ICMP_TSTAMP: 429 iresult = IcmpAliasIn1(pip); 430 break; 431 } 432 return(iresult); 433 } 434 435 436 static int 437 IcmpAliasOut1(struct ip *pip) 438 { 439 /* 440 Alias outgoing echo and timestamp requests. 441 De-alias outgoing echo and timestamp replies. 442 */ 443 struct alias_link *link; 444 struct icmp *ic; 445 446 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 447 448 /* Save overwritten data for when echo packet returns */ 449 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id); 450 if (link != NULL) 451 { 452 u_short alias_id; 453 int accumulate; 454 455 alias_id = GetAliasPort(link); 456 457 /* Since data field is being modified, adjust ICMP checksum */ 458 accumulate = ic->icmp_id; 459 accumulate -= alias_id; 460 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 461 462 /* Alias sequence number */ 463 ic->icmp_id = alias_id; 464 465 /* Change source address */ 466 { 467 struct in_addr alias_address; 468 469 alias_address = GetAliasAddress(link); 470 DifferentialChecksum(&pip->ip_sum, 471 (u_short *) &alias_address, 472 (u_short *) &pip->ip_src, 473 2); 474 pip->ip_src = alias_address; 475 } 476 477 return(PKT_ALIAS_OK); 478 } 479 return(PKT_ALIAS_IGNORED); 480 } 481 482 483 static int 484 IcmpAliasOut2(struct ip *pip) 485 { 486 /* 487 Alias outgoing ICMP error messages containing 488 IP header and first 64 bits of datagram. 489 */ 490 struct ip *ip; 491 struct icmp *ic, *ic2; 492 struct udphdr *ud; 493 struct tcphdr *tc; 494 struct alias_link *link; 495 496 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 497 ip = &ic->icmp_ip; 498 499 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); 500 tc = (struct tcphdr *) ud; 501 ic2 = (struct icmp *) ud; 502 503 if (ip->ip_p == IPPROTO_UDP) 504 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src, 505 ud->uh_dport, ud->uh_sport, 506 IPPROTO_UDP); 507 else if (ip->ip_p == IPPROTO_TCP) 508 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src, 509 tc->th_dport, tc->th_sport, 510 IPPROTO_TCP); 511 else if (ip->ip_p == IPPROTO_ICMP) { 512 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 513 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id); 514 else 515 link = NULL; 516 } else 517 link = NULL; 518 519 if (link != NULL) 520 { 521 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) 522 { 523 u_short *sptr; 524 int accumulate; 525 struct in_addr alias_address; 526 u_short alias_port; 527 528 alias_address = GetAliasAddress(link); 529 alias_port = GetAliasPort(link); 530 531 /* Adjust ICMP checksum */ 532 sptr = (u_short *) &(ip->ip_dst); 533 accumulate = *sptr++; 534 accumulate += *sptr; 535 sptr = (u_short *) &alias_address; 536 accumulate -= *sptr++; 537 accumulate -= *sptr; 538 accumulate += ud->uh_dport; 539 accumulate -= alias_port; 540 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 541 542 /* 543 * Alias address in IP header if it comes from the host 544 * the original TCP/UDP packet was destined for. 545 */ 546 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 547 DifferentialChecksum(&pip->ip_sum, 548 (u_short *) &alias_address, 549 (u_short *) &pip->ip_src, 550 2); 551 pip->ip_src = alias_address; 552 } 553 554 /* Alias address and port number of original IP packet 555 fragment contained in ICMP data section */ 556 ip->ip_dst = alias_address; 557 ud->uh_dport = alias_port; 558 } 559 else if (ip->ip_p == IPPROTO_ICMP) 560 { 561 u_short *sptr; 562 int accumulate; 563 struct in_addr alias_address; 564 u_short alias_id; 565 566 alias_address = GetAliasAddress(link); 567 alias_id = GetAliasPort(link); 568 569 /* Adjust ICMP checksum */ 570 sptr = (u_short *) &(ip->ip_dst); 571 accumulate = *sptr++; 572 accumulate += *sptr; 573 sptr = (u_short *) &alias_address; 574 accumulate -= *sptr++; 575 accumulate -= *sptr; 576 accumulate += ic2->icmp_id; 577 accumulate -= alias_id; 578 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 579 580 /* 581 * Alias address in IP header if it comes from the host 582 * the original ICMP message was destined for. 583 */ 584 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 585 DifferentialChecksum(&pip->ip_sum, 586 (u_short *) &alias_address, 587 (u_short *) &pip->ip_src, 588 2); 589 pip->ip_src = alias_address; 590 } 591 592 /* Alias address of original IP packet and sequence number of 593 embedded ICMP datagram */ 594 ip->ip_dst = alias_address; 595 ic2->icmp_id = alias_id; 596 } 597 return(PKT_ALIAS_OK); 598 } 599 return(PKT_ALIAS_IGNORED); 600 } 601 602 603 static int 604 IcmpAliasOut(struct ip *pip) 605 { 606 int iresult; 607 struct icmp *ic; 608 609 /* Return if proxy-only mode is enabled */ 610 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 611 return PKT_ALIAS_OK; 612 613 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 614 615 iresult = PKT_ALIAS_IGNORED; 616 switch (ic->icmp_type) 617 { 618 case ICMP_ECHO: 619 case ICMP_TSTAMP: 620 if (ic->icmp_code == 0) 621 { 622 iresult = IcmpAliasOut1(pip); 623 } 624 break; 625 case ICMP_UNREACH: 626 case ICMP_SOURCEQUENCH: 627 case ICMP_TIMXCEED: 628 case ICMP_PARAMPROB: 629 iresult = IcmpAliasOut2(pip); 630 break; 631 case ICMP_ECHOREPLY: 632 case ICMP_TSTAMPREPLY: 633 iresult = IcmpAliasOut1(pip); 634 } 635 return(iresult); 636 } 637 638 639 640 static int 641 ProtoAliasIn(struct ip *pip) 642 { 643 /* 644 Handle incoming IP packets. The 645 only thing which is done in this case is to alias 646 the dest IP address of the packet to our inside 647 machine. 648 */ 649 struct alias_link *link; 650 651 /* Return if proxy-only mode is enabled */ 652 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 653 return PKT_ALIAS_OK; 654 655 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p); 656 if (link != NULL) 657 { 658 struct in_addr original_address; 659 660 original_address = GetOriginalAddress(link); 661 662 /* Restore original IP address */ 663 DifferentialChecksum(&pip->ip_sum, 664 (u_short *) &original_address, 665 (u_short *) &pip->ip_dst, 666 2); 667 pip->ip_dst = original_address; 668 669 return(PKT_ALIAS_OK); 670 } 671 return(PKT_ALIAS_IGNORED); 672 } 673 674 675 static int 676 ProtoAliasOut(struct ip *pip) 677 { 678 /* 679 Handle outgoing IP packets. The 680 only thing which is done in this case is to alias 681 the source IP address of the packet. 682 */ 683 struct alias_link *link; 684 685 /* Return if proxy-only mode is enabled */ 686 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 687 return PKT_ALIAS_OK; 688 689 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p); 690 if (link != NULL) 691 { 692 struct in_addr alias_address; 693 694 alias_address = GetAliasAddress(link); 695 696 /* Change source address */ 697 DifferentialChecksum(&pip->ip_sum, 698 (u_short *) &alias_address, 699 (u_short *) &pip->ip_src, 700 2); 701 pip->ip_src = alias_address; 702 703 return(PKT_ALIAS_OK); 704 } 705 return(PKT_ALIAS_IGNORED); 706 } 707 708 709 static int 710 GreAliasIn(struct ip *pip) 711 { 712 u_short call_id; 713 struct alias_link *link; 714 715 /* Return if proxy-only mode is enabled. */ 716 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 717 return (PKT_ALIAS_OK); 718 719 if (PptpGetCallID(pip, &call_id)) { 720 if ((link = FindPptpIn(pip->ip_src, pip->ip_dst, call_id)) != NULL) { 721 struct in_addr alias_address; 722 struct in_addr original_address; 723 724 alias_address = GetAliasAddress(link); 725 original_address = GetOriginalAddress(link); 726 PptpSetCallID(pip, GetOriginalPort(link)); 727 728 /* Restore original IP address. */ 729 DifferentialChecksum(&pip->ip_sum, 730 (u_short *)&original_address, 731 (u_short *)&pip->ip_dst, 732 2); 733 pip->ip_dst = original_address; 734 735 return (PKT_ALIAS_OK); 736 } else 737 return (PKT_ALIAS_IGNORED); 738 } else 739 return ProtoAliasIn(pip); 740 } 741 742 743 static int 744 UdpAliasIn(struct ip *pip) 745 { 746 struct udphdr *ud; 747 struct alias_link *link; 748 749 /* Return if proxy-only mode is enabled */ 750 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 751 return PKT_ALIAS_OK; 752 753 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 754 755 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 756 ud->uh_sport, ud->uh_dport, 757 IPPROTO_UDP); 758 if (link != NULL) 759 { 760 struct in_addr alias_address; 761 struct in_addr original_address; 762 u_short alias_port; 763 int accumulate; 764 u_short *sptr; 765 int r = 0; 766 767 alias_address = GetAliasAddress(link); 768 original_address = GetOriginalAddress(link); 769 alias_port = ud->uh_dport; 770 ud->uh_dport = GetOriginalPort(link); 771 772 /* Special processing for IP encoding protocols */ 773 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 774 AliasHandleCUSeeMeIn(pip, original_address); 775 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 776 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 777 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) 778 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport); 779 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 780 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) 781 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port, 782 &original_address, &ud->uh_dport); 783 784 /* If UDP checksum is not zero, then adjust since destination port */ 785 /* is being unaliased and destination address is being altered. */ 786 if (ud->uh_sum != 0) 787 { 788 accumulate = alias_port; 789 accumulate -= ud->uh_dport; 790 sptr = (u_short *) &alias_address; 791 accumulate += *sptr++; 792 accumulate += *sptr; 793 sptr = (u_short *) &original_address; 794 accumulate -= *sptr++; 795 accumulate -= *sptr; 796 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 797 } 798 799 /* Restore original IP address */ 800 DifferentialChecksum(&pip->ip_sum, 801 (u_short *) &original_address, 802 (u_short *) &pip->ip_dst, 803 2); 804 pip->ip_dst = original_address; 805 806 /* 807 * If we cannot figure out the packet, ignore it. 808 */ 809 if (r < 0) 810 return(PKT_ALIAS_IGNORED); 811 else 812 return(PKT_ALIAS_OK); 813 } 814 return(PKT_ALIAS_IGNORED); 815 } 816 817 static int 818 UdpAliasOut(struct ip *pip) 819 { 820 struct udphdr *ud; 821 struct alias_link *link; 822 823 /* Return if proxy-only mode is enabled */ 824 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 825 return PKT_ALIAS_OK; 826 827 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 828 829 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 830 ud->uh_sport, ud->uh_dport, 831 IPPROTO_UDP); 832 if (link != NULL) 833 { 834 u_short alias_port; 835 struct in_addr alias_address; 836 837 alias_address = GetAliasAddress(link); 838 alias_port = GetAliasPort(link); 839 840 /* Special processing for IP encoding protocols */ 841 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 842 AliasHandleCUSeeMeOut(pip, link); 843 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 844 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 845 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) 846 AliasHandleUdpNbt(pip, link, &alias_address, alias_port); 847 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 848 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) 849 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport, 850 &alias_address, &alias_port); 851 852 /* If UDP checksum is not zero, adjust since source port is */ 853 /* being aliased and source address is being altered */ 854 if (ud->uh_sum != 0) 855 { 856 int accumulate; 857 u_short *sptr; 858 859 accumulate = ud->uh_sport; 860 accumulate -= alias_port; 861 sptr = (u_short *) &(pip->ip_src); 862 accumulate += *sptr++; 863 accumulate += *sptr; 864 sptr = (u_short *) &alias_address; 865 accumulate -= *sptr++; 866 accumulate -= *sptr; 867 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 868 } 869 870 /* Put alias port in UDP header */ 871 ud->uh_sport = alias_port; 872 873 /* Change source address */ 874 DifferentialChecksum(&pip->ip_sum, 875 (u_short *) &alias_address, 876 (u_short *) &pip->ip_src, 877 2); 878 pip->ip_src = alias_address; 879 880 return(PKT_ALIAS_OK); 881 } 882 return(PKT_ALIAS_IGNORED); 883 } 884 885 886 887 static int 888 TcpAliasIn(struct ip *pip) 889 { 890 struct tcphdr *tc; 891 struct alias_link *link; 892 893 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 894 895 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 896 tc->th_sport, tc->th_dport, 897 IPPROTO_TCP); 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); 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 iresult = GreAliasIn(pip); 1322 break; 1323 default: 1324 iresult = ProtoAliasIn(pip); 1325 break; 1326 } 1327 1328 if (ntohs(pip->ip_off) & IP_MF) 1329 { 1330 struct alias_link *link; 1331 1332 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id); 1333 if (link != NULL) 1334 { 1335 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1336 SetFragmentAddr(link, pip->ip_dst); 1337 } 1338 else 1339 { 1340 iresult = PKT_ALIAS_ERROR; 1341 } 1342 } 1343 } 1344 else 1345 { 1346 iresult = FragmentIn(pip); 1347 } 1348 1349 return(iresult); 1350 } 1351 1352 1353 1354 /* Unregistered address ranges */ 1355 1356 /* 10.0.0.0 -> 10.255.255.255 */ 1357 #define UNREG_ADDR_A_LOWER 0x0a000000 1358 #define UNREG_ADDR_A_UPPER 0x0affffff 1359 1360 /* 172.16.0.0 -> 172.31.255.255 */ 1361 #define UNREG_ADDR_B_LOWER 0xac100000 1362 #define UNREG_ADDR_B_UPPER 0xac1fffff 1363 1364 /* 192.168.0.0 -> 192.168.255.255 */ 1365 #define UNREG_ADDR_C_LOWER 0xc0a80000 1366 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1367 1368 int 1369 PacketAliasOut(char *ptr, /* valid IP packet */ 1370 int maxpacketsize /* How much the packet data may grow 1371 (FTP and IRC inline changes) */ 1372 ) 1373 { 1374 int iresult; 1375 struct in_addr addr_save; 1376 struct ip *pip; 1377 1378 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1379 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1380 iresult = PacketAliasIn(ptr, maxpacketsize); 1381 packetAliasMode |= PKT_ALIAS_REVERSE; 1382 return iresult; 1383 } 1384 1385 HouseKeeping(); 1386 ClearCheckNewLink(); 1387 pip = (struct ip *) ptr; 1388 1389 /* Defense against mangled packets */ 1390 if (ntohs(pip->ip_len) > maxpacketsize 1391 || (pip->ip_hl<<2) > maxpacketsize) 1392 return PKT_ALIAS_IGNORED; 1393 1394 addr_save = GetDefaultAliasAddress(); 1395 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) 1396 { 1397 u_long addr; 1398 int iclass; 1399 1400 iclass = 0; 1401 addr = ntohl(pip->ip_src.s_addr); 1402 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1403 iclass = 3; 1404 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1405 iclass = 2; 1406 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1407 iclass = 1; 1408 1409 if (iclass == 0) 1410 { 1411 SetDefaultAliasAddress(pip->ip_src); 1412 } 1413 } 1414 1415 iresult = PKT_ALIAS_IGNORED; 1416 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) 1417 { 1418 switch (pip->ip_p) 1419 { 1420 case IPPROTO_ICMP: 1421 iresult = IcmpAliasOut(pip); 1422 break; 1423 case IPPROTO_UDP: 1424 iresult = UdpAliasOut(pip); 1425 break; 1426 case IPPROTO_TCP: 1427 iresult = TcpAliasOut(pip, maxpacketsize); 1428 break; 1429 default: 1430 iresult = ProtoAliasOut(pip); 1431 break; 1432 } 1433 } 1434 else 1435 { 1436 iresult = FragmentOut(pip); 1437 } 1438 1439 SetDefaultAliasAddress(addr_save); 1440 return(iresult); 1441 } 1442 1443 int 1444 PacketUnaliasOut(char *ptr, /* valid IP packet */ 1445 int maxpacketsize /* for error checking */ 1446 ) 1447 { 1448 struct ip *pip; 1449 struct icmp *ic; 1450 struct udphdr *ud; 1451 struct tcphdr *tc; 1452 struct alias_link *link; 1453 int iresult = PKT_ALIAS_IGNORED; 1454 1455 pip = (struct ip *) ptr; 1456 1457 /* Defense against mangled packets */ 1458 if (ntohs(pip->ip_len) > maxpacketsize 1459 || (pip->ip_hl<<2) > maxpacketsize) 1460 return(iresult); 1461 1462 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 1463 tc = (struct tcphdr *) ud; 1464 ic = (struct icmp *) ud; 1465 1466 /* Find a link */ 1467 if (pip->ip_p == IPPROTO_UDP) 1468 link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src, 1469 ud->uh_dport, ud->uh_sport, 1470 IPPROTO_UDP); 1471 else if (pip->ip_p == IPPROTO_TCP) 1472 link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src, 1473 tc->th_dport, tc->th_sport, 1474 IPPROTO_TCP); 1475 else if (pip->ip_p == IPPROTO_ICMP) 1476 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id); 1477 else 1478 link = NULL; 1479 1480 /* Change it from an aliased packet to an unaliased packet */ 1481 if (link != NULL) 1482 { 1483 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) 1484 { 1485 u_short *sptr; 1486 int accumulate; 1487 struct in_addr original_address; 1488 u_short original_port; 1489 1490 original_address = GetOriginalAddress(link); 1491 original_port = GetOriginalPort(link); 1492 1493 /* Adjust TCP/UDP checksum */ 1494 sptr = (u_short *) &(pip->ip_src); 1495 accumulate = *sptr++; 1496 accumulate += *sptr; 1497 sptr = (u_short *) &original_address; 1498 accumulate -= *sptr++; 1499 accumulate -= *sptr; 1500 1501 if (pip->ip_p == IPPROTO_UDP) { 1502 accumulate += ud->uh_sport; 1503 accumulate -= original_port; 1504 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 1505 } else { 1506 accumulate += tc->th_sport; 1507 accumulate -= original_port; 1508 ADJUST_CHECKSUM(accumulate, tc->th_sum) 1509 } 1510 1511 /* Adjust IP checksum */ 1512 DifferentialChecksum(&pip->ip_sum, 1513 (u_short *) &original_address, 1514 (u_short *) &pip->ip_src, 1515 2); 1516 1517 /* Un-alias source address and port number */ 1518 pip->ip_src = original_address; 1519 if (pip->ip_p == IPPROTO_UDP) 1520 ud->uh_sport = original_port; 1521 else 1522 tc->th_sport = original_port; 1523 1524 iresult = PKT_ALIAS_OK; 1525 1526 } else if (pip->ip_p == IPPROTO_ICMP) { 1527 1528 u_short *sptr; 1529 int accumulate; 1530 struct in_addr original_address; 1531 u_short original_id; 1532 1533 original_address = GetOriginalAddress(link); 1534 original_id = GetOriginalPort(link); 1535 1536 /* Adjust ICMP checksum */ 1537 sptr = (u_short *) &(pip->ip_src); 1538 accumulate = *sptr++; 1539 accumulate += *sptr; 1540 sptr = (u_short *) &original_address; 1541 accumulate -= *sptr++; 1542 accumulate -= *sptr; 1543 accumulate += ic->icmp_id; 1544 accumulate -= original_id; 1545 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 1546 1547 /* Adjust IP checksum */ 1548 DifferentialChecksum(&pip->ip_sum, 1549 (u_short *) &original_address, 1550 (u_short *) &pip->ip_src, 1551 2); 1552 1553 /* Un-alias source address and port number */ 1554 pip->ip_src = original_address; 1555 ic->icmp_id = original_id; 1556 1557 iresult = PKT_ALIAS_OK; 1558 } 1559 } 1560 return(iresult); 1561 1562 } 1563