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