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 *, int create); 258 259 static int ProtoAliasIn(struct libalias *, struct ip *); 260 static int ProtoAliasOut(struct libalias *, struct ip *, int create); 261 262 static int UdpAliasIn(struct libalias *, struct ip *); 263 static int UdpAliasOut(struct libalias *, struct ip *, int create); 264 265 static int TcpAliasIn(struct libalias *, struct ip *); 266 static int TcpAliasOut(struct libalias *, struct ip *, int, int create); 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, int create) 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, int create) 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, int create) 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, create); 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, int create) 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, create); 947 if (link == NULL) 948 return (PKT_ALIAS_IGNORED); 949 if (link != NULL) { 950 u_short alias_port; 951 struct in_addr alias_address; 952 int accumulate; 953 954 /* Save original destination address, if this is a proxy packet. 955 Also modify packet to include destination encoding. This may 956 change the size of IP header. */ 957 if (proxy_type != 0) { 958 SetProxyPort(link, dest_port); 959 SetProxyAddress(link, dest_address); 960 ProxyModify(la, link, pip, maxpacketsize, proxy_type); 961 tc = (struct tcphdr *)((char *)pip + (pip->ip_hl << 2)); 962 } 963 /* Get alias address and port */ 964 alias_port = GetAliasPort(link); 965 alias_address = GetAliasAddress(link); 966 967 /* Monitor TCP connection state */ 968 TcpMonitorOut(pip, link); 969 970 /* Special processing for IP encoding protocols */ 971 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER 972 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) 973 AliasHandleFtpOut(la, pip, link, maxpacketsize); 974 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 975 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) 976 AliasHandleIrcOut(la, pip, link, maxpacketsize); 977 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1 978 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1 979 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2 980 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 981 AliasHandleRtspOut(la, pip, link, maxpacketsize); 982 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 983 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 984 AliasHandlePptpOut(la, pip, link); 985 else if (la->skinnyPort != 0 && (ntohs(tc->th_sport) == la->skinnyPort 986 || ntohs(tc->th_dport) == la->skinnyPort)) 987 AliasHandleSkinny(la, pip, link); 988 989 /* Adjust TCP checksum since source port is being aliased */ 990 /* and source address is being altered */ 991 accumulate = tc->th_sport; 992 tc->th_sport = alias_port; 993 accumulate -= tc->th_sport; 994 accumulate += twowords(&pip->ip_src); 995 accumulate -= twowords(&alias_address); 996 997 /* Modify sequence number if necessary */ 998 if (GetAckModified(link) == 1) { 999 int delta; 1000 1001 delta = GetDeltaSeqOut(pip, link); 1002 if (delta != 0) { 1003 accumulate += twowords(&tc->th_seq); 1004 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1005 accumulate -= twowords(&tc->th_seq); 1006 } 1007 } 1008 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1009 1010 /* Change source address */ 1011 accumulate = twowords(&pip->ip_src); 1012 pip->ip_src = alias_address; 1013 accumulate -= twowords(&pip->ip_src); 1014 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1015 1016 return (PKT_ALIAS_OK); 1017 } 1018 return (PKT_ALIAS_IGNORED); 1019 } 1020 1021 1022 1023 1024 /* Fragment Handling 1025 1026 FragmentIn() 1027 FragmentOut() 1028 1029 The packet aliasing module has a limited ability for handling IP 1030 fragments. If the ICMP, TCP or UDP header is in the first fragment 1031 received, then the ID number of the IP packet is saved, and other 1032 fragments are identified according to their ID number and IP address 1033 they were sent from. Pointers to unresolved fragments can also be 1034 saved and recalled when a header fragment is seen. 1035 */ 1036 1037 /* Local prototypes */ 1038 static int FragmentIn(struct libalias *, struct ip *); 1039 static int FragmentOut(struct libalias *, struct ip *); 1040 1041 1042 static int 1043 FragmentIn(struct libalias *la, struct ip *pip) 1044 { 1045 struct alias_link *link; 1046 1047 link = FindFragmentIn2(la, pip->ip_src, pip->ip_dst, pip->ip_id); 1048 if (link != NULL) { 1049 struct in_addr original_address; 1050 1051 GetFragmentAddr(link, &original_address); 1052 DifferentialChecksum(&pip->ip_sum, 1053 &original_address, &pip->ip_dst, 2); 1054 pip->ip_dst = original_address; 1055 1056 return (PKT_ALIAS_OK); 1057 } 1058 return (PKT_ALIAS_UNRESOLVED_FRAGMENT); 1059 } 1060 1061 1062 static int 1063 FragmentOut(struct libalias *la, struct ip *pip) 1064 { 1065 struct in_addr alias_address; 1066 1067 alias_address = FindAliasAddress(la, pip->ip_src); 1068 DifferentialChecksum(&pip->ip_sum, 1069 &alias_address, &pip->ip_src, 2); 1070 pip->ip_src = alias_address; 1071 1072 return (PKT_ALIAS_OK); 1073 } 1074 1075 1076 1077 1078 1079 1080 /* Outside World Access 1081 1082 PacketAliasSaveFragment() 1083 PacketAliasGetFragment() 1084 PacketAliasFragmentIn() 1085 PacketAliasIn() 1086 PacketAliasOut() 1087 PacketUnaliasOut() 1088 1089 (prototypes in alias.h) 1090 */ 1091 1092 1093 int 1094 LibAliasSaveFragment(struct libalias *la, char *ptr) 1095 { 1096 int iresult; 1097 struct alias_link *link; 1098 struct ip *pip; 1099 1100 pip = (struct ip *)ptr; 1101 link = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id); 1102 iresult = PKT_ALIAS_ERROR; 1103 if (link != NULL) { 1104 SetFragmentPtr(link, ptr); 1105 iresult = PKT_ALIAS_OK; 1106 } 1107 return (iresult); 1108 } 1109 1110 1111 char * 1112 LibAliasGetFragment(struct libalias *la, char *ptr) 1113 { 1114 struct alias_link *link; 1115 char *fptr; 1116 struct ip *pip; 1117 1118 pip = (struct ip *)ptr; 1119 link = FindFragmentPtr(la, pip->ip_src, pip->ip_id); 1120 if (link != NULL) { 1121 GetFragmentPtr(link, &fptr); 1122 SetFragmentPtr(link, NULL); 1123 SetExpire(link, 0); /* Deletes link */ 1124 1125 return (fptr); 1126 } else { 1127 return (NULL); 1128 } 1129 } 1130 1131 1132 void 1133 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly 1134 * de-aliased header 1135 * fragment */ 1136 char *ptr_fragment /* Points to fragment which must be 1137 * de-aliased */ 1138 ) 1139 { 1140 struct ip *pip; 1141 struct ip *fpip; 1142 1143 pip = (struct ip *)ptr; 1144 fpip = (struct ip *)ptr_fragment; 1145 1146 DifferentialChecksum(&fpip->ip_sum, 1147 &pip->ip_dst, &fpip->ip_dst, 2); 1148 fpip->ip_dst = pip->ip_dst; 1149 } 1150 1151 1152 int 1153 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) 1154 { 1155 struct in_addr alias_addr; 1156 struct ip *pip; 1157 int iresult; 1158 1159 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1160 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1161 iresult = PacketAliasOut(ptr, maxpacketsize); 1162 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1163 return iresult; 1164 } 1165 HouseKeeping(la); 1166 ClearCheckNewLink(la); 1167 pip = (struct ip *)ptr; 1168 alias_addr = pip->ip_dst; 1169 1170 /* Defense against mangled packets */ 1171 if (ntohs(pip->ip_len) > maxpacketsize 1172 || (pip->ip_hl << 2) > maxpacketsize) 1173 return PKT_ALIAS_IGNORED; 1174 1175 iresult = PKT_ALIAS_IGNORED; 1176 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1177 switch (pip->ip_p) { 1178 case IPPROTO_ICMP: 1179 iresult = IcmpAliasIn(la, pip); 1180 break; 1181 case IPPROTO_UDP: 1182 iresult = UdpAliasIn(la, pip); 1183 break; 1184 case IPPROTO_TCP: 1185 iresult = TcpAliasIn(la, pip); 1186 break; 1187 case IPPROTO_GRE: 1188 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY || 1189 AliasHandlePptpGreIn(la, pip) == 0) 1190 iresult = PKT_ALIAS_OK; 1191 else 1192 iresult = ProtoAliasIn(la, pip); 1193 break; 1194 default: 1195 iresult = ProtoAliasIn(la, pip); 1196 break; 1197 } 1198 1199 if (ntohs(pip->ip_off) & IP_MF) { 1200 struct alias_link *link; 1201 1202 link = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); 1203 if (link != NULL) { 1204 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1205 SetFragmentAddr(link, pip->ip_dst); 1206 } else { 1207 iresult = PKT_ALIAS_ERROR; 1208 } 1209 } 1210 } else { 1211 iresult = FragmentIn(la, pip); 1212 } 1213 1214 return (iresult); 1215 } 1216 1217 1218 1219 /* Unregistered address ranges */ 1220 1221 /* 10.0.0.0 -> 10.255.255.255 */ 1222 #define UNREG_ADDR_A_LOWER 0x0a000000 1223 #define UNREG_ADDR_A_UPPER 0x0affffff 1224 1225 /* 172.16.0.0 -> 172.31.255.255 */ 1226 #define UNREG_ADDR_B_LOWER 0xac100000 1227 #define UNREG_ADDR_B_UPPER 0xac1fffff 1228 1229 /* 192.168.0.0 -> 192.168.255.255 */ 1230 #define UNREG_ADDR_C_LOWER 0xc0a80000 1231 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1232 1233 int 1234 LibAliasOut(struct libalias *la, char *ptr, /* valid IP packet */ 1235 int maxpacketsize /* How much the packet data may grow (FTP 1236 * and IRC inline changes) */ 1237 ) 1238 { 1239 return (LibAliasOutTry(la, ptr, maxpacketsize, 1)); 1240 } 1241 1242 int 1243 LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */ 1244 int maxpacketsize, /* How much the packet data may grow (FTP 1245 * and IRC inline changes) */ 1246 int create /* Create new entries ? */ 1247 ) 1248 { 1249 int iresult; 1250 struct in_addr addr_save; 1251 struct ip *pip; 1252 1253 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1254 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1255 iresult = PacketAliasIn(ptr, maxpacketsize); 1256 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1257 return iresult; 1258 } 1259 HouseKeeping(la); 1260 ClearCheckNewLink(la); 1261 pip = (struct ip *)ptr; 1262 1263 /* Defense against mangled packets */ 1264 if (ntohs(pip->ip_len) > maxpacketsize 1265 || (pip->ip_hl << 2) > maxpacketsize) 1266 return PKT_ALIAS_IGNORED; 1267 1268 addr_save = GetDefaultAliasAddress(la); 1269 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) { 1270 u_long addr; 1271 int iclass; 1272 1273 iclass = 0; 1274 addr = ntohl(pip->ip_src.s_addr); 1275 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1276 iclass = 3; 1277 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1278 iclass = 2; 1279 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1280 iclass = 1; 1281 1282 if (iclass == 0) { 1283 SetDefaultAliasAddress(la, pip->ip_src); 1284 } 1285 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { 1286 SetDefaultAliasAddress(la, pip->ip_src); 1287 } 1288 iresult = PKT_ALIAS_IGNORED; 1289 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1290 switch (pip->ip_p) { 1291 case IPPROTO_ICMP: 1292 iresult = IcmpAliasOut(la, pip, create); 1293 break; 1294 case IPPROTO_UDP: 1295 iresult = UdpAliasOut(la, pip, create); 1296 break; 1297 case IPPROTO_TCP: 1298 iresult = TcpAliasOut(la, pip, maxpacketsize, create); 1299 break; 1300 case IPPROTO_GRE: 1301 if (AliasHandlePptpGreOut(la, pip) == 0) 1302 iresult = PKT_ALIAS_OK; 1303 else 1304 iresult = ProtoAliasOut(la, pip, create); 1305 break; 1306 default: 1307 iresult = ProtoAliasOut(la, pip, create); 1308 break; 1309 } 1310 } else { 1311 iresult = FragmentOut(la, pip); 1312 } 1313 1314 SetDefaultAliasAddress(la, addr_save); 1315 return (iresult); 1316 } 1317 1318 int 1319 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */ 1320 int maxpacketsize /* for error checking */ 1321 ) 1322 { 1323 struct ip *pip; 1324 struct icmp *ic; 1325 struct udphdr *ud; 1326 struct tcphdr *tc; 1327 struct alias_link *link; 1328 int iresult = PKT_ALIAS_IGNORED; 1329 1330 pip = (struct ip *)ptr; 1331 1332 /* Defense against mangled packets */ 1333 if (ntohs(pip->ip_len) > maxpacketsize 1334 || (pip->ip_hl << 2) > maxpacketsize) 1335 return (iresult); 1336 1337 ud = (struct udphdr *)((char *)pip + (pip->ip_hl << 2)); 1338 tc = (struct tcphdr *)ud; 1339 ic = (struct icmp *)ud; 1340 1341 /* Find a link */ 1342 if (pip->ip_p == IPPROTO_UDP) 1343 link = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1344 ud->uh_dport, ud->uh_sport, 1345 IPPROTO_UDP, 0); 1346 else if (pip->ip_p == IPPROTO_TCP) 1347 link = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1348 tc->th_dport, tc->th_sport, 1349 IPPROTO_TCP, 0); 1350 else if (pip->ip_p == IPPROTO_ICMP) 1351 link = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1352 else 1353 link = NULL; 1354 1355 /* Change it from an aliased packet to an unaliased packet */ 1356 if (link != NULL) { 1357 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) { 1358 int accumulate; 1359 struct in_addr original_address; 1360 u_short original_port; 1361 1362 original_address = GetOriginalAddress(link); 1363 original_port = GetOriginalPort(link); 1364 1365 /* Adjust TCP/UDP checksum */ 1366 accumulate = twowords(&pip->ip_src); 1367 accumulate -= twowords(&original_address); 1368 1369 if (pip->ip_p == IPPROTO_UDP) { 1370 accumulate += ud->uh_sport; 1371 accumulate -= original_port; 1372 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1373 } else { 1374 accumulate += tc->th_sport; 1375 accumulate -= original_port; 1376 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1377 } 1378 1379 /* Adjust IP checksum */ 1380 DifferentialChecksum(&pip->ip_sum, 1381 &original_address, &pip->ip_src, 2); 1382 1383 /* Un-alias source address and port number */ 1384 pip->ip_src = original_address; 1385 if (pip->ip_p == IPPROTO_UDP) 1386 ud->uh_sport = original_port; 1387 else 1388 tc->th_sport = original_port; 1389 1390 iresult = PKT_ALIAS_OK; 1391 1392 } else if (pip->ip_p == IPPROTO_ICMP) { 1393 1394 int accumulate; 1395 struct in_addr original_address; 1396 u_short original_id; 1397 1398 original_address = GetOriginalAddress(link); 1399 original_id = GetOriginalPort(link); 1400 1401 /* Adjust ICMP checksum */ 1402 accumulate = twowords(&pip->ip_src); 1403 accumulate -= twowords(&original_address); 1404 accumulate += ic->icmp_id; 1405 accumulate -= original_id; 1406 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1407 1408 /* Adjust IP checksum */ 1409 DifferentialChecksum(&pip->ip_sum, 1410 &original_address, &pip->ip_src, 2); 1411 1412 /* Un-alias source address and port number */ 1413 pip->ip_src = original_address; 1414 ic->icmp_id = original_id; 1415 1416 iresult = PKT_ALIAS_OK; 1417 } 1418 } 1419 return (iresult); 1420 1421 } 1422