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