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