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 Version 3.1 May, 2000 (salander) 80 - Added hooks to handle PPTP. 81 82 Version 3.2 July, 2000 (salander and satoh) 83 - Added PacketUnaliasOut routine. 84 - Added hooks to handle RTSP/RTP. 85 86 See HISTORY file for additional revisions. 87 88 $FreeBSD$ 89 */ 90 91 #include <sys/types.h> 92 93 #include <netinet/in_systm.h> 94 #include <netinet/in.h> 95 #include <netinet/ip.h> 96 #include <netinet/ip_icmp.h> 97 #include <netinet/tcp.h> 98 #include <netinet/udp.h> 99 100 #include <stdio.h> 101 102 #include "alias_local.h" 103 #include "alias.h" 104 105 #define NETBIOS_NS_PORT_NUMBER 137 106 #define NETBIOS_DGM_PORT_NUMBER 138 107 #define FTP_CONTROL_PORT_NUMBER 21 108 #define IRC_CONTROL_PORT_NUMBER_1 6667 109 #define IRC_CONTROL_PORT_NUMBER_2 6668 110 #define CUSEEME_PORT_NUMBER 7648 111 #define RTSP_CONTROL_PORT_NUMBER_1 554 112 #define RTSP_CONTROL_PORT_NUMBER_2 7070 113 #define PPTP_CONTROL_PORT_NUMBER 1723 114 115 116 117 118 /* TCP Handling Routines 119 120 TcpMonitorIn() -- These routines monitor TCP connections, and 121 TcpMonitorOut() delete a link when a connection is closed. 122 123 These routines look for SYN, FIN and RST flags to determine when TCP 124 connections open and close. When a TCP connection closes, the data 125 structure containing packet aliasing information is deleted after 126 a timeout period. 127 */ 128 129 /* Local prototypes */ 130 static void TcpMonitorIn(struct ip *, struct alias_link *); 131 132 static void TcpMonitorOut(struct ip *, struct alias_link *); 133 134 135 static void 136 TcpMonitorIn(struct ip *pip, struct alias_link *link) 137 { 138 struct tcphdr *tc; 139 140 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 141 142 switch (GetStateIn(link)) 143 { 144 case ALIAS_TCP_STATE_NOT_CONNECTED: 145 if (tc->th_flags & TH_RST) 146 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED); 147 else if (tc->th_flags & TH_SYN) 148 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED); 149 break; 150 case ALIAS_TCP_STATE_CONNECTED: 151 if (tc->th_flags & (TH_FIN | TH_RST)) 152 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED); 153 break; 154 } 155 } 156 157 static void 158 TcpMonitorOut(struct ip *pip, struct alias_link *link) 159 { 160 struct tcphdr *tc; 161 162 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 163 164 switch (GetStateOut(link)) 165 { 166 case ALIAS_TCP_STATE_NOT_CONNECTED: 167 if (tc->th_flags & TH_RST) 168 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED); 169 else if (tc->th_flags & TH_SYN) 170 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED); 171 break; 172 case ALIAS_TCP_STATE_CONNECTED: 173 if (tc->th_flags & (TH_FIN | TH_RST)) 174 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED); 175 break; 176 } 177 } 178 179 180 181 182 183 /* Protocol Specific Packet Aliasing Routines 184 185 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2() 186 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2() 187 ProtoAliasIn(), ProtoAliasOut() 188 UdpAliasIn(), UdpAliasOut() 189 TcpAliasIn(), TcpAliasOut() 190 191 These routines handle protocol specific details of packet aliasing. 192 One may observe a certain amount of repetitive arithmetic in these 193 functions, the purpose of which is to compute a revised checksum 194 without actually summing over the entire data packet, which could be 195 unnecessarily time consuming. 196 197 The purpose of the packet aliasing routines is to replace the source 198 address of the outgoing packet and then correctly put it back for 199 any incoming packets. For TCP and UDP, ports are also re-mapped. 200 201 For ICMP echo/timestamp requests and replies, the following scheme 202 is used: the ID number is replaced by an alias for the outgoing 203 packet. 204 205 ICMP error messages are handled by looking at the IP fragment 206 in the data section of the message. 207 208 For TCP and UDP protocols, a port number is chosen for an outgoing 209 packet, and then incoming packets are identified by IP address and 210 port numbers. For TCP packets, there is additional logic in the event 211 that sequence and ACK numbers have been altered (as in the case for 212 FTP data port commands). 213 214 The port numbers used by the packet aliasing module are not true 215 ports in the Unix sense. No sockets are actually bound to ports. 216 They are more correctly thought of as placeholders. 217 218 All packets go through the aliasing mechanism, whether they come from 219 the gateway machine or other machines on a local area network. 220 */ 221 222 223 /* Local prototypes */ 224 static int IcmpAliasIn1(struct ip *); 225 static int IcmpAliasIn2(struct ip *); 226 static int IcmpAliasIn (struct ip *); 227 228 static int IcmpAliasOut1(struct ip *); 229 static int IcmpAliasOut2(struct ip *); 230 static int IcmpAliasOut (struct ip *); 231 232 static int ProtoAliasIn(struct ip *); 233 static int ProtoAliasOut(struct ip *); 234 235 static int UdpAliasOut(struct ip *); 236 static int UdpAliasIn (struct ip *); 237 238 static int TcpAliasOut(struct ip *, int); 239 static int TcpAliasIn (struct ip *); 240 241 242 static int 243 IcmpAliasIn1(struct ip *pip) 244 { 245 /* 246 De-alias incoming echo and timestamp replies. 247 Alias incoming echo and timestamp requests. 248 */ 249 struct alias_link *link; 250 struct icmp *ic; 251 252 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 253 254 /* Get source address from ICMP data field and restore original data */ 255 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1); 256 if (link != NULL) 257 { 258 u_short original_id; 259 int accumulate; 260 261 original_id = GetOriginalPort(link); 262 263 /* Adjust ICMP checksum */ 264 accumulate = ic->icmp_id; 265 accumulate -= original_id; 266 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 267 268 /* Put original sequence number back in */ 269 ic->icmp_id = original_id; 270 271 /* Put original address back into IP header */ 272 { 273 struct in_addr original_address; 274 275 original_address = GetOriginalAddress(link); 276 DifferentialChecksum(&pip->ip_sum, 277 (u_short *) &original_address, 278 (u_short *) &pip->ip_dst, 279 2); 280 pip->ip_dst = original_address; 281 } 282 283 return(PKT_ALIAS_OK); 284 } 285 return(PKT_ALIAS_IGNORED); 286 } 287 288 static int 289 IcmpAliasIn2(struct ip *pip) 290 { 291 /* 292 Alias incoming ICMP error messages containing 293 IP header and first 64 bits of datagram. 294 */ 295 struct ip *ip; 296 struct icmp *ic, *ic2; 297 struct udphdr *ud; 298 struct tcphdr *tc; 299 struct alias_link *link; 300 301 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 302 ip = &ic->icmp_ip; 303 304 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); 305 tc = (struct tcphdr *) ud; 306 ic2 = (struct icmp *) ud; 307 308 if (ip->ip_p == IPPROTO_UDP) 309 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, 310 ud->uh_dport, ud->uh_sport, 311 IPPROTO_UDP, 0); 312 else if (ip->ip_p == IPPROTO_TCP) 313 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, 314 tc->th_dport, tc->th_sport, 315 IPPROTO_TCP, 0); 316 else if (ip->ip_p == IPPROTO_ICMP) { 317 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 318 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 319 else 320 link = NULL; 321 } else 322 link = NULL; 323 324 if (link != NULL) 325 { 326 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) 327 { 328 u_short *sptr; 329 int accumulate; 330 struct in_addr original_address; 331 u_short original_port; 332 333 original_address = GetOriginalAddress(link); 334 original_port = GetOriginalPort(link); 335 336 /* Adjust ICMP checksum */ 337 sptr = (u_short *) &(ip->ip_src); 338 accumulate = *sptr++; 339 accumulate += *sptr; 340 sptr = (u_short *) &original_address; 341 accumulate -= *sptr++; 342 accumulate -= *sptr; 343 accumulate += ud->uh_sport; 344 accumulate -= original_port; 345 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 346 347 /* Un-alias address in IP header */ 348 DifferentialChecksum(&pip->ip_sum, 349 (u_short *) &original_address, 350 (u_short *) &pip->ip_dst, 351 2); 352 pip->ip_dst = original_address; 353 354 /* Un-alias address and port number of original IP packet 355 fragment contained in ICMP data section */ 356 ip->ip_src = original_address; 357 ud->uh_sport = original_port; 358 } 359 else if (ip->ip_p == IPPROTO_ICMP) 360 { 361 u_short *sptr; 362 int accumulate; 363 struct in_addr original_address; 364 u_short original_id; 365 366 original_address = GetOriginalAddress(link); 367 original_id = GetOriginalPort(link); 368 369 /* Adjust ICMP checksum */ 370 sptr = (u_short *) &(ip->ip_src); 371 accumulate = *sptr++; 372 accumulate += *sptr; 373 sptr = (u_short *) &original_address; 374 accumulate -= *sptr++; 375 accumulate -= *sptr; 376 accumulate += ic2->icmp_id; 377 accumulate -= original_id; 378 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 379 380 /* Un-alias address in IP header */ 381 DifferentialChecksum(&pip->ip_sum, 382 (u_short *) &original_address, 383 (u_short *) &pip->ip_dst, 384 2); 385 pip->ip_dst = original_address; 386 387 /* Un-alias address of original IP packet and sequence number of 388 embedded ICMP datagram */ 389 ip->ip_src = original_address; 390 ic2->icmp_id = original_id; 391 } 392 return(PKT_ALIAS_OK); 393 } 394 return(PKT_ALIAS_IGNORED); 395 } 396 397 398 static int 399 IcmpAliasIn(struct ip *pip) 400 { 401 int iresult; 402 struct icmp *ic; 403 404 /* Return if proxy-only mode is enabled */ 405 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 406 return PKT_ALIAS_OK; 407 408 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 409 410 iresult = PKT_ALIAS_IGNORED; 411 switch (ic->icmp_type) 412 { 413 case ICMP_ECHOREPLY: 414 case ICMP_TSTAMPREPLY: 415 if (ic->icmp_code == 0) 416 { 417 iresult = IcmpAliasIn1(pip); 418 } 419 break; 420 case ICMP_UNREACH: 421 case ICMP_SOURCEQUENCH: 422 case ICMP_TIMXCEED: 423 case ICMP_PARAMPROB: 424 iresult = IcmpAliasIn2(pip); 425 break; 426 case ICMP_ECHO: 427 case ICMP_TSTAMP: 428 iresult = IcmpAliasIn1(pip); 429 break; 430 } 431 return(iresult); 432 } 433 434 435 static int 436 IcmpAliasOut1(struct ip *pip) 437 { 438 /* 439 Alias outgoing echo and timestamp requests. 440 De-alias outgoing echo and timestamp replies. 441 */ 442 struct alias_link *link; 443 struct icmp *ic; 444 445 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 446 447 /* Save overwritten data for when echo packet returns */ 448 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1); 449 if (link != NULL) 450 { 451 u_short alias_id; 452 int accumulate; 453 454 alias_id = GetAliasPort(link); 455 456 /* Since data field is being modified, adjust ICMP checksum */ 457 accumulate = ic->icmp_id; 458 accumulate -= alias_id; 459 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 460 461 /* Alias sequence number */ 462 ic->icmp_id = alias_id; 463 464 /* Change source address */ 465 { 466 struct in_addr alias_address; 467 468 alias_address = GetAliasAddress(link); 469 DifferentialChecksum(&pip->ip_sum, 470 (u_short *) &alias_address, 471 (u_short *) &pip->ip_src, 472 2); 473 pip->ip_src = alias_address; 474 } 475 476 return(PKT_ALIAS_OK); 477 } 478 return(PKT_ALIAS_IGNORED); 479 } 480 481 482 static int 483 IcmpAliasOut2(struct ip *pip) 484 { 485 /* 486 Alias outgoing ICMP error messages containing 487 IP header and first 64 bits of datagram. 488 */ 489 struct ip *ip; 490 struct icmp *ic, *ic2; 491 struct udphdr *ud; 492 struct tcphdr *tc; 493 struct alias_link *link; 494 495 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 496 ip = &ic->icmp_ip; 497 498 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); 499 tc = (struct tcphdr *) ud; 500 ic2 = (struct icmp *) ud; 501 502 if (ip->ip_p == IPPROTO_UDP) 503 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src, 504 ud->uh_dport, ud->uh_sport, 505 IPPROTO_UDP, 0); 506 else if (ip->ip_p == IPPROTO_TCP) 507 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src, 508 tc->th_dport, tc->th_sport, 509 IPPROTO_TCP, 0); 510 else if (ip->ip_p == IPPROTO_ICMP) { 511 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 512 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 513 else 514 link = NULL; 515 } else 516 link = NULL; 517 518 if (link != NULL) 519 { 520 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) 521 { 522 u_short *sptr; 523 int accumulate; 524 struct in_addr alias_address; 525 u_short alias_port; 526 527 alias_address = GetAliasAddress(link); 528 alias_port = GetAliasPort(link); 529 530 /* Adjust ICMP checksum */ 531 sptr = (u_short *) &(ip->ip_dst); 532 accumulate = *sptr++; 533 accumulate += *sptr; 534 sptr = (u_short *) &alias_address; 535 accumulate -= *sptr++; 536 accumulate -= *sptr; 537 accumulate += ud->uh_dport; 538 accumulate -= alias_port; 539 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 540 541 /* 542 * Alias address in IP header if it comes from the host 543 * the original TCP/UDP packet was destined for. 544 */ 545 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 546 DifferentialChecksum(&pip->ip_sum, 547 (u_short *) &alias_address, 548 (u_short *) &pip->ip_src, 549 2); 550 pip->ip_src = alias_address; 551 } 552 553 /* Alias address and port number of original IP packet 554 fragment contained in ICMP data section */ 555 ip->ip_dst = alias_address; 556 ud->uh_dport = alias_port; 557 } 558 else if (ip->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 /* 580 * Alias address in IP header if it comes from the host 581 * the original ICMP message was destined for. 582 */ 583 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 584 DifferentialChecksum(&pip->ip_sum, 585 (u_short *) &alias_address, 586 (u_short *) &pip->ip_src, 587 2); 588 pip->ip_src = alias_address; 589 } 590 591 /* Alias address of original IP packet and sequence number of 592 embedded ICMP datagram */ 593 ip->ip_dst = alias_address; 594 ic2->icmp_id = alias_id; 595 } 596 return(PKT_ALIAS_OK); 597 } 598 return(PKT_ALIAS_IGNORED); 599 } 600 601 602 static int 603 IcmpAliasOut(struct ip *pip) 604 { 605 int iresult; 606 struct icmp *ic; 607 608 /* Return if proxy-only mode is enabled */ 609 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 610 return PKT_ALIAS_OK; 611 612 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); 613 614 iresult = PKT_ALIAS_IGNORED; 615 switch (ic->icmp_type) 616 { 617 case ICMP_ECHO: 618 case ICMP_TSTAMP: 619 if (ic->icmp_code == 0) 620 { 621 iresult = IcmpAliasOut1(pip); 622 } 623 break; 624 case ICMP_UNREACH: 625 case ICMP_SOURCEQUENCH: 626 case ICMP_TIMXCEED: 627 case ICMP_PARAMPROB: 628 iresult = IcmpAliasOut2(pip); 629 break; 630 case ICMP_ECHOREPLY: 631 case ICMP_TSTAMPREPLY: 632 iresult = IcmpAliasOut1(pip); 633 } 634 return(iresult); 635 } 636 637 638 639 static int 640 ProtoAliasIn(struct ip *pip) 641 { 642 /* 643 Handle incoming IP packets. The 644 only thing which is done in this case is to alias 645 the dest IP address of the packet to our inside 646 machine. 647 */ 648 struct alias_link *link; 649 650 /* Return if proxy-only mode is enabled */ 651 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 652 return PKT_ALIAS_OK; 653 654 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p); 655 if (link != NULL) 656 { 657 struct in_addr original_address; 658 659 original_address = GetOriginalAddress(link); 660 661 /* Restore original IP address */ 662 DifferentialChecksum(&pip->ip_sum, 663 (u_short *) &original_address, 664 (u_short *) &pip->ip_dst, 665 2); 666 pip->ip_dst = original_address; 667 668 return(PKT_ALIAS_OK); 669 } 670 return(PKT_ALIAS_IGNORED); 671 } 672 673 674 static int 675 ProtoAliasOut(struct ip *pip) 676 { 677 /* 678 Handle outgoing IP packets. The 679 only thing which is done in this case is to alias 680 the source IP address of the packet. 681 */ 682 struct alias_link *link; 683 684 /* Return if proxy-only mode is enabled */ 685 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 686 return PKT_ALIAS_OK; 687 688 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p); 689 if (link != NULL) 690 { 691 struct in_addr alias_address; 692 693 alias_address = GetAliasAddress(link); 694 695 /* Change source address */ 696 DifferentialChecksum(&pip->ip_sum, 697 (u_short *) &alias_address, 698 (u_short *) &pip->ip_src, 699 2); 700 pip->ip_src = alias_address; 701 702 return(PKT_ALIAS_OK); 703 } 704 return(PKT_ALIAS_IGNORED); 705 } 706 707 708 static int 709 UdpAliasIn(struct ip *pip) 710 { 711 struct udphdr *ud; 712 struct alias_link *link; 713 714 /* Return if proxy-only mode is enabled */ 715 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 716 return PKT_ALIAS_OK; 717 718 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 719 720 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 721 ud->uh_sport, ud->uh_dport, 722 IPPROTO_UDP, 1); 723 if (link != NULL) 724 { 725 struct in_addr alias_address; 726 struct in_addr original_address; 727 u_short alias_port; 728 int accumulate; 729 u_short *sptr; 730 int r = 0; 731 732 alias_address = GetAliasAddress(link); 733 original_address = GetOriginalAddress(link); 734 alias_port = ud->uh_dport; 735 ud->uh_dport = GetOriginalPort(link); 736 737 /* Special processing for IP encoding protocols */ 738 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 739 AliasHandleCUSeeMeIn(pip, original_address); 740 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 741 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 742 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) 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 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port, 747 &original_address, &ud->uh_dport); 748 749 /* If UDP checksum is not zero, then adjust since destination port */ 750 /* is being unaliased and destination address is being altered. */ 751 if (ud->uh_sum != 0) 752 { 753 accumulate = alias_port; 754 accumulate -= ud->uh_dport; 755 sptr = (u_short *) &alias_address; 756 accumulate += *sptr++; 757 accumulate += *sptr; 758 sptr = (u_short *) &original_address; 759 accumulate -= *sptr++; 760 accumulate -= *sptr; 761 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 762 } 763 764 /* Restore original IP address */ 765 DifferentialChecksum(&pip->ip_sum, 766 (u_short *) &original_address, 767 (u_short *) &pip->ip_dst, 768 2); 769 pip->ip_dst = original_address; 770 771 /* 772 * If we cannot figure out the packet, ignore it. 773 */ 774 if (r < 0) 775 return(PKT_ALIAS_IGNORED); 776 else 777 return(PKT_ALIAS_OK); 778 } 779 return(PKT_ALIAS_IGNORED); 780 } 781 782 static int 783 UdpAliasOut(struct ip *pip) 784 { 785 struct udphdr *ud; 786 struct alias_link *link; 787 788 /* Return if proxy-only mode is enabled */ 789 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) 790 return PKT_ALIAS_OK; 791 792 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 793 794 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 795 ud->uh_sport, ud->uh_dport, 796 IPPROTO_UDP, 1); 797 if (link != NULL) 798 { 799 u_short alias_port; 800 struct in_addr alias_address; 801 802 alias_address = GetAliasAddress(link); 803 alias_port = GetAliasPort(link); 804 805 /* Special processing for IP encoding protocols */ 806 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 807 AliasHandleCUSeeMeOut(pip, link); 808 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 809 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 810 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) 811 AliasHandleUdpNbt(pip, link, &alias_address, alias_port); 812 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 813 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) 814 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport, 815 &alias_address, &alias_port); 816 817 /* If UDP checksum is not zero, adjust since source port is */ 818 /* being aliased and source address is being altered */ 819 if (ud->uh_sum != 0) 820 { 821 int accumulate; 822 u_short *sptr; 823 824 accumulate = ud->uh_sport; 825 accumulate -= alias_port; 826 sptr = (u_short *) &(pip->ip_src); 827 accumulate += *sptr++; 828 accumulate += *sptr; 829 sptr = (u_short *) &alias_address; 830 accumulate -= *sptr++; 831 accumulate -= *sptr; 832 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 833 } 834 835 /* Put alias port in UDP header */ 836 ud->uh_sport = alias_port; 837 838 /* Change source address */ 839 DifferentialChecksum(&pip->ip_sum, 840 (u_short *) &alias_address, 841 (u_short *) &pip->ip_src, 842 2); 843 pip->ip_src = alias_address; 844 845 return(PKT_ALIAS_OK); 846 } 847 return(PKT_ALIAS_IGNORED); 848 } 849 850 851 852 static int 853 TcpAliasIn(struct ip *pip) 854 { 855 struct tcphdr *tc; 856 struct alias_link *link; 857 858 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 859 860 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, 861 tc->th_sport, tc->th_dport, 862 IPPROTO_TCP, 863 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY)); 864 if (link != NULL) 865 { 866 struct in_addr alias_address; 867 struct in_addr original_address; 868 struct in_addr proxy_address; 869 u_short alias_port; 870 u_short proxy_port; 871 int accumulate; 872 u_short *sptr; 873 874 /* Special processing for IP encoding protocols */ 875 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 876 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 877 AliasHandlePptpIn(pip, link); 878 879 alias_address = GetAliasAddress(link); 880 original_address = GetOriginalAddress(link); 881 proxy_address = GetProxyAddress(link); 882 alias_port = tc->th_dport; 883 tc->th_dport = GetOriginalPort(link); 884 proxy_port = GetProxyPort(link); 885 886 /* Adjust TCP checksum since destination port is being unaliased */ 887 /* and destination port is being altered. */ 888 accumulate = alias_port; 889 accumulate -= tc->th_dport; 890 sptr = (u_short *) &alias_address; 891 accumulate += *sptr++; 892 accumulate += *sptr; 893 sptr = (u_short *) &original_address; 894 accumulate -= *sptr++; 895 accumulate -= *sptr; 896 897 /* If this is a proxy, then modify the TCP source port and 898 checksum accumulation */ 899 if (proxy_port != 0) 900 { 901 accumulate += tc->th_sport; 902 tc->th_sport = proxy_port; 903 accumulate -= tc->th_sport; 904 905 sptr = (u_short *) &pip->ip_src; 906 accumulate += *sptr++; 907 accumulate += *sptr; 908 sptr = (u_short *) &proxy_address; 909 accumulate -= *sptr++; 910 accumulate -= *sptr; 911 } 912 913 /* See if ACK number needs to be modified */ 914 if (GetAckModified(link) == 1) 915 { 916 int delta; 917 918 delta = GetDeltaAckIn(pip, link); 919 if (delta != 0) 920 { 921 sptr = (u_short *) &tc->th_ack; 922 accumulate += *sptr++; 923 accumulate += *sptr; 924 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 925 sptr = (u_short *) &tc->th_ack; 926 accumulate -= *sptr++; 927 accumulate -= *sptr; 928 } 929 } 930 931 ADJUST_CHECKSUM(accumulate, tc->th_sum); 932 933 /* Restore original IP address */ 934 sptr = (u_short *) &pip->ip_dst; 935 accumulate = *sptr++; 936 accumulate += *sptr; 937 pip->ip_dst = original_address; 938 sptr = (u_short *) &pip->ip_dst; 939 accumulate -= *sptr++; 940 accumulate -= *sptr; 941 942 /* If this is a transparent proxy packet, then modify the source 943 address */ 944 if (proxy_address.s_addr != 0) 945 { 946 sptr = (u_short *) &pip->ip_src; 947 accumulate += *sptr++; 948 accumulate += *sptr; 949 pip->ip_src = proxy_address; 950 sptr = (u_short *) &pip->ip_src; 951 accumulate -= *sptr++; 952 accumulate -= *sptr; 953 } 954 955 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 956 957 /* Monitor TCP connection state */ 958 TcpMonitorIn(pip, link); 959 960 return(PKT_ALIAS_OK); 961 } 962 return(PKT_ALIAS_IGNORED); 963 } 964 965 static int 966 TcpAliasOut(struct ip *pip, int maxpacketsize) 967 { 968 int proxy_type; 969 u_short dest_port; 970 u_short proxy_server_port; 971 struct in_addr dest_address; 972 struct in_addr proxy_server_address; 973 struct tcphdr *tc; 974 struct alias_link *link; 975 976 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 977 978 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port); 979 980 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 981 return PKT_ALIAS_OK; 982 983 /* If this is a transparent proxy, save original destination, 984 then alter the destination and adjust checksums */ 985 dest_port = tc->th_dport; 986 dest_address = pip->ip_dst; 987 if (proxy_type != 0) 988 { 989 int accumulate; 990 u_short *sptr; 991 992 accumulate = tc->th_dport; 993 tc->th_dport = proxy_server_port; 994 accumulate -= tc->th_dport; 995 996 sptr = (u_short *) &(pip->ip_dst); 997 accumulate += *sptr++; 998 accumulate += *sptr; 999 sptr = (u_short *) &proxy_server_address; 1000 accumulate -= *sptr++; 1001 accumulate -= *sptr; 1002 1003 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1004 1005 sptr = (u_short *) &(pip->ip_dst); 1006 accumulate = *sptr++; 1007 accumulate += *sptr; 1008 pip->ip_dst = proxy_server_address; 1009 sptr = (u_short *) &(pip->ip_dst); 1010 accumulate -= *sptr++; 1011 accumulate -= *sptr; 1012 1013 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1014 } 1015 1016 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, 1017 tc->th_sport, tc->th_dport, 1018 IPPROTO_TCP, 1); 1019 if (link !=NULL) 1020 { 1021 u_short alias_port; 1022 struct in_addr alias_address; 1023 int accumulate; 1024 u_short *sptr; 1025 1026 /* Save original destination address, if this is a proxy packet. 1027 Also modify packet to include destination encoding. */ 1028 if (proxy_type != 0) 1029 { 1030 SetProxyPort(link, dest_port); 1031 SetProxyAddress(link, dest_address); 1032 ProxyModify(link, pip, maxpacketsize, proxy_type); 1033 } 1034 1035 /* Get alias address and port */ 1036 alias_port = GetAliasPort(link); 1037 alias_address = GetAliasAddress(link); 1038 1039 /* Monitor TCP connection state */ 1040 TcpMonitorOut(pip, link); 1041 1042 /* Special processing for IP encoding protocols */ 1043 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER 1044 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) 1045 AliasHandleFtpOut(pip, link, maxpacketsize); 1046 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 1047 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) 1048 AliasHandleIrcOut(pip, link, maxpacketsize); 1049 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1 1050 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1 1051 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2 1052 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 1053 AliasHandleRtspOut(pip, link, maxpacketsize); 1054 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 1055 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 1056 AliasHandlePptpOut(pip, link); 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 1115 The packet aliasing module has a limited ability for handling IP 1116 fragments. If the ICMP, TCP or UDP header is in the first fragment 1117 received, then the ID number of the IP packet is saved, and other 1118 fragments are identified according to their ID number and IP address 1119 they were sent from. Pointers to unresolved fragments can also be 1120 saved and recalled when a header fragment is seen. 1121 */ 1122 1123 /* Local prototypes */ 1124 static int FragmentIn(struct ip *); 1125 static int FragmentOut(struct ip *); 1126 1127 1128 static int 1129 FragmentIn(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 1151 static int 1152 FragmentOut(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 PacketUnaliasOut() 1179 1180 (prototypes in alias.h) 1181 */ 1182 1183 1184 int 1185 PacketAliasSaveFragment(char *ptr) 1186 { 1187 int iresult; 1188 struct alias_link *link; 1189 struct ip *pip; 1190 1191 pip = (struct ip *) ptr; 1192 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id); 1193 iresult = PKT_ALIAS_ERROR; 1194 if (link != NULL) 1195 { 1196 SetFragmentPtr(link, ptr); 1197 iresult = PKT_ALIAS_OK; 1198 } 1199 return(iresult); 1200 } 1201 1202 1203 char * 1204 PacketAliasGetFragment(char *ptr) 1205 { 1206 struct alias_link *link; 1207 char *fptr; 1208 struct ip *pip; 1209 1210 pip = (struct ip *) ptr; 1211 link = FindFragmentPtr(pip->ip_src, pip->ip_id); 1212 if (link != NULL) 1213 { 1214 GetFragmentPtr(link, &fptr); 1215 SetFragmentPtr(link, NULL); 1216 SetExpire(link, 0); /* Deletes link */ 1217 1218 return(fptr); 1219 } 1220 else 1221 { 1222 return(NULL); 1223 } 1224 } 1225 1226 1227 void 1228 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased 1229 header fragment */ 1230 char *ptr_fragment /* Points to fragment which must 1231 be de-aliased */ 1232 ) 1233 { 1234 struct ip *pip; 1235 struct ip *fpip; 1236 1237 pip = (struct ip *) ptr; 1238 fpip = (struct ip *) ptr_fragment; 1239 1240 DifferentialChecksum(&fpip->ip_sum, 1241 (u_short *) &pip->ip_dst, 1242 (u_short *) &fpip->ip_dst, 1243 2); 1244 fpip->ip_dst = pip->ip_dst; 1245 } 1246 1247 1248 int 1249 PacketAliasIn(char *ptr, int maxpacketsize) 1250 { 1251 struct in_addr alias_addr; 1252 struct ip *pip; 1253 int iresult; 1254 1255 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1256 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1257 iresult = PacketAliasOut(ptr, maxpacketsize); 1258 packetAliasMode |= PKT_ALIAS_REVERSE; 1259 return iresult; 1260 } 1261 1262 HouseKeeping(); 1263 ClearCheckNewLink(); 1264 pip = (struct ip *) ptr; 1265 alias_addr = pip->ip_dst; 1266 1267 /* Defense against mangled packets */ 1268 if (ntohs(pip->ip_len) > maxpacketsize 1269 || (pip->ip_hl<<2) > maxpacketsize) 1270 return PKT_ALIAS_IGNORED; 1271 1272 iresult = PKT_ALIAS_IGNORED; 1273 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 ) 1274 { 1275 switch (pip->ip_p) 1276 { 1277 case IPPROTO_ICMP: 1278 iresult = IcmpAliasIn(pip); 1279 break; 1280 case IPPROTO_UDP: 1281 iresult = UdpAliasIn(pip); 1282 break; 1283 case IPPROTO_TCP: 1284 iresult = TcpAliasIn(pip); 1285 break; 1286 case IPPROTO_GRE: 1287 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY || 1288 AliasHandlePptpGreIn(pip) == 0) 1289 iresult = PKT_ALIAS_OK; 1290 else 1291 iresult = ProtoAliasIn(pip); 1292 break; 1293 default: 1294 iresult = ProtoAliasIn(pip); 1295 break; 1296 } 1297 1298 if (ntohs(pip->ip_off) & IP_MF) 1299 { 1300 struct alias_link *link; 1301 1302 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id); 1303 if (link != NULL) 1304 { 1305 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1306 SetFragmentAddr(link, pip->ip_dst); 1307 } 1308 else 1309 { 1310 iresult = PKT_ALIAS_ERROR; 1311 } 1312 } 1313 } 1314 else 1315 { 1316 iresult = FragmentIn(pip); 1317 } 1318 1319 return(iresult); 1320 } 1321 1322 1323 1324 /* Unregistered address ranges */ 1325 1326 /* 10.0.0.0 -> 10.255.255.255 */ 1327 #define UNREG_ADDR_A_LOWER 0x0a000000 1328 #define UNREG_ADDR_A_UPPER 0x0affffff 1329 1330 /* 172.16.0.0 -> 172.31.255.255 */ 1331 #define UNREG_ADDR_B_LOWER 0xac100000 1332 #define UNREG_ADDR_B_UPPER 0xac1fffff 1333 1334 /* 192.168.0.0 -> 192.168.255.255 */ 1335 #define UNREG_ADDR_C_LOWER 0xc0a80000 1336 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1337 1338 int 1339 PacketAliasOut(char *ptr, /* valid IP packet */ 1340 int maxpacketsize /* How much the packet data may grow 1341 (FTP and IRC inline changes) */ 1342 ) 1343 { 1344 int iresult; 1345 struct in_addr addr_save; 1346 struct ip *pip; 1347 1348 if (packetAliasMode & PKT_ALIAS_REVERSE) { 1349 packetAliasMode &= ~PKT_ALIAS_REVERSE; 1350 iresult = PacketAliasIn(ptr, maxpacketsize); 1351 packetAliasMode |= PKT_ALIAS_REVERSE; 1352 return iresult; 1353 } 1354 1355 HouseKeeping(); 1356 ClearCheckNewLink(); 1357 pip = (struct ip *) ptr; 1358 1359 /* Defense against mangled packets */ 1360 if (ntohs(pip->ip_len) > maxpacketsize 1361 || (pip->ip_hl<<2) > maxpacketsize) 1362 return PKT_ALIAS_IGNORED; 1363 1364 addr_save = GetDefaultAliasAddress(); 1365 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) 1366 { 1367 u_long addr; 1368 int iclass; 1369 1370 iclass = 0; 1371 addr = ntohl(pip->ip_src.s_addr); 1372 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1373 iclass = 3; 1374 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1375 iclass = 2; 1376 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1377 iclass = 1; 1378 1379 if (iclass == 0) 1380 { 1381 SetDefaultAliasAddress(pip->ip_src); 1382 } 1383 } 1384 1385 iresult = PKT_ALIAS_IGNORED; 1386 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) 1387 { 1388 switch (pip->ip_p) 1389 { 1390 case IPPROTO_ICMP: 1391 iresult = IcmpAliasOut(pip); 1392 break; 1393 case IPPROTO_UDP: 1394 iresult = UdpAliasOut(pip); 1395 break; 1396 case IPPROTO_TCP: 1397 iresult = TcpAliasOut(pip, maxpacketsize); 1398 break; 1399 case IPPROTO_GRE: 1400 if (AliasHandlePptpGreOut(pip) == 0) 1401 iresult = PKT_ALIAS_OK; 1402 else 1403 iresult = ProtoAliasOut(pip); 1404 break; 1405 default: 1406 iresult = ProtoAliasOut(pip); 1407 break; 1408 } 1409 } 1410 else 1411 { 1412 iresult = FragmentOut(pip); 1413 } 1414 1415 SetDefaultAliasAddress(addr_save); 1416 return(iresult); 1417 } 1418 1419 int 1420 PacketUnaliasOut(char *ptr, /* valid IP packet */ 1421 int maxpacketsize /* for error checking */ 1422 ) 1423 { 1424 struct ip *pip; 1425 struct icmp *ic; 1426 struct udphdr *ud; 1427 struct tcphdr *tc; 1428 struct alias_link *link; 1429 int iresult = PKT_ALIAS_IGNORED; 1430 1431 pip = (struct ip *) ptr; 1432 1433 /* Defense against mangled packets */ 1434 if (ntohs(pip->ip_len) > maxpacketsize 1435 || (pip->ip_hl<<2) > maxpacketsize) 1436 return(iresult); 1437 1438 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); 1439 tc = (struct tcphdr *) ud; 1440 ic = (struct icmp *) ud; 1441 1442 /* Find a link */ 1443 if (pip->ip_p == IPPROTO_UDP) 1444 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src, 1445 ud->uh_dport, ud->uh_sport, 1446 IPPROTO_UDP, 0); 1447 else if (pip->ip_p == IPPROTO_TCP) 1448 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src, 1449 tc->th_dport, tc->th_sport, 1450 IPPROTO_TCP, 0); 1451 else if (pip->ip_p == IPPROTO_ICMP) 1452 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1453 else 1454 link = NULL; 1455 1456 /* Change it from an aliased packet to an unaliased packet */ 1457 if (link != NULL) 1458 { 1459 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) 1460 { 1461 u_short *sptr; 1462 int accumulate; 1463 struct in_addr original_address; 1464 u_short original_port; 1465 1466 original_address = GetOriginalAddress(link); 1467 original_port = GetOriginalPort(link); 1468 1469 /* Adjust TCP/UDP checksum */ 1470 sptr = (u_short *) &(pip->ip_src); 1471 accumulate = *sptr++; 1472 accumulate += *sptr; 1473 sptr = (u_short *) &original_address; 1474 accumulate -= *sptr++; 1475 accumulate -= *sptr; 1476 1477 if (pip->ip_p == IPPROTO_UDP) { 1478 accumulate += ud->uh_sport; 1479 accumulate -= original_port; 1480 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1481 } else { 1482 accumulate += tc->th_sport; 1483 accumulate -= original_port; 1484 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1485 } 1486 1487 /* Adjust IP checksum */ 1488 DifferentialChecksum(&pip->ip_sum, 1489 (u_short *) &original_address, 1490 (u_short *) &pip->ip_src, 1491 2); 1492 1493 /* Un-alias source address and port number */ 1494 pip->ip_src = original_address; 1495 if (pip->ip_p == IPPROTO_UDP) 1496 ud->uh_sport = original_port; 1497 else 1498 tc->th_sport = original_port; 1499 1500 iresult = PKT_ALIAS_OK; 1501 1502 } else if (pip->ip_p == IPPROTO_ICMP) { 1503 1504 u_short *sptr; 1505 int accumulate; 1506 struct in_addr original_address; 1507 u_short original_id; 1508 1509 original_address = GetOriginalAddress(link); 1510 original_id = GetOriginalPort(link); 1511 1512 /* Adjust ICMP checksum */ 1513 sptr = (u_short *) &(pip->ip_src); 1514 accumulate = *sptr++; 1515 accumulate += *sptr; 1516 sptr = (u_short *) &original_address; 1517 accumulate -= *sptr++; 1518 accumulate -= *sptr; 1519 accumulate += ic->icmp_id; 1520 accumulate -= original_id; 1521 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1522 1523 /* Adjust IP checksum */ 1524 DifferentialChecksum(&pip->ip_sum, 1525 (u_short *) &original_address, 1526 (u_short *) &pip->ip_src, 1527 2); 1528 1529 /* Un-alias source address and port number */ 1530 pip->ip_src = original_address; 1531 ic->icmp_id = original_id; 1532 1533 iresult = PKT_ALIAS_OK; 1534 } 1535 } 1536 return(iresult); 1537 1538 } 1539