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(), IcmpAliasIn3() 184 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2(), IcmpAliasOut3() 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 IcmpAliasIn3(struct ip *); 226 static int IcmpAliasIn (struct ip *); 227 228 static int IcmpAliasOut1(struct ip *); 229 static int IcmpAliasOut2(struct ip *); 230 static int IcmpAliasOut3(struct ip *); 231 static int IcmpAliasOut (struct ip *); 232 233 static int ProtoAliasIn(struct ip *); 234 static int ProtoAliasOut(struct ip *); 235 236 static int UdpAliasOut(struct ip *); 237 static int UdpAliasIn (struct ip *); 238 239 static int TcpAliasOut(struct ip *, int); 240 static int TcpAliasIn (struct ip *); 241 242 static int GreAliasIn(struct ip *); 243 244 245 static int 246 IcmpAliasIn1(struct ip *pip) 247 { 248 /* 249 De-alias incoming echo and timestamp replies 250 */ 251 struct alias_link *link; 252 struct icmp *ic; 253 254 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 255 256 /* Get source address from ICMP data field and restore original data */ 257 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id); 258 if (link != NULL) 259 { 260 u_short original_id; 261 int accumulate; 262 263 original_id = GetOriginalPort(link); 264 265 /* Adjust ICMP checksum */ 266 accumulate = ic->icmp_id; 267 accumulate -= original_id; 268 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 269 270 /* Put original sequence number back in */ 271 ic->icmp_id = original_id; 272 273 /* Put original address back into IP header */ 274 { 275 struct in_addr original_address; 276 277 original_address = GetOriginalAddress(link); 278 DifferentialChecksum(&pip->ip_sum, 279 (u_short *) &original_address, 280 (u_short *) &pip->ip_dst, 281 2); 282 pip->ip_dst = original_address; 283 } 284 285 return(PKT_ALIAS_OK); 286 } 287 return(PKT_ALIAS_IGNORED); 288 } 289 290 static int 291 IcmpAliasIn2(struct ip *pip) 292 { 293 /* 294 Alias incoming ICMP error messages containing 295 IP header and first 64 bits of datagram. 296 */ 297 struct ip *ip; 298 struct icmp *ic, *ic2; 299 struct udphdr *ud; 300 struct tcphdr *tc; 301 struct alias_link *link; 302 303 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 304 ip = (struct ip *) ic->icmp_data; 305 306 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); 307 tc = (struct tcphdr *) ud; 308 ic2 = (struct icmp *) ud; 309 310 if (ip->ip_p == IPPROTO_UDP) 311 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, 312 ud->uh_dport, ud->uh_sport, 313 IPPROTO_UDP); 314 else if (ip->ip_p == IPPROTO_TCP) 315 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, 316 tc->th_dport, tc->th_sport, 317 IPPROTO_TCP); 318 else if (ip->ip_p == IPPROTO_ICMP) { 319 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 320 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id); 321 else 322 link = NULL; 323 } else 324 link = NULL; 325 326 if (link != NULL) 327 { 328 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) 329 { 330 u_short *sptr; 331 int accumulate; 332 struct in_addr original_address; 333 u_short original_port; 334 335 original_address = GetOriginalAddress(link); 336 original_port = GetOriginalPort(link); 337 338 /* Adjust ICMP checksum */ 339 sptr = (u_short *) &(ip->ip_src); 340 accumulate = *sptr++; 341 accumulate += *sptr; 342 sptr = (u_short *) &original_address; 343 accumulate -= *sptr++; 344 accumulate -= *sptr; 345 accumulate += ud->uh_sport; 346 accumulate -= original_port; 347 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 348 349 /* Un-alias address in IP header */ 350 DifferentialChecksum(&pip->ip_sum, 351 (u_short *) &original_address, 352 (u_short *) &pip->ip_dst, 353 2); 354 pip->ip_dst = original_address; 355 356 /* Un-alias address and port number of original IP packet 357 fragment contained in ICMP data section */ 358 ip->ip_src = original_address; 359 ud->uh_sport = original_port; 360 } 361 else if (pip->ip_p == IPPROTO_ICMP) 362 { 363 u_short *sptr; 364 int accumulate; 365 struct in_addr original_address; 366 u_short original_id; 367 368 original_address = GetOriginalAddress(link); 369 original_id = GetOriginalPort(link); 370 371 /* Adjust ICMP checksum */ 372 sptr = (u_short *) &(ip->ip_src); 373 accumulate = *sptr++; 374 accumulate += *sptr; 375 sptr = (u_short *) &original_address; 376 accumulate -= *sptr++; 377 accumulate -= *sptr; 378 accumulate += ic2->icmp_id; 379 accumulate -= original_id; 380 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 381 382 /* Un-alias address in IP header */ 383 DifferentialChecksum(&pip->ip_sum, 384 (u_short *) &original_address, 385 (u_short *) &pip->ip_dst, 386 2); 387 pip->ip_dst = original_address; 388 389 /* Un-alias address of original IP packet and sequence number of 390 embedded ICMP datagram */ 391 ip->ip_src = original_address; 392 ic2->icmp_id = original_id; 393 } 394 return(PKT_ALIAS_OK); 395 } 396 return(PKT_ALIAS_IGNORED); 397 } 398 399 static int 400 IcmpAliasIn3(struct ip *pip) 401 { 402 struct in_addr original_address; 403 404 original_address = FindOriginalAddress(pip->ip_dst); 405 DifferentialChecksum(&pip->ip_sum, 406 (u_short *) &original_address, 407 (u_short *) &pip->ip_dst, 408 2); 409 pip->ip_dst = original_address; 410 411 return PKT_ALIAS_OK; 412 } 413 414 415 static int 416 IcmpAliasIn(struct ip *pip) 417 { 418 int iresult; 419 struct icmp *ic; 420 421 /* Return if proxy-only mode is enabled */ 422 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 423 return PKT_ALIAS_OK; 424 425 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 426 427 iresult = PKT_ALIAS_IGNORED; 428 switch (ic->icmp_type) 429 { 430 case ICMP_ECHOREPLY: 431 case ICMP_TSTAMPREPLY: 432 if (ic->icmp_code == 0) 433 { 434 iresult = IcmpAliasIn1(pip); 435 } 436 break; 437 case ICMP_UNREACH: 438 case ICMP_SOURCEQUENCH: 439 case ICMP_TIMXCEED: 440 case ICMP_PARAMPROB: 441 iresult = IcmpAliasIn2(pip); 442 break; 443 case ICMP_ECHO: 444 case ICMP_TSTAMP: 445 iresult = IcmpAliasIn3(pip); 446 break; 447 } 448 return(iresult); 449 } 450 451 452 static int 453 IcmpAliasOut1(struct ip *pip) 454 { 455 /* 456 Alias ICMP echo and timestamp packets 457 */ 458 struct alias_link *link; 459 struct icmp *ic; 460 461 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 462 463 /* Save overwritten data for when echo packet returns */ 464 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id); 465 if (link != NULL) 466 { 467 u_short alias_id; 468 int accumulate; 469 470 alias_id = GetAliasPort(link); 471 472 /* Since data field is being modified, adjust ICMP checksum */ 473 accumulate = ic->icmp_id; 474 accumulate -= alias_id; 475 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 476 477 /* Alias sequence number */ 478 ic->icmp_id = alias_id; 479 480 /* Change source address */ 481 { 482 struct in_addr alias_address; 483 484 alias_address = GetAliasAddress(link); 485 DifferentialChecksum(&pip->ip_sum, 486 (u_short *) &alias_address, 487 (u_short *) &pip->ip_src, 488 2); 489 pip->ip_src = alias_address; 490 } 491 492 return(PKT_ALIAS_OK); 493 } 494 return(PKT_ALIAS_IGNORED); 495 } 496 497 498 static int 499 IcmpAliasOut2(struct ip *pip) 500 { 501 /* 502 Alias outgoing ICMP error messages containing 503 IP header and first 64 bits of datagram. 504 */ 505 struct ip *ip; 506 struct icmp *ic, *ic2; 507 struct udphdr *ud; 508 struct tcphdr *tc; 509 struct alias_link *link; 510 511 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 512 ip = (struct ip *) ic->icmp_data; 513 514 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); 515 tc = (struct tcphdr *) ud; 516 ic2 = (struct icmp *) ud; 517 518 if (ip->ip_p == IPPROTO_UDP) 519 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src, 520 ud->uh_dport, ud->uh_sport, 521 IPPROTO_UDP); 522 else if (ip->ip_p == IPPROTO_TCP) 523 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src, 524 tc->th_dport, tc->th_sport, 525 IPPROTO_TCP); 526 else if (ip->ip_p == IPPROTO_ICMP) { 527 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 528 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id); 529 else 530 link = NULL; 531 } else 532 link = NULL; 533 534 if (link != NULL) 535 { 536 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) 537 { 538 u_short *sptr; 539 int accumulate; 540 struct in_addr alias_address; 541 u_short alias_port; 542 543 alias_address = GetAliasAddress(link); 544 alias_port = GetAliasPort(link); 545 546 /* Adjust ICMP checksum */ 547 sptr = (u_short *) &(ip->ip_dst); 548 accumulate = *sptr++; 549 accumulate += *sptr; 550 sptr = (u_short *) &alias_address; 551 accumulate -= *sptr++; 552 accumulate -= *sptr; 553 accumulate += ud->uh_dport; 554 accumulate -= alias_port; 555 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 556 557 /* Alias address in IP header */ 558 DifferentialChecksum(&pip->ip_sum, 559 (u_short *) &alias_address, 560 (u_short *) &pip->ip_src, 561 2); 562 pip->ip_src = alias_address; 563 564 /* Alias address and port number of original IP packet 565 fragment contained in ICMP data section */ 566 ip->ip_dst = alias_address; 567 ud->uh_dport = alias_port; 568 } 569 else if (pip->ip_p == IPPROTO_ICMP) 570 { 571 u_short *sptr; 572 int accumulate; 573 struct in_addr alias_address; 574 u_short alias_id; 575 576 alias_address = GetAliasAddress(link); 577 alias_id = GetAliasPort(link); 578 579 /* Adjust ICMP checksum */ 580 sptr = (u_short *) &(ip->ip_dst); 581 accumulate = *sptr++; 582 accumulate += *sptr; 583 sptr = (u_short *) &alias_address; 584 accumulate -= *sptr++; 585 accumulate -= *sptr; 586 accumulate += ic2->icmp_id; 587 accumulate -= alias_id; 588 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 589 590 /* Alias address in IP header */ 591 DifferentialChecksum(&pip->ip_sum, 592 (u_short *) &alias_address, 593 (u_short *) &pip->ip_src, 594 2); 595 pip->ip_src = alias_address; 596 597 /* Alias address of original IP packet and sequence number of 598 embedded ICMP datagram */ 599 ip->ip_dst = alias_address; 600 ic2->icmp_id = alias_id; 601 } 602 return(PKT_ALIAS_OK); 603 } 604 return(PKT_ALIAS_IGNORED); 605 } 606 607 608 static int 609 IcmpAliasOut3(struct ip *pip) 610 { 611 /* 612 Handle outgoing echo and timestamp replies. The 613 only thing which is done in this case is to alias 614 the source IP address of the packet. 615 */ 616 struct in_addr alias_addr; 617 618 alias_addr = FindAliasAddress(pip->ip_src); 619 DifferentialChecksum(&pip->ip_sum, 620 (u_short *) &alias_addr, 621 (u_short *) &pip->ip_src, 622 2); 623 pip->ip_src = alias_addr; 624 625 return PKT_ALIAS_OK; 626 } 627 628 629 static int 630 IcmpAliasOut(struct ip *pip) 631 { 632 int iresult; 633 struct icmp *ic; 634 635 /* Return if proxy-only mode is enabled */ 636 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 637 return PKT_ALIAS_OK; 638 639 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 640 641 iresult = PKT_ALIAS_IGNORED; 642 switch (ic->icmp_type) 643 { 644 case ICMP_ECHO: 645 case ICMP_TSTAMP: 646 if (ic->icmp_code == 0) 647 { 648 iresult = IcmpAliasOut1(pip); 649 } 650 break; 651 case ICMP_UNREACH: 652 case ICMP_SOURCEQUENCH: 653 case ICMP_TIMXCEED: 654 case ICMP_PARAMPROB: 655 iresult = IcmpAliasOut2(pip); 656 break; 657 case ICMP_ECHOREPLY: 658 case ICMP_TSTAMPREPLY: 659 iresult = IcmpAliasOut3(pip); 660 } 661 return(iresult); 662 } 663 664 665 666 static int 667 ProtoAliasIn(struct ip *pip) 668 { 669 /* 670 Handle incoming IP packets. The 671 only thing which is done in this case is to alias 672 the dest IP address of the packet to our inside 673 machine. 674 */ 675 struct alias_link *link; 676 677 /* Return if proxy-only mode is enabled */ 678 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 679 return PKT_ALIAS_OK; 680 681 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p); 682 if (link != NULL) 683 { 684 struct in_addr original_address; 685 686 original_address = GetOriginalAddress(link); 687 688 /* Restore original IP address */ 689 DifferentialChecksum(&pip->ip_sum, 690 (u_short *) &original_address, 691 (u_short *) &pip->ip_dst, 692 2); 693 pip->ip_dst = original_address; 694 695 return(PKT_ALIAS_OK); 696 } 697 return(PKT_ALIAS_IGNORED); 698 } 699 700 701 static int 702 ProtoAliasOut(struct ip *pip) 703 { 704 /* 705 Handle outgoing IP packets. The 706 only thing which is done in this case is to alias 707 the source IP address of the packet. 708 */ 709 struct alias_link *link; 710 711 /* Return if proxy-only mode is enabled */ 712 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 713 return PKT_ALIAS_OK; 714 715 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p); 716 if (link != NULL) 717 { 718 struct in_addr alias_address; 719 720 alias_address = GetAliasAddress(link); 721 722 /* Change source address */ 723 DifferentialChecksum(&pip->ip_sum, 724 (u_short *) &alias_address, 725 (u_short *) &pip->ip_src, 726 2); 727 pip->ip_src = alias_address; 728 729 return(PKT_ALIAS_OK); 730 } 731 return(PKT_ALIAS_IGNORED); 732 } 733 734 735 static int 736 GreAliasIn(struct ip *pip) 737 { 738 u_short call_id; 739 struct alias_link *link; 740 741 /* Return if proxy-only mode is enabled. */ 742 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 743 return (PKT_ALIAS_OK); 744 745 if (PptpGetCallID(pip, &call_id)) { 746 if ((link = FindPptpIn(pip->ip_src, pip->ip_dst, call_id)) != NULL) { 747 struct in_addr alias_address; 748 struct in_addr original_address; 749 750 alias_address = GetAliasAddress(link); 751 original_address = GetOriginalAddress(link); 752 PptpSetCallID(pip, GetOriginalPort(link)); 753 754 /* Restore original IP address. */ 755 DifferentialChecksum(&pip->ip_sum, 756 (u_short *)&original_address, 757 (u_short *)&pip->ip_dst, 758 2); 759 pip->ip_dst = original_address; 760 761 return (PKT_ALIAS_OK); 762 } else 763 return (PKT_ALIAS_IGNORED); 764 } else 765 return ProtoAliasIn(pip); 766 } 767 768 769 static int 770 UdpAliasIn(struct ip *pip) 771 { 772 struct udphdr *ud; 773 struct alias_link *link; 774 775 /* Return if proxy-only mode is enabled */ 776 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 777 return PKT_ALIAS_OK; 778 779 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 780 781 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 782 ud->uh_sport, ud->uh_dport, 783 IPPROTO_UDP); 784 if (link != NULL) 785 { 786 struct in_addr alias_address; 787 struct in_addr original_address; 788 u_short alias_port; 789 int accumulate; 790 u_short *sptr; 791 int r = 0; 792 793 alias_address = GetAliasAddress(link); 794 original_address = GetOriginalAddress(link); 795 alias_port = ud->uh_dport; 796 ud->uh_dport = GetOriginalPort(link); 797 798 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 799 if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 800 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER ) 801 { 802 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport); 803 } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 804 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER ) 805 { 806 r = AliasHandleUdpNbtNS(pip, link, 807 &alias_address, 808 &alias_port, 809 &original_address, 810 &ud->uh_dport ); 811 } 812 813 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 814 AliasHandleCUSeeMeIn(pip, original_address); 815 816 /* If UDP checksum is not zero, then adjust since destination port */ 817 /* is being unaliased and destination port is being altered. */ 818 if (ud->uh_sum != 0) 819 { 820 accumulate = alias_port; 821 accumulate -= ud->uh_dport; 822 sptr = (u_short *) &alias_address; 823 accumulate += *sptr++; 824 accumulate += *sptr; 825 sptr = (u_short *) &original_address; 826 accumulate -= *sptr++; 827 accumulate -= *sptr; 828 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 829 } 830 831 /* Restore original IP address */ 832 DifferentialChecksum(&pip->ip_sum, 833 (u_short *) &original_address, 834 (u_short *) &pip->ip_dst, 835 2); 836 pip->ip_dst = original_address; 837 838 /* 839 * If we cannot figure out the packet, ignore it. 840 */ 841 if (r < 0) 842 return(PKT_ALIAS_IGNORED); 843 else 844 return(PKT_ALIAS_OK); 845 } 846 return(PKT_ALIAS_IGNORED); 847 } 848 849 static int 850 UdpAliasOut(struct ip *pip) 851 { 852 struct udphdr *ud; 853 struct alias_link *link; 854 855 /* Return if proxy-only mode is enabled */ 856 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 857 return PKT_ALIAS_OK; 858 859 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 860 861 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 862 ud->uh_sport, ud->uh_dport, 863 IPPROTO_UDP); 864 if (link != NULL) 865 { 866 u_short alias_port; 867 struct in_addr alias_address; 868 869 alias_address = GetAliasAddress(link); 870 alias_port = GetAliasPort(link); 871 872 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 873 AliasHandleCUSeeMeOut(pip, link); 874 875 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 876 if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 877 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER ) 878 { 879 AliasHandleUdpNbt(pip, link, &alias_address, alias_port); 880 } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 881 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER ) 882 { 883 AliasHandleUdpNbtNS(pip, link, 884 &pip->ip_src, 885 &ud->uh_sport, 886 &alias_address, 887 &alias_port); 888 } 889 890 /* If UDP checksum is not zero, adjust since source port is */ 891 /* being aliased and source address is being altered */ 892 if (ud->uh_sum != 0) 893 { 894 int accumulate; 895 u_short *sptr; 896 897 accumulate = ud->uh_sport; 898 accumulate -= alias_port; 899 sptr = (u_short *) &(pip->ip_src); 900 accumulate += *sptr++; 901 accumulate += *sptr; 902 sptr = (u_short *) &alias_address; 903 accumulate -= *sptr++; 904 accumulate -= *sptr; 905 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 906 } 907 908 /* Put alias port in UDP header */ 909 ud->uh_sport = alias_port; 910 911 /* Change source address */ 912 DifferentialChecksum(&pip->ip_sum, 913 (u_short *) &alias_address, 914 (u_short *) &pip->ip_src, 915 2); 916 pip->ip_src = alias_address; 917 918 return(PKT_ALIAS_OK); 919 } 920 return(PKT_ALIAS_IGNORED); 921 } 922 923 924 925 static int 926 TcpAliasIn(struct ip *pip) 927 { 928 struct tcphdr *tc; 929 struct alias_link *link; 930 931 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 932 933 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 934 tc->th_sport, tc->th_dport, 935 IPPROTO_TCP); 936 if (link != NULL) 937 { 938 struct in_addr alias_address; 939 struct in_addr original_address; 940 struct in_addr proxy_address; 941 u_short alias_port; 942 u_short proxy_port; 943 int accumulate; 944 u_short *sptr; 945 946 /* Special processing for IP encoding protocols */ 947 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 948 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 949 AliasHandlePptpIn(pip, link); 950 951 alias_address = GetAliasAddress(link); 952 original_address = GetOriginalAddress(link); 953 proxy_address = GetProxyAddress(link); 954 alias_port = tc->th_dport; 955 tc->th_dport = GetOriginalPort(link); 956 proxy_port = GetProxyPort(link); 957 958 /* Adjust TCP checksum since destination port is being unaliased */ 959 /* and destination port is being altered. */ 960 accumulate = alias_port; 961 accumulate -= tc->th_dport; 962 sptr = (u_short *) &alias_address; 963 accumulate += *sptr++; 964 accumulate += *sptr; 965 sptr = (u_short *) &original_address; 966 accumulate -= *sptr++; 967 accumulate -= *sptr; 968 969 /* If this is a proxy, then modify the TCP source port and 970 checksum accumulation */ 971 if (proxy_port != 0) 972 { 973 accumulate += tc->th_sport; 974 tc->th_sport = proxy_port; 975 accumulate -= tc->th_sport; 976 977 sptr = (u_short *) &pip->ip_src; 978 accumulate += *sptr++; 979 accumulate += *sptr; 980 sptr = (u_short *) &proxy_address; 981 accumulate -= *sptr++; 982 accumulate -= *sptr; 983 } 984 985 /* See if ACK number needs to be modified */ 986 if (GetAckModified(link) == 1) 987 { 988 int delta; 989 990 delta = GetDeltaAckIn(pip, link); 991 if (delta != 0) 992 { 993 sptr = (u_short *) &tc->th_ack; 994 accumulate += *sptr++; 995 accumulate += *sptr; 996 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 997 sptr = (u_short *) &tc->th_ack; 998 accumulate -= *sptr++; 999 accumulate -= *sptr; 1000 } 1001 } 1002 1003 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1004 1005 /* Restore original IP address */ 1006 sptr = (u_short *) &pip->ip_dst; 1007 accumulate = *sptr++; 1008 accumulate += *sptr; 1009 pip->ip_dst = original_address; 1010 sptr = (u_short *) &pip->ip_dst; 1011 accumulate -= *sptr++; 1012 accumulate -= *sptr; 1013 1014 /* If this is a transparent proxy packet, then modify the source 1015 address */ 1016 if (proxy_address.s_addr != 0) 1017 { 1018 sptr = (u_short *) &pip->ip_src; 1019 accumulate += *sptr++; 1020 accumulate += *sptr; 1021 pip->ip_src = proxy_address; 1022 sptr = (u_short *) &pip->ip_src; 1023 accumulate -= *sptr++; 1024 accumulate -= *sptr; 1025 } 1026 1027 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1028 1029 /* Monitor TCP connection state */ 1030 TcpMonitorIn(pip, link); 1031 1032 return(PKT_ALIAS_OK); 1033 } 1034 return(PKT_ALIAS_IGNORED); 1035 } 1036 1037 static int 1038 TcpAliasOut(struct ip *pip, int maxpacketsize) 1039 { 1040 int proxy_type; 1041 u_short dest_port; 1042 u_short proxy_server_port; 1043 struct in_addr dest_address; 1044 struct in_addr proxy_server_address; 1045 struct tcphdr *tc; 1046 struct alias_link *link; 1047 1048 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 1049 1050 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port); 1051 1052 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 1053 return PKT_ALIAS_OK; 1054 1055 /* If this is a transparent proxy, save original destination, 1056 then alter the destination and adjust checksums */ 1057 dest_port = tc->th_dport; 1058 dest_address = pip->ip_dst; 1059 if (proxy_type != 0) 1060 { 1061 int accumulate; 1062 u_short *sptr; 1063 1064 accumulate = tc->th_dport; 1065 tc->th_dport = proxy_server_port; 1066 accumulate -= tc->th_dport; 1067 1068 sptr = (u_short *) &(pip->ip_dst); 1069 accumulate += *sptr++; 1070 accumulate += *sptr; 1071 sptr = (u_short *) &proxy_server_address; 1072 accumulate -= *sptr++; 1073 accumulate -= *sptr; 1074 1075 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1076 1077 sptr = (u_short *) &(pip->ip_dst); 1078 accumulate = *sptr++; 1079 accumulate += *sptr; 1080 pip->ip_dst = proxy_server_address; 1081 sptr = (u_short *) &(pip->ip_dst); 1082 accumulate -= *sptr++; 1083 accumulate -= *sptr; 1084 1085 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1086 } 1087 1088 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 1089 tc->th_sport, tc->th_dport, 1090 IPPROTO_TCP); 1091 if (link !=NULL) 1092 { 1093 u_short alias_port; 1094 struct in_addr alias_address; 1095 int accumulate; 1096 u_short *sptr; 1097 1098 /* Save original destination address, if this is a proxy packet. 1099 Also modify packet to include destination encoding. */ 1100 if (proxy_type != 0) 1101 { 1102 SetProxyPort(link, dest_port); 1103 SetProxyAddress(link, dest_address); 1104 ProxyModify(link, pip, maxpacketsize, proxy_type); 1105 } 1106 1107 /* Get alias address and port */ 1108 alias_port = GetAliasPort(link); 1109 alias_address = GetAliasAddress(link); 1110 1111 /* Monitor TCP connection state */ 1112 TcpMonitorOut(pip, link); 1113 1114 /* Special processing for IP encoding protocols */ 1115 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER 1116 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) 1117 AliasHandleFtpOut(pip, link, maxpacketsize); 1118 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 1119 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) 1120 AliasHandleIrcOut(pip, link, maxpacketsize); 1121 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1 1122 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1 1123 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2 1124 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 1125 AliasHandleRtspOut(pip, link, maxpacketsize); 1126 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 1127 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 1128 AliasHandlePptpOut(pip, link); 1129 1130 /* Adjust TCP checksum since source port is being aliased */ 1131 /* and source address is being altered */ 1132 accumulate = tc->th_sport; 1133 tc->th_sport = alias_port; 1134 accumulate -= tc->th_sport; 1135 1136 sptr = (u_short *) &(pip->ip_src); 1137 accumulate += *sptr++; 1138 accumulate += *sptr; 1139 sptr = (u_short *) &alias_address; 1140 accumulate -= *sptr++; 1141 accumulate -= *sptr; 1142 1143 /* Modify sequence number if necessary */ 1144 if (GetAckModified(link) == 1) 1145 { 1146 int delta; 1147 1148 delta = GetDeltaSeqOut(pip, link); 1149 if (delta != 0) 1150 { 1151 sptr = (u_short *) &tc->th_seq; 1152 accumulate += *sptr++; 1153 accumulate += *sptr; 1154 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1155 sptr = (u_short *) &tc->th_seq; 1156 accumulate -= *sptr++; 1157 accumulate -= *sptr; 1158 } 1159 } 1160 1161 ADJUST_CHECKSUM(accumulate, tc->th_sum) 1162 1163 /* Change source address */ 1164 sptr = (u_short *) &(pip->ip_src); 1165 accumulate = *sptr++; 1166 accumulate += *sptr; 1167 pip->ip_src = alias_address; 1168 sptr = (u_short *) &(pip->ip_src); 1169 accumulate -= *sptr++; 1170 accumulate -= *sptr; 1171 1172 ADJUST_CHECKSUM(accumulate, pip->ip_sum) 1173 1174 return(PKT_ALIAS_OK); 1175 } 1176 return(PKT_ALIAS_IGNORED); 1177 } 1178 1179 1180 1181 1182 /* Fragment Handling 1183 1184 FragmentIn() 1185 FragmentOut() 1186 1187 The packet aliasing module has a limited ability for handling IP 1188 fragments. If the ICMP, TCP or UDP header is in the first fragment 1189 received, then the ID number of the IP packet is saved, and other 1190 fragments are identified according to their ID number and IP address 1191 they were sent from. Pointers to unresolved fragments can also be 1192 saved and recalled when a header fragment is seen. 1193 */ 1194 1195 /* Local prototypes */ 1196 static int FragmentIn(struct ip *); 1197 static int FragmentOut(struct ip *); 1198 1199 1200 static int 1201 FragmentIn(struct ip *pip) 1202 { 1203 struct alias_link *link; 1204 1205 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id); 1206 if (link != NULL) 1207 { 1208 struct in_addr original_address; 1209 1210 GetFragmentAddr(link, &original_address); 1211 DifferentialChecksum(&pip->ip_sum, 1212 (u_short *) &original_address, 1213 (u_short *) &pip->ip_dst, 1214 2); 1215 pip->ip_dst = original_address; 1216 1217 return(PKT_ALIAS_OK); 1218 } 1219 return(PKT_ALIAS_UNRESOLVED_FRAGMENT); 1220 } 1221 1222 1223 static int 1224 FragmentOut(struct ip *pip) 1225 { 1226 struct in_addr alias_address; 1227 1228 alias_address = FindAliasAddress(pip->ip_src); 1229 DifferentialChecksum(&pip->ip_sum, 1230 (u_short *) &alias_address, 1231 (u_short *) &pip->ip_src, 1232 2); 1233 pip->ip_src = alias_address; 1234 1235 return(PKT_ALIAS_OK); 1236 } 1237 1238 1239 1240 1241 1242 1243 /* Outside World Access 1244 1245 PacketAliasSaveFragment() 1246 PacketAliasGetFragment() 1247 PacketAliasFragmentIn() 1248 PacketAliasIn() 1249 PacketAliasOut() 1250 PacketUnaliasOut() 1251 1252 (prototypes in alias.h) 1253 */ 1254 1255 1256 int 1257 PacketAliasSaveFragment(char *ptr) 1258 { 1259 int iresult; 1260 struct alias_link *link; 1261 struct ip *pip; 1262 1263 pip = (struct ip *) ptr; 1264 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id); 1265 iresult = PKT_ALIAS_ERROR; 1266 if (link != NULL) 1267 { 1268 SetFragmentPtr(link, ptr); 1269 iresult = PKT_ALIAS_OK; 1270 } 1271 return(iresult); 1272 } 1273 1274 1275 char * 1276 PacketAliasGetFragment(char *ptr) 1277 { 1278 struct alias_link *link; 1279 char *fptr; 1280 struct ip *pip; 1281 1282 pip = (struct ip *) ptr; 1283 link = FindFragmentPtr(pip->ip_src, pip->ip_id); 1284 if (link != NULL) 1285 { 1286 GetFragmentPtr(link, &fptr); 1287 SetFragmentPtr(link, NULL); 1288 SetExpire(link, 0); /* Deletes link */ 1289 1290 return(fptr); 1291 } 1292 else 1293 { 1294 return(NULL); 1295 } 1296 } 1297 1298 1299 void 1300 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased 1301 header fragment */ 1302 char *ptr_fragment /* Points to fragment which must 1303 be de-aliased */ 1304 ) 1305 { 1306 struct ip *pip; 1307 struct ip *fpip; 1308 1309 pip = (struct ip *) ptr; 1310 fpip = (struct ip *) ptr_fragment; 1311 1312 DifferentialChecksum(&fpip->ip_sum, 1313 (u_short *) &pip->ip_dst, 1314 (u_short *) &fpip->ip_dst, 1315 2); 1316 fpip->ip_dst = pip->ip_dst; 1317 } 1318 1319 1320 int 1321 PacketAliasIn(char *ptr, int maxpacketsize) 1322 { 1323 struct in_addr alias_addr; 1324 struct ip *pip; 1325 int iresult; 1326 1327 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1328 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1329 iresult = PacketAliasOut(ptr, maxpacketsize); 1330 packetAliasMode |= PKT_ALIAS_REVERSE; 1331 return iresult; 1332 } 1333 1334 HouseKeeping(); 1335 ClearCheckNewLink(); 1336 pip = (struct ip *) ptr; 1337 alias_addr = pip->ip_dst; 1338 1339 /* Defense against mangled packets */ 1340 if (ntohs(pip->ip_len) > maxpacketsize 1341 || (pip->ip_hl<<2) > maxpacketsize) 1342 return PKT_ALIAS_IGNORED; 1343 1344 iresult = PKT_ALIAS_IGNORED; 1345 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 ) 1346 { 1347 switch (pip->ip_p) 1348 { 1349 case IPPROTO_ICMP: 1350 iresult = IcmpAliasIn(pip); 1351 break; 1352 case IPPROTO_UDP: 1353 iresult = UdpAliasIn(pip); 1354 break; 1355 case IPPROTO_TCP: 1356 iresult = TcpAliasIn(pip); 1357 break; 1358 case IPPROTO_GRE: 1359 iresult = GreAliasIn(pip); 1360 break; 1361 default: 1362 iresult = ProtoAliasIn(pip); 1363 break; 1364 } 1365 1366 if (ntohs(pip->ip_off) & IP_MF) 1367 { 1368 struct alias_link *link; 1369 1370 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id); 1371 if (link != NULL) 1372 { 1373 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1374 SetFragmentAddr(link, pip->ip_dst); 1375 } 1376 else 1377 { 1378 iresult = PKT_ALIAS_ERROR; 1379 } 1380 } 1381 } 1382 else 1383 { 1384 iresult = FragmentIn(pip); 1385 } 1386 1387 return(iresult); 1388 } 1389 1390 1391 1392 /* Unregistered address ranges */ 1393 1394 /* 10.0.0.0 -> 10.255.255.255 */ 1395 #define UNREG_ADDR_A_LOWER 0x0a000000 1396 #define UNREG_ADDR_A_UPPER 0x0affffff 1397 1398 /* 172.16.0.0 -> 172.31.255.255 */ 1399 #define UNREG_ADDR_B_LOWER 0xac100000 1400 #define UNREG_ADDR_B_UPPER 0xac1fffff 1401 1402 /* 192.168.0.0 -> 192.168.255.255 */ 1403 #define UNREG_ADDR_C_LOWER 0xc0a80000 1404 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1405 1406 int 1407 PacketAliasOut(char *ptr, /* valid IP packet */ 1408 int maxpacketsize /* How much the packet data may grow 1409 (FTP and IRC inline changes) */ 1410 ) 1411 { 1412 int iresult; 1413 struct in_addr addr_save; 1414 struct ip *pip; 1415 1416 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1417 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1418 iresult = PacketAliasIn(ptr, maxpacketsize); 1419 packetAliasMode |= PKT_ALIAS_REVERSE; 1420 return iresult; 1421 } 1422 1423 HouseKeeping(); 1424 ClearCheckNewLink(); 1425 pip = (struct ip *) ptr; 1426 1427 /* Defense against mangled packets */ 1428 if (ntohs(pip->ip_len) > maxpacketsize 1429 || (pip->ip_hl<<2) > maxpacketsize) 1430 return PKT_ALIAS_IGNORED; 1431 1432 addr_save = GetDefaultAliasAddress(); 1433 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) 1434 { 1435 u_long addr; 1436 int iclass; 1437 1438 iclass = 0; 1439 addr = ntohl(pip->ip_src.s_addr); 1440 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1441 iclass = 3; 1442 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1443 iclass = 2; 1444 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1445 iclass = 1; 1446 1447 if (iclass == 0) 1448 { 1449 SetDefaultAliasAddress(pip->ip_src); 1450 } 1451 } 1452 1453 iresult = PKT_ALIAS_IGNORED; 1454 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) 1455 { 1456 switch (pip->ip_p) 1457 { 1458 case IPPROTO_ICMP: 1459 iresult = IcmpAliasOut(pip); 1460 break; 1461 case IPPROTO_UDP: 1462 iresult = UdpAliasOut(pip); 1463 break; 1464 case IPPROTO_TCP: 1465 iresult = TcpAliasOut(pip, maxpacketsize); 1466 break; 1467 default: 1468 iresult = ProtoAliasOut(pip); 1469 break; 1470 } 1471 } 1472 else 1473 { 1474 iresult = FragmentOut(pip); 1475 } 1476 1477 SetDefaultAliasAddress(addr_save); 1478 return(iresult); 1479 } 1480 1481 int 1482 PacketUnaliasOut(char *ptr, /* valid IP packet */ 1483 int maxpacketsize /* for error checking */ 1484 ) 1485 { 1486 struct ip *pip; 1487 struct icmp *ic; 1488 struct udphdr *ud; 1489 struct tcphdr *tc; 1490 struct alias_link *link; 1491 int iresult = PKT_ALIAS_IGNORED; 1492 1493 pip = (struct ip *) ptr; 1494 1495 /* Defense against mangled packets */ 1496 if (ntohs(pip->ip_len) > maxpacketsize 1497 || (pip->ip_hl<<2) > maxpacketsize) 1498 return(iresult); 1499 1500 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 1501 tc = (struct tcphdr *) ud; 1502 ic = (struct icmp *) ud; 1503 1504 /* Find a link */ 1505 if (pip->ip_p == IPPROTO_UDP) 1506 link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src, 1507 ud->uh_dport, ud->uh_sport, 1508 IPPROTO_UDP); 1509 else if (pip->ip_p == IPPROTO_TCP) 1510 link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src, 1511 tc->th_dport, tc->th_sport, 1512 IPPROTO_TCP); 1513 else if (pip->ip_p == IPPROTO_ICMP) 1514 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id); 1515 else 1516 link = NULL; 1517 1518 /* Change it from an aliased packet to an unaliased packet */ 1519 if (link != NULL) 1520 { 1521 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) 1522 { 1523 u_short *sptr; 1524 int accumulate; 1525 struct in_addr original_address; 1526 u_short original_port; 1527 1528 original_address = GetOriginalAddress(link); 1529 original_port = GetOriginalPort(link); 1530 1531 /* Adjust TCP/UDP checksum */ 1532 sptr = (u_short *) &(pip->ip_src); 1533 accumulate = *sptr++; 1534 accumulate += *sptr; 1535 sptr = (u_short *) &original_address; 1536 accumulate -= *sptr++; 1537 accumulate -= *sptr; 1538 1539 if (pip->ip_p == IPPROTO_UDP) { 1540 accumulate += ud->uh_sport; 1541 accumulate -= original_port; 1542 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 1543 } else { 1544 accumulate += tc->th_sport; 1545 accumulate -= original_port; 1546 ADJUST_CHECKSUM(accumulate, tc->th_sum) 1547 } 1548 1549 /* Adjust IP checksum */ 1550 DifferentialChecksum(&pip->ip_sum, 1551 (u_short *) &original_address, 1552 (u_short *) &pip->ip_src, 1553 2); 1554 1555 /* Un-alias source address and port number */ 1556 pip->ip_src = original_address; 1557 if (pip->ip_p == IPPROTO_UDP) 1558 ud->uh_sport = original_port; 1559 else 1560 tc->th_sport = original_port; 1561 1562 iresult = PKT_ALIAS_OK; 1563 1564 } else if (pip->ip_p == IPPROTO_ICMP) { 1565 1566 u_short *sptr; 1567 int accumulate; 1568 struct in_addr original_address; 1569 u_short original_id; 1570 1571 original_address = GetOriginalAddress(link); 1572 original_id = GetOriginalPort(link); 1573 1574 /* Adjust ICMP checksum */ 1575 sptr = (u_short *) &(pip->ip_src); 1576 accumulate = *sptr++; 1577 accumulate += *sptr; 1578 sptr = (u_short *) &original_address; 1579 accumulate -= *sptr++; 1580 accumulate -= *sptr; 1581 accumulate += ic->icmp_id; 1582 accumulate -= original_id; 1583 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) 1584 1585 /* Adjust IP checksum */ 1586 DifferentialChecksum(&pip->ip_sum, 1587 (u_short *) &original_address, 1588 (u_short *) &pip->ip_src, 1589 2); 1590 1591 /* Un-alias source address and port number */ 1592 pip->ip_src = original_address; 1593 ic->icmp_id = original_id; 1594 1595 iresult = PKT_ALIAS_OK; 1596 } 1597 } 1598 return(iresult); 1599 1600 } 1601