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