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 do 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 */ 82 83 #include <stdio.h> 84 #include <unistd.h> 85 86 #include <sys/param.h> 87 #include <sys/types.h> 88 89 #include <netinet/in_systm.h> 90 #include <netinet/in.h> 91 #include <netinet/ip.h> 92 #include <netinet/ip_icmp.h> 93 #include <netinet/tcp.h> 94 #include <netinet/udp.h> 95 96 #ifndef IPPROTO_GRE 97 #define IPPROTO_GRE 47 98 #endif 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 FTP_CONTROL_PORT_NUMBER 21 107 #define IRC_CONTROL_PORT_NUMBER_1 6667 108 #define IRC_CONTROL_PORT_NUMBER_2 6668 109 #define CUSEEME_PORT_NUMBER 7648 110 111 112 113 114 /* TCP Handling Routines 115 116 TcpMonitorIn() -- These routines monitor TCP connections, and 117 TcpMonitorOut() delete a link when a connection is closed. 118 119 These routines look for SYN, ACK and RST flags to determine when TCP 120 connections open and close. When a TCP connection closes, the data 121 structure containing packet aliasing information is deleted after 122 a timeout period. 123 */ 124 125 /* Local prototypes */ 126 static void TcpMonitorIn(struct ip *, struct alias_link *); 127 128 static void TcpMonitorOut(struct ip *, struct alias_link *); 129 130 131 static void 132 TcpMonitorIn(struct ip *pip, struct alias_link *link) 133 { 134 struct tcphdr *tc; 135 136 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 137 138 switch (GetStateIn(link)) 139 { 140 case ALIAS_TCP_STATE_NOT_CONNECTED: 141 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 146 || tc->th_flags & TH_RST) 147 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED); 148 break; 149 } 150 } 151 152 static void 153 TcpMonitorOut(struct ip *pip, struct alias_link *link) 154 { 155 struct tcphdr *tc; 156 157 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 158 159 switch (GetStateOut(link)) 160 { 161 case ALIAS_TCP_STATE_NOT_CONNECTED: 162 if (tc->th_flags & TH_SYN) 163 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED); 164 break; 165 case ALIAS_TCP_STATE_CONNECTED: 166 if (tc->th_flags & TH_FIN 167 || tc->th_flags & 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 is 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 seqence 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 in_addr alias_addr; 495 struct ip *ip; 496 struct icmp *ic; 497 498 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 499 ip = (struct ip *) ic->icmp_data; 500 501 alias_addr = FindAliasAddress(ip->ip_src); 502 503 /* Alias destination address in IP fragment */ 504 DifferentialChecksum(&ic->icmp_cksum, 505 (u_short *) &alias_addr, 506 (u_short *) &ip->ip_dst, 507 2); 508 ip->ip_dst = alias_addr; 509 510 /* alias source address in IP header */ 511 DifferentialChecksum(&pip->ip_sum, 512 (u_short *) &alias_addr, 513 (u_short *) &pip->ip_src, 514 2); 515 pip->ip_src = alias_addr; 516 517 return PKT_ALIAS_OK; 518 } 519 520 521 static int 522 IcmpAliasOut3(struct ip *pip) 523 { 524 /* 525 Handle outgoing echo and timestamp replies. The 526 only thing which is done in this case is to alias 527 the source IP address of the packet. 528 */ 529 struct in_addr alias_addr; 530 531 alias_addr = FindAliasAddress(pip->ip_src); 532 DifferentialChecksum(&pip->ip_sum, 533 (u_short *) &alias_addr, 534 (u_short *) &pip->ip_src, 535 2); 536 pip->ip_src = alias_addr; 537 538 return PKT_ALIAS_OK; 539 } 540 541 542 static int 543 IcmpAliasOut(struct ip *pip) 544 { 545 int iresult; 546 struct icmp *ic; 547 548 /* Return if proxy-only mode is enabled */ 549 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 550 return PKT_ALIAS_OK; 551 552 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 553 554 iresult = PKT_ALIAS_IGNORED; 555 switch (ic->icmp_type) 556 { 557 case ICMP_ECHO: 558 case ICMP_TSTAMP: 559 if (ic->icmp_code == 0) 560 { 561 iresult = IcmpAliasOut1(pip); 562 } 563 break; 564 case ICMP_UNREACH: 565 case ICMP_SOURCEQUENCH: 566 case ICMP_TIMXCEED: 567 case ICMP_PARAMPROB: 568 iresult = IcmpAliasOut2(pip); 569 break; 570 case ICMP_ECHOREPLY: 571 case ICMP_TSTAMPREPLY: 572 iresult = IcmpAliasOut3(pip); 573 } 574 return(iresult); 575 } 576 577 578 579 static int 580 PptpAliasIn(struct ip *pip) 581 { 582 /* 583 Handle incoming PPTP packets. The 584 only thing which is done in this case is to alias 585 the dest IP address of the packet to our inside 586 machine. 587 */ 588 struct in_addr alias_addr; 589 590 if (!GetPptpAlias (&alias_addr)) 591 return PKT_ALIAS_IGNORED; 592 593 if (pip->ip_src.s_addr != alias_addr.s_addr) { 594 595 DifferentialChecksum(&pip->ip_sum, 596 (u_short *) &alias_addr, 597 (u_short *) &pip->ip_dst, 598 2); 599 pip->ip_dst = alias_addr; 600 } 601 602 return PKT_ALIAS_OK; 603 } 604 605 606 static int 607 PptpAliasOut(struct ip *pip) 608 { 609 /* 610 Handle outgoing PPTP packets. The 611 only thing which is done in this case is to alias 612 the source IP address of the packet. 613 */ 614 struct in_addr alias_addr; 615 616 if (!GetPptpAlias (&alias_addr)) 617 return PKT_ALIAS_IGNORED; 618 619 if (pip->ip_src.s_addr == alias_addr.s_addr) { 620 621 alias_addr = FindAliasAddress(pip->ip_src); 622 DifferentialChecksum(&pip->ip_sum, 623 (u_short *) &alias_addr, 624 (u_short *) &pip->ip_src, 625 2); 626 pip->ip_src = alias_addr; 627 } 628 629 return PKT_ALIAS_OK; 630 } 631 632 633 634 static int 635 UdpAliasIn(struct ip *pip) 636 { 637 struct udphdr *ud; 638 struct alias_link *link; 639 640 /* Return if proxy-only mode is enabled */ 641 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 642 return PKT_ALIAS_OK; 643 644 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 645 646 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 647 ud->uh_sport, ud->uh_dport, 648 IPPROTO_UDP); 649 if (link != NULL) 650 { 651 struct in_addr alias_address; 652 struct in_addr original_address; 653 u_short alias_port; 654 int accumulate; 655 u_short *sptr; 656 int r = 0; 657 658 alias_address = GetAliasAddress(link); 659 original_address = GetOriginalAddress(link); 660 alias_port = ud->uh_dport; 661 ud->uh_dport = GetOriginalPort(link); 662 663 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 664 if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 665 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER ) 666 { 667 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport); 668 } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 669 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER ) 670 { 671 r = AliasHandleUdpNbtNS(pip, link, 672 &alias_address, 673 &alias_port, 674 &original_address, 675 &ud->uh_dport ); 676 } 677 678 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 679 AliasHandleCUSeeMeIn(pip, original_address); 680 681 /* If UDP checksum is not zero, then adjust since destination port */ 682 /* is being unaliased and destination port is being altered. */ 683 if (ud->uh_sum != 0) 684 { 685 accumulate = alias_port; 686 accumulate -= ud->uh_dport; 687 sptr = (u_short *) &alias_address; 688 accumulate += *sptr++; 689 accumulate += *sptr; 690 sptr = (u_short *) &original_address; 691 accumulate -= *sptr++; 692 accumulate -= *sptr; 693 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 694 } 695 696 /* Restore original IP address */ 697 DifferentialChecksum(&pip->ip_sum, 698 (u_short *) &original_address, 699 (u_short *) &pip->ip_dst, 700 2); 701 pip->ip_dst = original_address; 702 703 /* 704 * If we cannot figure out the packet, ignore it. 705 */ 706 if (r < 0) 707 return(PKT_ALIAS_IGNORED); 708 else 709 return(PKT_ALIAS_OK); 710 } 711 return(PKT_ALIAS_IGNORED); 712 } 713 714 static int 715 UdpAliasOut(struct ip *pip) 716 { 717 struct udphdr *ud; 718 struct alias_link *link; 719 720 /* Return if proxy-only mode is enabled */ 721 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 722 return PKT_ALIAS_OK; 723 724 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 725 726 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 727 ud->uh_sport, ud->uh_dport, 728 IPPROTO_UDP); 729 if (link != NULL) 730 { 731 u_short alias_port; 732 struct in_addr alias_address; 733 734 alias_address = GetAliasAddress(link); 735 alias_port = GetAliasPort(link); 736 737 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 738 AliasHandleCUSeeMeOut(pip, link); 739 740 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 741 if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 742 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER ) 743 { 744 AliasHandleUdpNbt(pip, link, &alias_address, alias_port); 745 } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 746 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER ) 747 { 748 AliasHandleUdpNbtNS(pip, link, 749 &pip->ip_src, 750 &ud->uh_sport, 751 &alias_address, 752 &alias_port); 753 } 754 755 /* If UDP checksum is not zero, adjust since source port is */ 756 /* being aliased and source address is being altered */ 757 if (ud->uh_sum != 0) 758 { 759 int accumulate; 760 u_short *sptr; 761 762 accumulate = ud->uh_sport; 763 accumulate -= alias_port; 764 sptr = (u_short *) &(pip->ip_src); 765 accumulate += *sptr++; 766 accumulate += *sptr; 767 sptr = (u_short *) &alias_address; 768 accumulate -= *sptr++; 769 accumulate -= *sptr; 770 ADJUST_CHECKSUM(accumulate, ud->uh_sum) 771 } 772 773 /* Put alias port in UDP header */ 774 ud->uh_sport = alias_port; 775 776 /* Change source address */ 777 DifferentialChecksum(&pip->ip_sum, 778 (u_short *) &alias_address, 779 (u_short *) &pip->ip_src, 780 2); 781 pip->ip_src = alias_address; 782 783 return(PKT_ALIAS_OK); 784 } 785 return(PKT_ALIAS_IGNORED); 786 } 787 788 789 790 static int 791 TcpAliasIn(struct ip *pip) 792 { 793 struct tcphdr *tc; 794 struct alias_link *link; 795 796 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 797 798 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 799 tc->th_sport, tc->th_dport, 800 IPPROTO_TCP); 801 if (link != NULL) 802 { 803 struct in_addr alias_address; 804 struct in_addr original_address; 805 struct in_addr proxy_address; 806 u_short alias_port; 807 u_short proxy_port; 808 int accumulate; 809 u_short *sptr; 810 811 alias_address = GetAliasAddress(link); 812 original_address = GetOriginalAddress(link); 813 proxy_address = GetProxyAddress(link); 814 alias_port = tc->th_dport; 815 tc->th_dport = GetOriginalPort(link); 816 proxy_port = GetProxyPort(link); 817 818 /* Adjust TCP checksum since destination port is being unaliased */ 819 /* and destination port is being altered. */ 820 accumulate = alias_port; 821 accumulate -= tc->th_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 829 /* If this is a proxy, then modify the tcp source port and 830 checksum accumulation */ 831 if (proxy_port != 0) 832 { 833 accumulate += tc->th_sport; 834 tc->th_sport = proxy_port; 835 accumulate -= tc->th_sport; 836 837 sptr = (u_short *) &pip->ip_src; 838 accumulate += *sptr++; 839 accumulate += *sptr; 840 sptr = (u_short *) &proxy_address; 841 accumulate -= *sptr++; 842 accumulate -= *sptr; 843 } 844 845 /* See if ack number needs to be modified */ 846 if (GetAckModified(link) == 1) 847 { 848 int delta; 849 850 delta = GetDeltaAckIn(pip, link); 851 if (delta != 0) 852 { 853 sptr = (u_short *) &tc->th_ack; 854 accumulate += *sptr++; 855 accumulate += *sptr; 856 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 857 sptr = (u_short *) &tc->th_ack; 858 accumulate -= *sptr++; 859 accumulate -= *sptr; 860 } 861 } 862 863 ADJUST_CHECKSUM(accumulate, tc->th_sum); 864 865 /* Restore original IP address */ 866 sptr = (u_short *) &pip->ip_dst; 867 accumulate = *sptr++; 868 accumulate += *sptr; 869 pip->ip_dst = original_address; 870 sptr = (u_short *) &pip->ip_dst; 871 accumulate -= *sptr++; 872 accumulate -= *sptr; 873 874 /* If this is a transparent proxy packet, then modify the source 875 address */ 876 if (proxy_address.s_addr != 0) 877 { 878 sptr = (u_short *) &pip->ip_src; 879 accumulate += *sptr++; 880 accumulate += *sptr; 881 pip->ip_src = proxy_address; 882 sptr = (u_short *) &pip->ip_src; 883 accumulate -= *sptr++; 884 accumulate -= *sptr; 885 } 886 887 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 888 889 /* Monitor TCP connection state */ 890 TcpMonitorIn(pip, link); 891 892 return(PKT_ALIAS_OK); 893 } 894 return(PKT_ALIAS_IGNORED); 895 } 896 897 static int 898 TcpAliasOut(struct ip *pip, int maxpacketsize) 899 { 900 int proxy_type; 901 u_short dest_port; 902 u_short proxy_server_port; 903 struct in_addr dest_address; 904 struct in_addr proxy_server_address; 905 struct tcphdr *tc; 906 struct alias_link *link; 907 908 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 909 910 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port); 911 912 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 913 return PKT_ALIAS_OK; 914 915 /* If this is a transparent proxy, save original destination, 916 then alter the destination and adust checksums */ 917 dest_port = tc->th_dport; 918 dest_address = pip->ip_dst; 919 if (proxy_type != 0) 920 { 921 int accumulate; 922 u_short *sptr; 923 924 accumulate = tc->th_dport; 925 tc->th_dport = proxy_server_port; 926 accumulate -= tc->th_dport; 927 928 sptr = (u_short *) &(pip->ip_dst); 929 accumulate += *sptr++; 930 accumulate += *sptr; 931 sptr = (u_short *) &proxy_server_address; 932 accumulate -= *sptr++; 933 accumulate -= *sptr; 934 935 ADJUST_CHECKSUM(accumulate, tc->th_sum); 936 937 sptr = (u_short *) &(pip->ip_dst); 938 accumulate = *sptr++; 939 accumulate += *sptr; 940 pip->ip_dst = proxy_server_address; 941 sptr = (u_short *) &(pip->ip_dst); 942 accumulate -= *sptr++; 943 accumulate -= *sptr; 944 945 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 946 } 947 948 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 949 tc->th_sport, tc->th_dport, 950 IPPROTO_TCP); 951 if (link !=NULL) 952 { 953 u_short alias_port; 954 struct in_addr alias_address; 955 int accumulate; 956 u_short *sptr; 957 958 /* Save original destination address, if this is a proxy packet. 959 Also modify packet to include destination encoding. */ 960 if (proxy_type != 0) 961 { 962 SetProxyPort(link, dest_port); 963 SetProxyAddress(link, dest_address); 964 ProxyModify(link, pip, maxpacketsize, proxy_type); 965 } 966 967 /* Get alias address and port */ 968 alias_port = GetAliasPort(link); 969 alias_address = GetAliasAddress(link); 970 971 /* Monitor tcp connection state */ 972 TcpMonitorOut(pip, link); 973 974 /* Special processing for IP encoding protocols */ 975 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER 976 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) 977 AliasHandleFtpOut(pip, link, maxpacketsize); 978 if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 979 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) 980 AliasHandleIrcOut(pip, link, maxpacketsize); 981 982 /* Adjust TCP checksum since source port is being aliased */ 983 /* and source address is being altered */ 984 accumulate = tc->th_sport; 985 tc->th_sport = alias_port; 986 accumulate -= tc->th_sport; 987 988 sptr = (u_short *) &(pip->ip_src); 989 accumulate += *sptr++; 990 accumulate += *sptr; 991 sptr = (u_short *) &alias_address; 992 accumulate -= *sptr++; 993 accumulate -= *sptr; 994 995 /* Modify sequence number if necessary */ 996 if (GetAckModified(link) == 1) 997 { 998 int delta; 999 1000 delta = GetDeltaSeqOut(pip, link); 1001 if (delta != 0) 1002 { 1003 sptr = (u_short *) &tc->th_seq; 1004 accumulate += *sptr++; 1005 accumulate += *sptr; 1006 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1007 sptr = (u_short *) &tc->th_seq; 1008 accumulate -= *sptr++; 1009 accumulate -= *sptr; 1010 } 1011 } 1012 1013 ADJUST_CHECKSUM(accumulate, tc->th_sum) 1014 1015 /* Change source address */ 1016 sptr = (u_short *) &(pip->ip_src); 1017 accumulate = *sptr++; 1018 accumulate += *sptr; 1019 pip->ip_src = alias_address; 1020 sptr = (u_short *) &(pip->ip_src); 1021 accumulate -= *sptr++; 1022 accumulate -= *sptr; 1023 1024 ADJUST_CHECKSUM(accumulate, pip->ip_sum) 1025 1026 return(PKT_ALIAS_OK); 1027 } 1028 return(PKT_ALIAS_IGNORED); 1029 } 1030 1031 1032 1033 1034 /* Fragment Handling 1035 1036 FragmentIn() 1037 FragmentOut() 1038 1039 The packet aliasing module has a limited ability for handling IP 1040 fragments. If the ICMP, TCP or UDP header is in the first fragment 1041 received, then the id number of the IP packet is saved, and other 1042 fragments are identified according to their ID number and IP address 1043 they were sent from. Pointers to unresolved fragments can also be 1044 saved and recalled when a header fragment is seen. 1045 */ 1046 1047 /* Local prototypes */ 1048 static int FragmentIn(struct ip *); 1049 static int FragmentOut(struct ip *); 1050 1051 1052 static int 1053 FragmentIn(struct ip *pip) 1054 { 1055 struct alias_link *link; 1056 1057 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id); 1058 if (link != NULL) 1059 { 1060 struct in_addr original_address; 1061 1062 GetFragmentAddr(link, &original_address); 1063 DifferentialChecksum(&pip->ip_sum, 1064 (u_short *) &original_address, 1065 (u_short *) &pip->ip_dst, 1066 2); 1067 pip->ip_dst = original_address; 1068 1069 return(PKT_ALIAS_OK); 1070 } 1071 return(PKT_ALIAS_UNRESOLVED_FRAGMENT); 1072 } 1073 1074 1075 static int 1076 FragmentOut(struct ip *pip) 1077 { 1078 struct in_addr alias_address; 1079 1080 alias_address = FindAliasAddress(pip->ip_src); 1081 DifferentialChecksum(&pip->ip_sum, 1082 (u_short *) &alias_address, 1083 (u_short *) &pip->ip_src, 1084 2); 1085 pip->ip_src = alias_address; 1086 1087 return(PKT_ALIAS_OK); 1088 } 1089 1090 1091 1092 1093 1094 1095 /* Outside World Access 1096 1097 PacketAliasSaveFragment() 1098 PacketAliasGetFragment() 1099 PacketAliasFragmentIn() 1100 PacketAliasIn() 1101 PacketAliasOut() 1102 1103 (prototypes in alias.h) 1104 */ 1105 1106 1107 int 1108 PacketAliasSaveFragment(char *ptr) 1109 { 1110 int iresult; 1111 struct alias_link *link; 1112 struct ip *pip; 1113 1114 pip = (struct ip *) ptr; 1115 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id); 1116 iresult = PKT_ALIAS_ERROR; 1117 if (link != NULL) 1118 { 1119 SetFragmentPtr(link, ptr); 1120 iresult = PKT_ALIAS_OK; 1121 } 1122 return(iresult); 1123 } 1124 1125 1126 char * 1127 PacketAliasGetFragment(char *ptr) 1128 { 1129 struct alias_link *link; 1130 char *fptr; 1131 struct ip *pip; 1132 1133 pip = (struct ip *) ptr; 1134 link = FindFragmentPtr(pip->ip_src, pip->ip_id); 1135 if (link != NULL) 1136 { 1137 GetFragmentPtr(link, &fptr); 1138 SetFragmentPtr(link, NULL); 1139 SetExpire(link, 0); /* Deletes link */ 1140 1141 return(fptr); 1142 } 1143 else 1144 { 1145 return(NULL); 1146 } 1147 } 1148 1149 1150 void 1151 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased 1152 header fragment */ 1153 char *ptr_fragment /* Points to fragment which must 1154 be de-aliased */ 1155 ) 1156 { 1157 struct ip *pip; 1158 struct ip *fpip; 1159 1160 pip = (struct ip *) ptr; 1161 fpip = (struct ip *) ptr_fragment; 1162 1163 DifferentialChecksum(&fpip->ip_sum, 1164 (u_short *) &pip->ip_dst, 1165 (u_short *) &fpip->ip_dst, 1166 2); 1167 fpip->ip_dst = pip->ip_dst; 1168 } 1169 1170 1171 int 1172 PacketAliasIn(char *ptr, int maxpacketsize) 1173 { 1174 struct in_addr alias_addr; 1175 struct ip *pip; 1176 int iresult; 1177 1178 if (packetAliasMode & PKT_ALIAS_REVERSE) 1179 return PacketAliasOut(ptr, maxpacketsize); 1180 1181 HouseKeeping(); 1182 ClearCheckNewLink(); 1183 pip = (struct ip *) ptr; 1184 alias_addr = pip->ip_dst; 1185 1186 /* Defense against mangled packets */ 1187 if (ntohs(pip->ip_len) > maxpacketsize 1188 || (pip->ip_hl<<2) > maxpacketsize) 1189 return PKT_ALIAS_IGNORED; 1190 1191 iresult = PKT_ALIAS_IGNORED; 1192 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 ) 1193 { 1194 switch (pip->ip_p) 1195 { 1196 case IPPROTO_ICMP: 1197 iresult = IcmpAliasIn(pip); 1198 break; 1199 case IPPROTO_UDP: 1200 iresult = UdpAliasIn(pip); 1201 break; 1202 case IPPROTO_TCP: 1203 iresult = TcpAliasIn(pip); 1204 break; 1205 case IPPROTO_GRE: 1206 iresult = PptpAliasIn(pip); 1207 break; 1208 } 1209 1210 if (ntohs(pip->ip_off) & IP_MF) 1211 { 1212 struct alias_link *link; 1213 1214 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id); 1215 if (link != NULL) 1216 { 1217 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1218 SetFragmentAddr(link, pip->ip_dst); 1219 } 1220 else 1221 { 1222 iresult = PKT_ALIAS_ERROR; 1223 } 1224 } 1225 } 1226 else 1227 { 1228 iresult = FragmentIn(pip); 1229 } 1230 1231 return(iresult); 1232 } 1233 1234 1235 1236 /* Unregistered address ranges */ 1237 1238 /* 10.0.0.0 -> 10.255.255.255 */ 1239 #define UNREG_ADDR_A_LOWER 0x0a000000 1240 #define UNREG_ADDR_A_UPPER 0x0affffff 1241 1242 /* 172.16.0.0 -> 172.31.255.255 */ 1243 #define UNREG_ADDR_B_LOWER 0xac100000 1244 #define UNREG_ADDR_B_UPPER 0xac1fffff 1245 1246 /* 192.168.0.0 -> 192.168.255.255 */ 1247 #define UNREG_ADDR_C_LOWER 0xc0a80000 1248 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1249 1250 int 1251 PacketAliasOut(char *ptr, /* valid IP packet */ 1252 int maxpacketsize /* How much the packet data may grow 1253 (FTP and IRC inline changes) */ 1254 ) 1255 { 1256 int iresult; 1257 struct in_addr addr_save; 1258 struct ip *pip; 1259 1260 if (packetAliasMode & PKT_ALIAS_REVERSE) 1261 return PacketAliasIn(ptr, maxpacketsize); 1262 1263 HouseKeeping(); 1264 ClearCheckNewLink(); 1265 pip = (struct ip *) ptr; 1266 1267 /* Defense against mangled packets */ 1268 if (ntohs(pip->ip_len) > maxpacketsize 1269 || (pip->ip_hl<<2) > maxpacketsize) 1270 return PKT_ALIAS_IGNORED; 1271 1272 addr_save = GetDefaultAliasAddress(); 1273 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) 1274 { 1275 unsigned int addr; 1276 int iclass; 1277 1278 iclass = 0; 1279 addr = ntohl(pip->ip_src.s_addr); 1280 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1281 iclass = 3; 1282 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1283 iclass = 2; 1284 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1285 iclass = 1; 1286 1287 if (iclass == 0) 1288 { 1289 SetDefaultAliasAddress(pip->ip_src); 1290 } 1291 } 1292 1293 iresult = PKT_ALIAS_IGNORED; 1294 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) 1295 { 1296 switch (pip->ip_p) 1297 { 1298 case IPPROTO_ICMP: 1299 iresult = IcmpAliasOut(pip); 1300 break; 1301 case IPPROTO_UDP: 1302 iresult = UdpAliasOut(pip); 1303 break; 1304 case IPPROTO_TCP: 1305 iresult = TcpAliasOut(pip, maxpacketsize); 1306 break; 1307 case IPPROTO_GRE: 1308 iresult = PptpAliasOut(pip); 1309 break; 1310 } 1311 } 1312 else 1313 { 1314 iresult = FragmentOut(pip); 1315 } 1316 1317 SetDefaultAliasAddress(addr_save); 1318 return(iresult); 1319 } 1320