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