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