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