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