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 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 773 if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 774 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER ) 775 { 776 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport); 777 } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 778 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER ) 779 { 780 r = AliasHandleUdpNbtNS(pip, link, 781 &alias_address, 782 &alias_port, 783 &original_address, 784 &ud->uh_dport ); 785 } 786 787 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 788 AliasHandleCUSeeMeIn(pip, original_address); 789 790 /* If UDP checksum is not zero, then adjust since destination port */ 791 /* is being unaliased and destination port is being altered. */ 792 if (ud->uh_sum != 0) 793 { 794 accumulate = alias_port; 795 accumulate -= ud->uh_dport; 796 sptr = (u_short *) &alias_address; 797 accumulate += *sptr++; 798 accumulate += *sptr; 799 sptr = (u_short *) &original_address; 800 accumulate -= *sptr++; 801 accumulate -= *sptr; 802 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 803 } 804 805 /* Restore original IP address */ 806 DifferentialChecksum(&pip->ip_sum, 807 (u_short *) &original_address, 808 (u_short *) &pip->ip_dst, 809 2); 810 pip->ip_dst = original_address; 811 812 /* 813 * If we cannot figure out the packet, ignore it. 814 */ 815 if (r < 0) 816 return(PKT_ALIAS_IGNORED); 817 else 818 return(PKT_ALIAS_OK); 819 } 820 return(PKT_ALIAS_IGNORED); 821 } 822 823 static int 824 UdpAliasOut(struct ip *pip) 825 { 826 struct udphdr *ud; 827 struct alias_link *link; 828 829 /* Return if proxy-only mode is enabled */ 830 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 831 return PKT_ALIAS_OK; 832 833 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 834 835 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 836 ud->uh_sport, ud->uh_dport, 837 IPPROTO_UDP); 838 if (link != NULL) 839 { 840 u_short alias_port; 841 struct in_addr alias_address; 842 843 alias_address = GetAliasAddress(link); 844 alias_port = GetAliasPort(link); 845 846 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 847 AliasHandleCUSeeMeOut(pip, link); 848 849 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 850 if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 851 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER ) 852 { 853 AliasHandleUdpNbt(pip, link, &alias_address, alias_port); 854 } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 855 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER ) 856 { 857 AliasHandleUdpNbtNS(pip, link, 858 &pip->ip_src, 859 &ud->uh_sport, 860 &alias_address, 861 &alias_port); 862 } 863 864 /* If UDP checksum is not zero, adjust since source port is */ 865 /* being aliased and source address is being altered */ 866 if (ud->uh_sum != 0) 867 { 868 int accumulate; 869 u_short *sptr; 870 871 accumulate = ud->uh_sport; 872 accumulate -= alias_port; 873 sptr = (u_short *) &(pip->ip_src); 874 accumulate += *sptr++; 875 accumulate += *sptr; 876 sptr = (u_short *) &alias_address; 877 accumulate -= *sptr++; 878 accumulate -= *sptr; 879 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 880 } 881 882 /* Put alias port in UDP header */ 883 ud->uh_sport = alias_port; 884 885 /* Change source address */ 886 DifferentialChecksum(&pip->ip_sum, 887 (u_short *) &alias_address, 888 (u_short *) &pip->ip_src, 889 2); 890 pip->ip_src = alias_address; 891 892 return(PKT_ALIAS_OK); 893 } 894 return(PKT_ALIAS_IGNORED); 895 } 896 897 898 899 static int 900 TcpAliasIn(struct ip *pip) 901 { 902 struct tcphdr *tc; 903 struct alias_link *link; 904 905 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 906 907 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 908 tc->th_sport, tc->th_dport, 909 IPPROTO_TCP); 910 if (link != NULL) 911 { 912 struct in_addr alias_address; 913 struct in_addr original_address; 914 struct in_addr proxy_address; 915 u_short alias_port; 916 u_short proxy_port; 917 int accumulate; 918 u_short *sptr; 919 920 /* Special processing for IP encoding protocols */ 921 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 922 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 923 AliasHandlePptpIn(pip, link); 924 925 alias_address = GetAliasAddress(link); 926 original_address = GetOriginalAddress(link); 927 proxy_address = GetProxyAddress(link); 928 alias_port = tc->th_dport; 929 tc->th_dport = GetOriginalPort(link); 930 proxy_port = GetProxyPort(link); 931 932 /* Adjust TCP checksum since destination port is being unaliased */ 933 /* and destination port is being altered. */ 934 accumulate = alias_port; 935 accumulate -= tc->th_dport; 936 sptr = (u_short *) &alias_address; 937 accumulate += *sptr++; 938 accumulate += *sptr; 939 sptr = (u_short *) &original_address; 940 accumulate -= *sptr++; 941 accumulate -= *sptr; 942 943 /* If this is a proxy, then modify the TCP source port and 944 checksum accumulation */ 945 if (proxy_port != 0) 946 { 947 accumulate += tc->th_sport; 948 tc->th_sport = proxy_port; 949 accumulate -= tc->th_sport; 950 951 sptr = (u_short *) &pip->ip_src; 952 accumulate += *sptr++; 953 accumulate += *sptr; 954 sptr = (u_short *) &proxy_address; 955 accumulate -= *sptr++; 956 accumulate -= *sptr; 957 } 958 959 /* See if ACK number needs to be modified */ 960 if (GetAckModified(link) == 1) 961 { 962 int delta; 963 964 delta = GetDeltaAckIn(pip, link); 965 if (delta != 0) 966 { 967 sptr = (u_short *) &tc->th_ack; 968 accumulate += *sptr++; 969 accumulate += *sptr; 970 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 971 sptr = (u_short *) &tc->th_ack; 972 accumulate -= *sptr++; 973 accumulate -= *sptr; 974 } 975 } 976 977 ADJUST_CHECKSUM(accumulate, tc->th_sum); 978 979 /* Restore original IP address */ 980 sptr = (u_short *) &pip->ip_dst; 981 accumulate = *sptr++; 982 accumulate += *sptr; 983 pip->ip_dst = original_address; 984 sptr = (u_short *) &pip->ip_dst; 985 accumulate -= *sptr++; 986 accumulate -= *sptr; 987 988 /* If this is a transparent proxy packet, then modify the source 989 address */ 990 if (proxy_address.s_addr != 0) 991 { 992 sptr = (u_short *) &pip->ip_src; 993 accumulate += *sptr++; 994 accumulate += *sptr; 995 pip->ip_src = proxy_address; 996 sptr = (u_short *) &pip->ip_src; 997 accumulate -= *sptr++; 998 accumulate -= *sptr; 999 } 1000 1001 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1002 1003 /* Monitor TCP connection state */ 1004 TcpMonitorIn(pip, link); 1005 1006 return(PKT_ALIAS_OK); 1007 } 1008 return(PKT_ALIAS_IGNORED); 1009 } 1010 1011 static int 1012 TcpAliasOut(struct ip *pip, int maxpacketsize) 1013 { 1014 int proxy_type; 1015 u_short dest_port; 1016 u_short proxy_server_port; 1017 struct in_addr dest_address; 1018 struct in_addr proxy_server_address; 1019 struct tcphdr *tc; 1020 struct alias_link *link; 1021 1022 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 1023 1024 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port); 1025 1026 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 1027 return PKT_ALIAS_OK; 1028 1029 /* If this is a transparent proxy, save original destination, 1030 then alter the destination and adjust checksums */ 1031 dest_port = tc->th_dport; 1032 dest_address = pip->ip_dst; 1033 if (proxy_type != 0) 1034 { 1035 int accumulate; 1036 u_short *sptr; 1037 1038 accumulate = tc->th_dport; 1039 tc->th_dport = proxy_server_port; 1040 accumulate -= tc->th_dport; 1041 1042 sptr = (u_short *) &(pip->ip_dst); 1043 accumulate += *sptr++; 1044 accumulate += *sptr; 1045 sptr = (u_short *) &proxy_server_address; 1046 accumulate -= *sptr++; 1047 accumulate -= *sptr; 1048 1049 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1050 1051 sptr = (u_short *) &(pip->ip_dst); 1052 accumulate = *sptr++; 1053 accumulate += *sptr; 1054 pip->ip_dst = proxy_server_address; 1055 sptr = (u_short *) &(pip->ip_dst); 1056 accumulate -= *sptr++; 1057 accumulate -= *sptr; 1058 1059 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1060 } 1061 1062 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 1063 tc->th_sport, tc->th_dport, 1064 IPPROTO_TCP); 1065 if (link !=NULL) 1066 { 1067 u_short alias_port; 1068 struct in_addr alias_address; 1069 int accumulate; 1070 u_short *sptr; 1071 1072 /* Save original destination address, if this is a proxy packet. 1073 Also modify packet to include destination encoding. */ 1074 if (proxy_type != 0) 1075 { 1076 SetProxyPort(link, dest_port); 1077 SetProxyAddress(link, dest_address); 1078 ProxyModify(link, pip, maxpacketsize, proxy_type); 1079 } 1080 1081 /* Get alias address and port */ 1082 alias_port = GetAliasPort(link); 1083 alias_address = GetAliasAddress(link); 1084 1085 /* Monitor TCP connection state */ 1086 TcpMonitorOut(pip, link); 1087 1088 /* Special processing for IP encoding protocols */ 1089 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER 1090 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) 1091 AliasHandleFtpOut(pip, link, maxpacketsize); 1092 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 1093 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) 1094 AliasHandleIrcOut(pip, link, maxpacketsize); 1095 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1 1096 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1 1097 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2 1098 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 1099 AliasHandleRtspOut(pip, link, maxpacketsize); 1100 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 1101 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 1102 AliasHandlePptpOut(pip, link); 1103 1104 /* Adjust TCP checksum since source port is being aliased */ 1105 /* and source address is being altered */ 1106 accumulate = tc->th_sport; 1107 tc->th_sport = alias_port; 1108 accumulate -= tc->th_sport; 1109 1110 sptr = (u_short *) &(pip->ip_src); 1111 accumulate += *sptr++; 1112 accumulate += *sptr; 1113 sptr = (u_short *) &alias_address; 1114 accumulate -= *sptr++; 1115 accumulate -= *sptr; 1116 1117 /* Modify sequence number if necessary */ 1118 if (GetAckModified(link) == 1) 1119 { 1120 int delta; 1121 1122 delta = GetDeltaSeqOut(pip, link); 1123 if (delta != 0) 1124 { 1125 sptr = (u_short *) &tc->th_seq; 1126 accumulate += *sptr++; 1127 accumulate += *sptr; 1128 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1129 sptr = (u_short *) &tc->th_seq; 1130 accumulate -= *sptr++; 1131 accumulate -= *sptr; 1132 } 1133 } 1134 1135 ADJUST_CHECKSUM(accumulate, tc->th_sum) 1136 1137 /* Change source address */ 1138 sptr = (u_short *) &(pip->ip_src); 1139 accumulate = *sptr++; 1140 accumulate += *sptr; 1141 pip->ip_src = alias_address; 1142 sptr = (u_short *) &(pip->ip_src); 1143 accumulate -= *sptr++; 1144 accumulate -= *sptr; 1145 1146 ADJUST_CHECKSUM(accumulate, pip->ip_sum) 1147 1148 return(PKT_ALIAS_OK); 1149 } 1150 return(PKT_ALIAS_IGNORED); 1151 } 1152 1153 1154 1155 1156 /* Fragment Handling 1157 1158 FragmentIn() 1159 FragmentOut() 1160 1161 The packet aliasing module has a limited ability for handling IP 1162 fragments. If the ICMP, TCP or UDP header is in the first fragment 1163 received, then the ID number of the IP packet is saved, and other 1164 fragments are identified according to their ID number and IP address 1165 they were sent from. Pointers to unresolved fragments can also be 1166 saved and recalled when a header fragment is seen. 1167 */ 1168 1169 /* Local prototypes */ 1170 static int FragmentIn(struct ip *); 1171 static int FragmentOut(struct ip *); 1172 1173 1174 static int 1175 FragmentIn(struct ip *pip) 1176 { 1177 struct alias_link *link; 1178 1179 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id); 1180 if (link != NULL) 1181 { 1182 struct in_addr original_address; 1183 1184 GetFragmentAddr(link, &original_address); 1185 DifferentialChecksum(&pip->ip_sum, 1186 (u_short *) &original_address, 1187 (u_short *) &pip->ip_dst, 1188 2); 1189 pip->ip_dst = original_address; 1190 1191 return(PKT_ALIAS_OK); 1192 } 1193 return(PKT_ALIAS_UNRESOLVED_FRAGMENT); 1194 } 1195 1196 1197 static int 1198 FragmentOut(struct ip *pip) 1199 { 1200 struct in_addr alias_address; 1201 1202 alias_address = FindAliasAddress(pip->ip_src); 1203 DifferentialChecksum(&pip->ip_sum, 1204 (u_short *) &alias_address, 1205 (u_short *) &pip->ip_src, 1206 2); 1207 pip->ip_src = alias_address; 1208 1209 return(PKT_ALIAS_OK); 1210 } 1211 1212 1213 1214 1215 1216 1217 /* Outside World Access 1218 1219 PacketAliasSaveFragment() 1220 PacketAliasGetFragment() 1221 PacketAliasFragmentIn() 1222 PacketAliasIn() 1223 PacketAliasOut() 1224 PacketUnaliasOut() 1225 1226 (prototypes in alias.h) 1227 */ 1228 1229 1230 int 1231 PacketAliasSaveFragment(char *ptr) 1232 { 1233 int iresult; 1234 struct alias_link *link; 1235 struct ip *pip; 1236 1237 pip = (struct ip *) ptr; 1238 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id); 1239 iresult = PKT_ALIAS_ERROR; 1240 if (link != NULL) 1241 { 1242 SetFragmentPtr(link, ptr); 1243 iresult = PKT_ALIAS_OK; 1244 } 1245 return(iresult); 1246 } 1247 1248 1249 char * 1250 PacketAliasGetFragment(char *ptr) 1251 { 1252 struct alias_link *link; 1253 char *fptr; 1254 struct ip *pip; 1255 1256 pip = (struct ip *) ptr; 1257 link = FindFragmentPtr(pip->ip_src, pip->ip_id); 1258 if (link != NULL) 1259 { 1260 GetFragmentPtr(link, &fptr); 1261 SetFragmentPtr(link, NULL); 1262 SetExpire(link, 0); /* Deletes link */ 1263 1264 return(fptr); 1265 } 1266 else 1267 { 1268 return(NULL); 1269 } 1270 } 1271 1272 1273 void 1274 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased 1275 header fragment */ 1276 char *ptr_fragment /* Points to fragment which must 1277 be de-aliased */ 1278 ) 1279 { 1280 struct ip *pip; 1281 struct ip *fpip; 1282 1283 pip = (struct ip *) ptr; 1284 fpip = (struct ip *) ptr_fragment; 1285 1286 DifferentialChecksum(&fpip->ip_sum, 1287 (u_short *) &pip->ip_dst, 1288 (u_short *) &fpip->ip_dst, 1289 2); 1290 fpip->ip_dst = pip->ip_dst; 1291 } 1292 1293 1294 int 1295 PacketAliasIn(char *ptr, int maxpacketsize) 1296 { 1297 struct in_addr alias_addr; 1298 struct ip *pip; 1299 int iresult; 1300 1301 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1302 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1303 iresult = PacketAliasOut(ptr, maxpacketsize); 1304 packetAliasMode |= PKT_ALIAS_REVERSE; 1305 return iresult; 1306 } 1307 1308 HouseKeeping(); 1309 ClearCheckNewLink(); 1310 pip = (struct ip *) ptr; 1311 alias_addr = pip->ip_dst; 1312 1313 /* Defense against mangled packets */ 1314 if (ntohs(pip->ip_len) > maxpacketsize 1315 || (pip->ip_hl<<2) > maxpacketsize) 1316 return PKT_ALIAS_IGNORED; 1317 1318 iresult = PKT_ALIAS_IGNORED; 1319 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 ) 1320 { 1321 switch (pip->ip_p) 1322 { 1323 case IPPROTO_ICMP: 1324 iresult = IcmpAliasIn(pip); 1325 break; 1326 case IPPROTO_UDP: 1327 iresult = UdpAliasIn(pip); 1328 break; 1329 case IPPROTO_TCP: 1330 iresult = TcpAliasIn(pip); 1331 break; 1332 case IPPROTO_GRE: 1333 iresult = GreAliasIn(pip); 1334 break; 1335 default: 1336 iresult = ProtoAliasIn(pip); 1337 break; 1338 } 1339 1340 if (ntohs(pip->ip_off) & IP_MF) 1341 { 1342 struct alias_link *link; 1343 1344 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id); 1345 if (link != NULL) 1346 { 1347 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1348 SetFragmentAddr(link, pip->ip_dst); 1349 } 1350 else 1351 { 1352 iresult = PKT_ALIAS_ERROR; 1353 } 1354 } 1355 } 1356 else 1357 { 1358 iresult = FragmentIn(pip); 1359 } 1360 1361 return(iresult); 1362 } 1363 1364 1365 1366 /* Unregistered address ranges */ 1367 1368 /* 10.0.0.0 -> 10.255.255.255 */ 1369 #define UNREG_ADDR_A_LOWER 0x0a000000 1370 #define UNREG_ADDR_A_UPPER 0x0affffff 1371 1372 /* 172.16.0.0 -> 172.31.255.255 */ 1373 #define UNREG_ADDR_B_LOWER 0xac100000 1374 #define UNREG_ADDR_B_UPPER 0xac1fffff 1375 1376 /* 192.168.0.0 -> 192.168.255.255 */ 1377 #define UNREG_ADDR_C_LOWER 0xc0a80000 1378 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1379 1380 int 1381 PacketAliasOut(char *ptr, /* valid IP packet */ 1382 int maxpacketsize /* How much the packet data may grow 1383 (FTP and IRC inline changes) */ 1384 ) 1385 { 1386 int iresult; 1387 struct in_addr addr_save; 1388 struct ip *pip; 1389 1390 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1391 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1392 iresult = PacketAliasIn(ptr, maxpacketsize); 1393 packetAliasMode |= PKT_ALIAS_REVERSE; 1394 return iresult; 1395 } 1396 1397 HouseKeeping(); 1398 ClearCheckNewLink(); 1399 pip = (struct ip *) ptr; 1400 1401 /* Defense against mangled packets */ 1402 if (ntohs(pip->ip_len) > maxpacketsize 1403 || (pip->ip_hl<<2) > maxpacketsize) 1404 return PKT_ALIAS_IGNORED; 1405 1406 addr_save = GetDefaultAliasAddress(); 1407 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) 1408 { 1409 u_long addr; 1410 int iclass; 1411 1412 iclass = 0; 1413 addr = ntohl(pip->ip_src.s_addr); 1414 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1415 iclass = 3; 1416 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1417 iclass = 2; 1418 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1419 iclass = 1; 1420 1421 if (iclass == 0) 1422 { 1423 SetDefaultAliasAddress(pip->ip_src); 1424 } 1425 } 1426 1427 iresult = PKT_ALIAS_IGNORED; 1428 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) 1429 { 1430 switch (pip->ip_p) 1431 { 1432 case IPPROTO_ICMP: 1433 iresult = IcmpAliasOut(pip); 1434 break; 1435 case IPPROTO_UDP: 1436 iresult = UdpAliasOut(pip); 1437 break; 1438 case IPPROTO_TCP: 1439 iresult = TcpAliasOut(pip, maxpacketsize); 1440 break; 1441 default: 1442 iresult = ProtoAliasOut(pip); 1443 break; 1444 } 1445 } 1446 else 1447 { 1448 iresult = FragmentOut(pip); 1449 } 1450 1451 SetDefaultAliasAddress(addr_save); 1452 return(iresult); 1453 } 1454 1455 int 1456 PacketUnaliasOut(char *ptr, /* valid IP packet */ 1457 int maxpacketsize /* for error checking */ 1458 ) 1459 { 1460 struct ip *pip; 1461 struct icmp *ic; 1462 struct udphdr *ud; 1463 struct tcphdr *tc; 1464 struct alias_link *link; 1465 int iresult = PKT_ALIAS_IGNORED; 1466 1467 pip = (struct ip *) ptr; 1468 1469 /* Defense against mangled packets */ 1470 if (ntohs(pip->ip_len) > maxpacketsize 1471 || (pip->ip_hl<<2) > maxpacketsize) 1472 return(iresult); 1473 1474 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 1475 tc = (struct tcphdr *) ud; 1476 ic = (struct icmp *) ud; 1477 1478 /* Find a link */ 1479 if (pip->ip_p == IPPROTO_UDP) 1480 link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src, 1481 ud->uh_dport, ud->uh_sport, 1482 IPPROTO_UDP); 1483 else if (pip->ip_p == IPPROTO_TCP) 1484 link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src, 1485 tc->th_dport, tc->th_sport, 1486 IPPROTO_TCP); 1487 else if (pip->ip_p == IPPROTO_ICMP) 1488 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id); 1489 else 1490 link = NULL; 1491 1492 /* Change it from an aliased packet to an unaliased packet */ 1493 if (link != NULL) 1494 { 1495 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) 1496 { 1497 u_short *sptr; 1498 int accumulate; 1499 struct in_addr original_address; 1500 u_short original_port; 1501 1502 original_address = GetOriginalAddress(link); 1503 original_port = GetOriginalPort(link); 1504 1505 /* Adjust TCP/UDP checksum */ 1506 sptr = (u_short *) &(pip->ip_src); 1507 accumulate = *sptr++; 1508 accumulate += *sptr; 1509 sptr = (u_short *) &original_address; 1510 accumulate -= *sptr++; 1511 accumulate -= *sptr; 1512 1513 if (pip->ip_p == IPPROTO_UDP) { 1514 accumulate += ud->uh_sport; 1515 accumulate -= original_port; 1516 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 1517 } else { 1518 accumulate += tc->th_sport; 1519 accumulate -= original_port; 1520 ADJUST_CHECKSUM(accumulate, tc->th_sum) 1521 } 1522 1523 /* Adjust IP checksum */ 1524 DifferentialChecksum(&pip->ip_sum, 1525 (u_short *) &original_address, 1526 (u_short *) &pip->ip_src, 1527 2); 1528 1529 /* Un-alias source address and port number */ 1530 pip->ip_src = original_address; 1531 if (pip->ip_p == IPPROTO_UDP) 1532 ud->uh_sport = original_port; 1533 else 1534 tc->th_sport = original_port; 1535 1536 iresult = PKT_ALIAS_OK; 1537 1538 } else if (pip->ip_p == IPPROTO_ICMP) { 1539 1540 u_short *sptr; 1541 int accumulate; 1542 struct in_addr original_address; 1543 u_short original_id; 1544 1545 original_address = GetOriginalAddress(link); 1546 original_id = GetOriginalPort(link); 1547 1548 /* Adjust ICMP checksum */ 1549 sptr = (u_short *) &(pip->ip_src); 1550 accumulate = *sptr++; 1551 accumulate += *sptr; 1552 sptr = (u_short *) &original_address; 1553 accumulate -= *sptr++; 1554 accumulate -= *sptr; 1555 accumulate += ic->icmp_id; 1556 accumulate -= original_id; 1557 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 1558 1559 /* Adjust IP checksum */ 1560 DifferentialChecksum(&pip->ip_sum, 1561 (u_short *) &original_address, 1562 (u_short *) &pip->ip_src, 1563 2); 1564 1565 /* Un-alias source address and port number */ 1566 pip->ip_src = original_address; 1567 ic->icmp_id = original_id; 1568 1569 iresult = PKT_ALIAS_OK; 1570 } 1571 } 1572 return(iresult); 1573 1574 } 1575