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