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