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