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