1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2001 Charles Mott <cm@linktel.net> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 /* 33 Alias.c provides supervisory control for the functions of the 34 packet aliasing software. It consists of routines to monitor 35 TCP connection state, protocol-specific aliasing routines, 36 fragment handling and the following outside world functional 37 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn, 38 PacketAliasIn and PacketAliasOut. 39 40 The other C program files are briefly described. The data 41 structure framework which holds information needed to translate 42 packets is encapsulated in alias_db.c. Data is accessed by 43 function calls, so other segments of the program need not know 44 about the underlying data structures. Alias_ftp.c contains 45 special code for modifying the ftp PORT command used to establish 46 data connections, while alias_irc.c does the same for IRC 47 DCC. Alias_util.c contains a few utility routines. 48 49 Version 1.0 August, 1996 (cjm) 50 51 Version 1.1 August 20, 1996 (cjm) 52 PPP host accepts incoming connections for ports 0 to 1023. 53 (Gary Roberts pointed out the need to handle incoming 54 connections.) 55 56 Version 1.2 September 7, 1996 (cjm) 57 Fragment handling error in alias_db.c corrected. 58 (Tom Torrance helped fix this problem.) 59 60 Version 1.4 September 16, 1996 (cjm) 61 - A more generalized method for handling incoming 62 connections, without the 0-1023 restriction, is 63 implemented in alias_db.c 64 - Improved ICMP support in alias.c. Traceroute 65 packet streams can now be correctly aliased. 66 - TCP connection closing logic simplified in 67 alias.c and now allows for additional 1 minute 68 "grace period" after FIN or RST is observed. 69 70 Version 1.5 September 17, 1996 (cjm) 71 Corrected error in handling incoming UDP packets with 0 checksum. 72 (Tom Torrance helped fix this problem.) 73 74 Version 1.6 September 18, 1996 (cjm) 75 Simplified ICMP aliasing scheme. Should now support 76 traceroute from Win95 as well as FreeBSD. 77 78 Version 1.7 January 9, 1997 (cjm) 79 - Out-of-order fragment handling. 80 - IP checksum error fixed for ftp transfers 81 from aliasing host. 82 - Integer return codes added to all 83 aliasing/de-aliasing functions. 84 - Some obsolete comments cleaned up. 85 - Differential checksum computations for 86 IP header (TCP, UDP and ICMP were already 87 differential). 88 89 Version 2.1 May 1997 (cjm) 90 - Added support for outgoing ICMP error 91 messages. 92 - Added two functions PacketAliasIn2() 93 and PacketAliasOut2() for dynamic address 94 control (e.g. round-robin allocation of 95 incoming packets). 96 97 Version 2.2 July 1997 (cjm) 98 - Rationalized API function names to begin 99 with "PacketAlias..." 100 - Eliminated PacketAliasIn2() and 101 PacketAliasOut2() as poorly conceived. 102 103 Version 2.3 Dec 1998 (dillon) 104 - Major bounds checking additions, see FreeBSD/CVS 105 106 Version 3.1 May, 2000 (salander) 107 - Added hooks to handle PPTP. 108 109 Version 3.2 July, 2000 (salander and satoh) 110 - Added PacketUnaliasOut routine. 111 - Added hooks to handle RTSP/RTP. 112 113 See HISTORY file for additional revisions. 114 */ 115 116 #ifdef _KERNEL 117 #include <sys/param.h> 118 #include <sys/systm.h> 119 #include <sys/mbuf.h> 120 #include <sys/sysctl.h> 121 #else 122 #include <sys/types.h> 123 #include <stdlib.h> 124 #include <stdio.h> 125 #include <ctype.h> 126 #include <dlfcn.h> 127 #include <errno.h> 128 #include <string.h> 129 #endif 130 131 #include <netinet/in_systm.h> 132 #include <netinet/in.h> 133 #include <netinet/ip.h> 134 #include <netinet/ip_icmp.h> 135 #include <netinet/tcp.h> 136 #include <netinet/udp.h> 137 138 #ifdef _KERNEL 139 #include <netinet/libalias/alias.h> 140 #include <netinet/libalias/alias_local.h> 141 #include <netinet/libalias/alias_mod.h> 142 #else 143 #include <err.h> 144 #include "alias.h" 145 #include "alias_local.h" 146 #include "alias_mod.h" 147 #endif 148 149 /* 150 * Define libalias SYSCTL Node 151 */ 152 #ifdef SYSCTL_NODE 153 154 SYSCTL_DECL(_net_inet); 155 SYSCTL_DECL(_net_inet_ip); 156 SYSCTL_NODE(_net_inet_ip, OID_AUTO, alias, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 157 "Libalias sysctl API"); 158 159 #endif 160 161 static __inline int 162 twowords(void *p) 163 { 164 uint8_t *c = p; 165 166 #if BYTE_ORDER == LITTLE_ENDIAN 167 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0]; 168 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2]; 169 #else 170 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1]; 171 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3]; 172 #endif 173 return (s1 + s2); 174 } 175 176 /* TCP Handling Routines 177 178 TcpMonitorIn() -- These routines monitor TCP connections, and 179 TcpMonitorOut() delete a link when a connection is closed. 180 181 These routines look for SYN, FIN and RST flags to determine when TCP 182 connections open and close. When a TCP connection closes, the data 183 structure containing packet aliasing information is deleted after 184 a timeout period. 185 */ 186 187 /* Local prototypes */ 188 static void TcpMonitorIn(u_char, struct alias_link *); 189 190 static void TcpMonitorOut(u_char, struct alias_link *); 191 192 193 static void 194 TcpMonitorIn(u_char th_flags, struct alias_link *lnk) 195 { 196 197 switch (GetStateIn(lnk)) { 198 case ALIAS_TCP_STATE_NOT_CONNECTED: 199 if (th_flags & TH_RST) 200 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED); 201 else if (th_flags & TH_SYN) 202 SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED); 203 break; 204 case ALIAS_TCP_STATE_CONNECTED: 205 if (th_flags & (TH_FIN | TH_RST)) 206 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED); 207 break; 208 } 209 } 210 211 static void 212 TcpMonitorOut(u_char th_flags, struct alias_link *lnk) 213 { 214 215 switch (GetStateOut(lnk)) { 216 case ALIAS_TCP_STATE_NOT_CONNECTED: 217 if (th_flags & TH_RST) 218 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED); 219 else if (th_flags & TH_SYN) 220 SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED); 221 break; 222 case ALIAS_TCP_STATE_CONNECTED: 223 if (th_flags & (TH_FIN | TH_RST)) 224 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED); 225 break; 226 } 227 } 228 229 230 231 232 233 /* Protocol Specific Packet Aliasing Routines 234 235 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2() 236 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2() 237 ProtoAliasIn(), ProtoAliasOut() 238 UdpAliasIn(), UdpAliasOut() 239 TcpAliasIn(), TcpAliasOut() 240 241 These routines handle protocol specific details of packet aliasing. 242 One may observe a certain amount of repetitive arithmetic in these 243 functions, the purpose of which is to compute a revised checksum 244 without actually summing over the entire data packet, which could be 245 unnecessarily time consuming. 246 247 The purpose of the packet aliasing routines is to replace the source 248 address of the outgoing packet and then correctly put it back for 249 any incoming packets. For TCP and UDP, ports are also re-mapped. 250 251 For ICMP echo/timestamp requests and replies, the following scheme 252 is used: the ID number is replaced by an alias for the outgoing 253 packet. 254 255 ICMP error messages are handled by looking at the IP fragment 256 in the data section of the message. 257 258 For TCP and UDP protocols, a port number is chosen for an outgoing 259 packet, and then incoming packets are identified by IP address and 260 port numbers. For TCP packets, there is additional logic in the event 261 that sequence and ACK numbers have been altered (as in the case for 262 FTP data port commands). 263 264 The port numbers used by the packet aliasing module are not true 265 ports in the Unix sense. No sockets are actually bound to ports. 266 They are more correctly thought of as placeholders. 267 268 All packets go through the aliasing mechanism, whether they come from 269 the gateway machine or other machines on a local area network. 270 */ 271 272 273 /* Local prototypes */ 274 static int IcmpAliasIn1(struct libalias *, struct ip *); 275 static int IcmpAliasIn2(struct libalias *, struct ip *); 276 static int IcmpAliasIn(struct libalias *, struct ip *); 277 278 static int IcmpAliasOut1(struct libalias *, struct ip *, int create); 279 static int IcmpAliasOut2(struct libalias *, struct ip *); 280 static int IcmpAliasOut(struct libalias *, struct ip *, int create); 281 282 static int ProtoAliasIn(struct libalias *la, struct in_addr ip_src, 283 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum); 284 static int ProtoAliasOut(struct libalias *la, struct in_addr *ip_src, 285 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, 286 int create); 287 288 static int UdpAliasIn(struct libalias *, struct ip *); 289 static int UdpAliasOut(struct libalias *, struct ip *, int, int create); 290 291 static int TcpAliasIn(struct libalias *, struct ip *); 292 static int TcpAliasOut(struct libalias *, struct ip *, int, int create); 293 294 295 static int 296 IcmpAliasIn1(struct libalias *la, struct ip *pip) 297 { 298 299 LIBALIAS_LOCK_ASSERT(la); 300 /* 301 De-alias incoming echo and timestamp replies. 302 Alias incoming echo and timestamp requests. 303 */ 304 struct alias_link *lnk; 305 struct icmp *ic; 306 307 ic = (struct icmp *)ip_next(pip); 308 309 /* Get source address from ICMP data field and restore original data */ 310 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1); 311 if (lnk != NULL) { 312 u_short original_id; 313 int accumulate; 314 315 original_id = GetOriginalPort(lnk); 316 317 /* Adjust ICMP checksum */ 318 accumulate = ic->icmp_id; 319 accumulate -= original_id; 320 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 321 322 /* Put original sequence number back in */ 323 ic->icmp_id = original_id; 324 325 /* Put original address back into IP header */ 326 { 327 struct in_addr original_address; 328 329 original_address = GetOriginalAddress(lnk); 330 DifferentialChecksum(&pip->ip_sum, 331 &original_address, &pip->ip_dst, 2); 332 pip->ip_dst = original_address; 333 } 334 335 return (PKT_ALIAS_OK); 336 } 337 return (PKT_ALIAS_IGNORED); 338 } 339 340 static int 341 IcmpAliasIn2(struct libalias *la, struct ip *pip) 342 { 343 344 LIBALIAS_LOCK_ASSERT(la); 345 /* 346 Alias incoming ICMP error messages containing 347 IP header and first 64 bits of datagram. 348 */ 349 struct ip *ip; 350 struct icmp *ic, *ic2; 351 struct udphdr *ud; 352 struct tcphdr *tc; 353 struct alias_link *lnk; 354 355 ic = (struct icmp *)ip_next(pip); 356 ip = &ic->icmp_ip; 357 358 ud = (struct udphdr *)ip_next(ip); 359 tc = (struct tcphdr *)ip_next(ip); 360 ic2 = (struct icmp *)ip_next(ip); 361 362 if (ip->ip_p == IPPROTO_UDP) 363 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src, 364 ud->uh_dport, ud->uh_sport, 365 IPPROTO_UDP, 0); 366 else if (ip->ip_p == IPPROTO_TCP) 367 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src, 368 tc->th_dport, tc->th_sport, 369 IPPROTO_TCP, 0); 370 else if (ip->ip_p == IPPROTO_ICMP) { 371 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 372 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 373 else 374 lnk = NULL; 375 } else 376 lnk = NULL; 377 378 if (lnk != NULL) { 379 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) { 380 int accumulate, accumulate2; 381 struct in_addr original_address; 382 u_short original_port; 383 384 original_address = GetOriginalAddress(lnk); 385 original_port = GetOriginalPort(lnk); 386 387 /* Adjust ICMP checksum */ 388 accumulate = twowords(&ip->ip_src); 389 accumulate -= twowords(&original_address); 390 accumulate += ud->uh_sport; 391 accumulate -= original_port; 392 accumulate2 = accumulate; 393 accumulate2 += ip->ip_sum; 394 ADJUST_CHECKSUM(accumulate, ip->ip_sum); 395 accumulate2 -= ip->ip_sum; 396 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum); 397 398 /* Un-alias address in IP header */ 399 DifferentialChecksum(&pip->ip_sum, 400 &original_address, &pip->ip_dst, 2); 401 pip->ip_dst = original_address; 402 403 /* Un-alias address and port number of original IP packet 404 fragment contained in ICMP data section */ 405 ip->ip_src = original_address; 406 ud->uh_sport = original_port; 407 } else if (ip->ip_p == IPPROTO_ICMP) { 408 int accumulate, accumulate2; 409 struct in_addr original_address; 410 u_short original_id; 411 412 original_address = GetOriginalAddress(lnk); 413 original_id = GetOriginalPort(lnk); 414 415 /* Adjust ICMP checksum */ 416 accumulate = twowords(&ip->ip_src); 417 accumulate -= twowords(&original_address); 418 accumulate += ic2->icmp_id; 419 accumulate -= original_id; 420 accumulate2 = accumulate; 421 accumulate2 += ip->ip_sum; 422 ADJUST_CHECKSUM(accumulate, ip->ip_sum); 423 accumulate2 -= ip->ip_sum; 424 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum); 425 426 /* Un-alias address in IP header */ 427 DifferentialChecksum(&pip->ip_sum, 428 &original_address, &pip->ip_dst, 2); 429 pip->ip_dst = original_address; 430 431 /* Un-alias address of original IP packet and sequence number of 432 embedded ICMP datagram */ 433 ip->ip_src = original_address; 434 ic2->icmp_id = original_id; 435 } 436 return (PKT_ALIAS_OK); 437 } 438 return (PKT_ALIAS_IGNORED); 439 } 440 441 442 static int 443 IcmpAliasIn(struct libalias *la, struct ip *pip) 444 { 445 int iresult; 446 struct icmp *ic; 447 448 LIBALIAS_LOCK_ASSERT(la); 449 /* Return if proxy-only mode is enabled */ 450 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 451 return (PKT_ALIAS_OK); 452 453 ic = (struct icmp *)ip_next(pip); 454 455 iresult = PKT_ALIAS_IGNORED; 456 switch (ic->icmp_type) { 457 case ICMP_ECHOREPLY: 458 case ICMP_TSTAMPREPLY: 459 if (ic->icmp_code == 0) { 460 iresult = IcmpAliasIn1(la, pip); 461 } 462 break; 463 case ICMP_UNREACH: 464 case ICMP_SOURCEQUENCH: 465 case ICMP_TIMXCEED: 466 case ICMP_PARAMPROB: 467 iresult = IcmpAliasIn2(la, pip); 468 break; 469 case ICMP_ECHO: 470 case ICMP_TSTAMP: 471 iresult = IcmpAliasIn1(la, pip); 472 break; 473 } 474 return (iresult); 475 } 476 477 478 static int 479 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create) 480 { 481 /* 482 Alias outgoing echo and timestamp requests. 483 De-alias outgoing echo and timestamp replies. 484 */ 485 struct alias_link *lnk; 486 struct icmp *ic; 487 488 LIBALIAS_LOCK_ASSERT(la); 489 ic = (struct icmp *)ip_next(pip); 490 491 /* Save overwritten data for when echo packet returns */ 492 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create); 493 if (lnk != NULL) { 494 u_short alias_id; 495 int accumulate; 496 497 alias_id = GetAliasPort(lnk); 498 499 /* Since data field is being modified, adjust ICMP checksum */ 500 accumulate = ic->icmp_id; 501 accumulate -= alias_id; 502 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 503 504 /* Alias sequence number */ 505 ic->icmp_id = alias_id; 506 507 /* Change source address */ 508 { 509 struct in_addr alias_address; 510 511 alias_address = GetAliasAddress(lnk); 512 DifferentialChecksum(&pip->ip_sum, 513 &alias_address, &pip->ip_src, 2); 514 pip->ip_src = alias_address; 515 } 516 517 return (PKT_ALIAS_OK); 518 } 519 return (PKT_ALIAS_IGNORED); 520 } 521 522 523 static int 524 IcmpAliasOut2(struct libalias *la, struct ip *pip) 525 { 526 /* 527 Alias outgoing ICMP error messages containing 528 IP header and first 64 bits of datagram. 529 */ 530 struct ip *ip; 531 struct icmp *ic, *ic2; 532 struct udphdr *ud; 533 struct tcphdr *tc; 534 struct alias_link *lnk; 535 536 LIBALIAS_LOCK_ASSERT(la); 537 ic = (struct icmp *)ip_next(pip); 538 ip = &ic->icmp_ip; 539 540 ud = (struct udphdr *)ip_next(ip); 541 tc = (struct tcphdr *)ip_next(ip); 542 ic2 = (struct icmp *)ip_next(ip); 543 544 if (ip->ip_p == IPPROTO_UDP) 545 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src, 546 ud->uh_dport, ud->uh_sport, 547 IPPROTO_UDP, 0); 548 else if (ip->ip_p == IPPROTO_TCP) 549 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src, 550 tc->th_dport, tc->th_sport, 551 IPPROTO_TCP, 0); 552 else if (ip->ip_p == IPPROTO_ICMP) { 553 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 554 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 555 else 556 lnk = NULL; 557 } else 558 lnk = NULL; 559 560 if (lnk != NULL) { 561 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) { 562 int accumulate; 563 struct in_addr alias_address; 564 u_short alias_port; 565 566 alias_address = GetAliasAddress(lnk); 567 alias_port = GetAliasPort(lnk); 568 569 /* Adjust ICMP checksum */ 570 accumulate = twowords(&ip->ip_dst); 571 accumulate -= twowords(&alias_address); 572 accumulate += ud->uh_dport; 573 accumulate -= alias_port; 574 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 575 576 /* 577 * Alias address in IP header if it comes from the host 578 * the original TCP/UDP packet was destined for. 579 */ 580 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 581 DifferentialChecksum(&pip->ip_sum, 582 &alias_address, &pip->ip_src, 2); 583 pip->ip_src = alias_address; 584 } 585 /* Alias address and port number of original IP packet 586 fragment contained in ICMP data section */ 587 ip->ip_dst = alias_address; 588 ud->uh_dport = alias_port; 589 } else if (ip->ip_p == IPPROTO_ICMP) { 590 int accumulate; 591 struct in_addr alias_address; 592 u_short alias_id; 593 594 alias_address = GetAliasAddress(lnk); 595 alias_id = GetAliasPort(lnk); 596 597 /* Adjust ICMP checksum */ 598 accumulate = twowords(&ip->ip_dst); 599 accumulate -= twowords(&alias_address); 600 accumulate += ic2->icmp_id; 601 accumulate -= alias_id; 602 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 603 604 /* 605 * Alias address in IP header if it comes from the host 606 * the original ICMP message was destined for. 607 */ 608 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 609 DifferentialChecksum(&pip->ip_sum, 610 &alias_address, &pip->ip_src, 2); 611 pip->ip_src = alias_address; 612 } 613 /* Alias address of original IP packet and sequence number of 614 embedded ICMP datagram */ 615 ip->ip_dst = alias_address; 616 ic2->icmp_id = alias_id; 617 } 618 return (PKT_ALIAS_OK); 619 } 620 return (PKT_ALIAS_IGNORED); 621 } 622 623 624 static int 625 IcmpAliasOut(struct libalias *la, struct ip *pip, int create) 626 { 627 int iresult; 628 struct icmp *ic; 629 630 LIBALIAS_LOCK_ASSERT(la); 631 (void)create; 632 633 /* Return if proxy-only mode is enabled */ 634 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 635 return (PKT_ALIAS_OK); 636 637 ic = (struct icmp *)ip_next(pip); 638 639 iresult = PKT_ALIAS_IGNORED; 640 switch (ic->icmp_type) { 641 case ICMP_ECHO: 642 case ICMP_TSTAMP: 643 if (ic->icmp_code == 0) { 644 iresult = IcmpAliasOut1(la, pip, create); 645 } 646 break; 647 case ICMP_UNREACH: 648 case ICMP_SOURCEQUENCH: 649 case ICMP_TIMXCEED: 650 case ICMP_PARAMPROB: 651 iresult = IcmpAliasOut2(la, pip); 652 break; 653 case ICMP_ECHOREPLY: 654 case ICMP_TSTAMPREPLY: 655 iresult = IcmpAliasOut1(la, pip, create); 656 } 657 return (iresult); 658 } 659 660 static int 661 ProtoAliasIn(struct libalias *la, struct in_addr ip_src, 662 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum) 663 { 664 /* 665 Handle incoming IP packets. The 666 only thing which is done in this case is to alias 667 the dest IP address of the packet to our inside 668 machine. 669 */ 670 struct alias_link *lnk; 671 672 LIBALIAS_LOCK_ASSERT(la); 673 /* Return if proxy-only mode is enabled */ 674 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 675 return (PKT_ALIAS_OK); 676 677 lnk = FindProtoIn(la, ip_src, *ip_dst, ip_p); 678 if (lnk != NULL) { 679 struct in_addr original_address; 680 681 original_address = GetOriginalAddress(lnk); 682 683 /* Restore original IP address */ 684 DifferentialChecksum(ip_sum, 685 &original_address, ip_dst, 2); 686 *ip_dst = original_address; 687 688 return (PKT_ALIAS_OK); 689 } 690 return (PKT_ALIAS_IGNORED); 691 } 692 693 static int 694 ProtoAliasOut(struct libalias *la, struct in_addr *ip_src, 695 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create) 696 { 697 /* 698 Handle outgoing IP packets. The 699 only thing which is done in this case is to alias 700 the source IP address of the packet. 701 */ 702 struct alias_link *lnk; 703 704 LIBALIAS_LOCK_ASSERT(la); 705 706 /* Return if proxy-only mode is enabled */ 707 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 708 return (PKT_ALIAS_OK); 709 710 if (!create) 711 return (PKT_ALIAS_IGNORED); 712 713 lnk = FindProtoOut(la, *ip_src, ip_dst, ip_p); 714 if (lnk != NULL) { 715 struct in_addr alias_address; 716 717 alias_address = GetAliasAddress(lnk); 718 719 /* Change source address */ 720 DifferentialChecksum(ip_sum, 721 &alias_address, ip_src, 2); 722 *ip_src = alias_address; 723 724 return (PKT_ALIAS_OK); 725 } 726 return (PKT_ALIAS_IGNORED); 727 } 728 729 730 static int 731 UdpAliasIn(struct libalias *la, struct ip *pip) 732 { 733 struct udphdr *ud; 734 struct alias_link *lnk; 735 736 LIBALIAS_LOCK_ASSERT(la); 737 738 ud = (struct udphdr *)ip_next(pip); 739 740 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, 741 ud->uh_sport, ud->uh_dport, 742 IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)); 743 if (lnk != NULL) { 744 struct in_addr alias_address; 745 struct in_addr original_address; 746 struct in_addr proxy_address; 747 u_short alias_port; 748 u_short proxy_port; 749 int accumulate; 750 int error; 751 struct alias_data ad = { 752 .lnk = lnk, 753 .oaddr = &original_address, 754 .aaddr = &alias_address, 755 .aport = &alias_port, 756 .sport = &ud->uh_sport, 757 .dport = &ud->uh_dport, 758 .maxpktsize = 0 759 }; 760 761 alias_address = GetAliasAddress(lnk); 762 original_address = GetOriginalAddress(lnk); 763 proxy_address = GetProxyAddress(lnk); 764 alias_port = ud->uh_dport; 765 ud->uh_dport = GetOriginalPort(lnk); 766 proxy_port = GetProxyPort(lnk); 767 768 /* Walk out chain. */ 769 error = find_handler(IN, UDP, la, pip, &ad); 770 /* If we cannot figure out the packet, ignore it. */ 771 if (error < 0) 772 return (PKT_ALIAS_IGNORED); 773 774 /* If UDP checksum is not zero, then adjust since destination port */ 775 /* is being unaliased and destination address is being altered. */ 776 if (ud->uh_sum != 0) { 777 accumulate = alias_port; 778 accumulate -= ud->uh_dport; 779 accumulate += twowords(&alias_address); 780 accumulate -= twowords(&original_address); 781 782 /* If this is a proxy packet, modify checksum because of source change.*/ 783 if (proxy_port != 0) { 784 accumulate += ud->uh_sport; 785 accumulate -= proxy_port; 786 } 787 788 if (proxy_address.s_addr != 0) { 789 accumulate += twowords(&pip->ip_src); 790 accumulate -= twowords(&proxy_address); 791 } 792 793 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 794 } 795 /* XXX: Could the two if's below be concatenated to one ? */ 796 /* Restore source port and/or address in case of proxying*/ 797 798 if (proxy_port != 0) 799 ud->uh_sport = proxy_port; 800 801 if (proxy_address.s_addr != 0) { 802 DifferentialChecksum(&pip->ip_sum, 803 &proxy_address, &pip->ip_src, 2); 804 pip->ip_src = proxy_address; 805 } 806 807 /* Restore original IP address */ 808 DifferentialChecksum(&pip->ip_sum, 809 &original_address, &pip->ip_dst, 2); 810 pip->ip_dst = original_address; 811 812 return (PKT_ALIAS_OK); 813 } 814 return (PKT_ALIAS_IGNORED); 815 } 816 817 static int 818 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) 819 { 820 struct udphdr *ud; 821 struct alias_link *lnk; 822 struct in_addr dest_address; 823 struct in_addr proxy_server_address; 824 u_short dest_port; 825 u_short proxy_server_port; 826 int proxy_type; 827 int error; 828 829 LIBALIAS_LOCK_ASSERT(la); 830 831 /* Return if proxy-only mode is enabled and not proxyrule found.*/ 832 ud = (struct udphdr *)ip_next(pip); 833 proxy_type = ProxyCheck(la, &proxy_server_address, 834 &proxy_server_port, pip->ip_src, pip->ip_dst, 835 ud->uh_dport, pip->ip_p); 836 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 837 return (PKT_ALIAS_OK); 838 839 /* If this is a transparent proxy, save original destination, 840 * then alter the destination and adjust checksums */ 841 dest_port = ud->uh_dport; 842 dest_address = pip->ip_dst; 843 844 if (proxy_type != 0) { 845 int accumulate; 846 847 accumulate = twowords(&pip->ip_dst); 848 accumulate -= twowords(&proxy_server_address); 849 850 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 851 852 if (ud->uh_sum != 0) { 853 accumulate = twowords(&pip->ip_dst); 854 accumulate -= twowords(&proxy_server_address); 855 accumulate += ud->uh_dport; 856 accumulate -= proxy_server_port; 857 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 858 } 859 pip->ip_dst = proxy_server_address; 860 ud->uh_dport = proxy_server_port; 861 } 862 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, 863 ud->uh_sport, ud->uh_dport, 864 IPPROTO_UDP, create); 865 if (lnk != NULL) { 866 u_short alias_port; 867 struct in_addr alias_address; 868 struct alias_data ad = { 869 .lnk = lnk, 870 .oaddr = NULL, 871 .aaddr = &alias_address, 872 .aport = &alias_port, 873 .sport = &ud->uh_sport, 874 .dport = &ud->uh_dport, 875 .maxpktsize = 0 876 }; 877 878 /* Save original destination address, if this is a proxy packet. 879 * Also modify packet to include destination encoding. This may 880 * change the size of IP header. */ 881 if (proxy_type != 0) { 882 SetProxyPort(lnk, dest_port); 883 SetProxyAddress(lnk, dest_address); 884 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type); 885 ud = (struct udphdr *)ip_next(pip); 886 } 887 888 alias_address = GetAliasAddress(lnk); 889 alias_port = GetAliasPort(lnk); 890 891 /* Walk out chain. */ 892 error = find_handler(OUT, UDP, la, pip, &ad); 893 894 /* If UDP checksum is not zero, adjust since source port is */ 895 /* being aliased and source address is being altered */ 896 if (ud->uh_sum != 0) { 897 int accumulate; 898 899 accumulate = ud->uh_sport; 900 accumulate -= alias_port; 901 accumulate += twowords(&pip->ip_src); 902 accumulate -= twowords(&alias_address); 903 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 904 } 905 /* Put alias port in UDP header */ 906 ud->uh_sport = alias_port; 907 908 /* Change source address */ 909 DifferentialChecksum(&pip->ip_sum, 910 &alias_address, &pip->ip_src, 2); 911 pip->ip_src = alias_address; 912 913 return (PKT_ALIAS_OK); 914 } 915 return (PKT_ALIAS_IGNORED); 916 } 917 918 919 920 static int 921 TcpAliasIn(struct libalias *la, struct ip *pip) 922 { 923 struct tcphdr *tc; 924 struct alias_link *lnk; 925 926 LIBALIAS_LOCK_ASSERT(la); 927 tc = (struct tcphdr *)ip_next(pip); 928 929 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, 930 tc->th_sport, tc->th_dport, 931 IPPROTO_TCP, 932 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)); 933 if (lnk != NULL) { 934 struct in_addr alias_address; 935 struct in_addr original_address; 936 struct in_addr proxy_address; 937 u_short alias_port; 938 u_short proxy_port; 939 int accumulate, error; 940 941 /* 942 * The init of MANY vars is a bit below, but aliashandlepptpin 943 * seems to need the destination port that came within the 944 * packet and not the original one looks below [*]. 945 */ 946 947 struct alias_data ad = { 948 .lnk = lnk, 949 .oaddr = NULL, 950 .aaddr = NULL, 951 .aport = NULL, 952 .sport = &tc->th_sport, 953 .dport = &tc->th_dport, 954 .maxpktsize = 0 955 }; 956 957 /* Walk out chain. */ 958 error = find_handler(IN, TCP, la, pip, &ad); 959 960 alias_address = GetAliasAddress(lnk); 961 original_address = GetOriginalAddress(lnk); 962 proxy_address = GetProxyAddress(lnk); 963 alias_port = tc->th_dport; 964 tc->th_dport = GetOriginalPort(lnk); 965 proxy_port = GetProxyPort(lnk); 966 967 /* 968 * Look above, if anyone is going to add find_handler AFTER 969 * this aliashandlepptpin/point, please redo alias_data too. 970 * Uncommenting the piece here below should be enough. 971 */ 972 #if 0 973 struct alias_data ad = { 974 .lnk = lnk, 975 .oaddr = &original_address, 976 .aaddr = &alias_address, 977 .aport = &alias_port, 978 .sport = &ud->uh_sport, 979 .dport = &ud->uh_dport, 980 .maxpktsize = 0 981 }; 982 983 /* Walk out chain. */ 984 error = find_handler(la, pip, &ad); 985 if (error == EHDNOF) 986 printf("Protocol handler not found\n"); 987 #endif 988 989 /* Adjust TCP checksum since destination port is being unaliased */ 990 /* and destination port is being altered. */ 991 accumulate = alias_port; 992 accumulate -= tc->th_dport; 993 accumulate += twowords(&alias_address); 994 accumulate -= twowords(&original_address); 995 996 /* If this is a proxy, then modify the TCP source port and 997 checksum accumulation */ 998 if (proxy_port != 0) { 999 accumulate += tc->th_sport; 1000 tc->th_sport = proxy_port; 1001 accumulate -= tc->th_sport; 1002 accumulate += twowords(&pip->ip_src); 1003 accumulate -= twowords(&proxy_address); 1004 } 1005 /* See if ACK number needs to be modified */ 1006 if (GetAckModified(lnk) == 1) { 1007 int delta; 1008 1009 tc = (struct tcphdr *)ip_next(pip); 1010 delta = GetDeltaAckIn(tc->th_ack, lnk); 1011 if (delta != 0) { 1012 accumulate += twowords(&tc->th_ack); 1013 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 1014 accumulate -= twowords(&tc->th_ack); 1015 } 1016 } 1017 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1018 1019 /* Restore original IP address */ 1020 accumulate = twowords(&pip->ip_dst); 1021 pip->ip_dst = original_address; 1022 accumulate -= twowords(&pip->ip_dst); 1023 1024 /* If this is a transparent proxy packet, then modify the source 1025 address */ 1026 if (proxy_address.s_addr != 0) { 1027 accumulate += twowords(&pip->ip_src); 1028 pip->ip_src = proxy_address; 1029 accumulate -= twowords(&pip->ip_src); 1030 } 1031 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1032 1033 /* Monitor TCP connection state */ 1034 tc = (struct tcphdr *)ip_next(pip); 1035 TcpMonitorIn(tc->th_flags, lnk); 1036 1037 return (PKT_ALIAS_OK); 1038 } 1039 return (PKT_ALIAS_IGNORED); 1040 } 1041 1042 static int 1043 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) 1044 { 1045 int proxy_type, error; 1046 u_short dest_port; 1047 u_short proxy_server_port; 1048 struct in_addr dest_address; 1049 struct in_addr proxy_server_address; 1050 struct tcphdr *tc; 1051 struct alias_link *lnk; 1052 1053 LIBALIAS_LOCK_ASSERT(la); 1054 tc = (struct tcphdr *)ip_next(pip); 1055 1056 if (create) 1057 proxy_type = ProxyCheck(la, &proxy_server_address, 1058 &proxy_server_port, pip->ip_src, pip->ip_dst, 1059 tc->th_dport, pip->ip_p); 1060 else 1061 proxy_type = 0; 1062 1063 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 1064 return (PKT_ALIAS_OK); 1065 1066 /* If this is a transparent proxy, save original destination, 1067 then alter the destination and adjust checksums */ 1068 dest_port = tc->th_dport; 1069 dest_address = pip->ip_dst; 1070 if (proxy_type != 0) { 1071 int accumulate; 1072 1073 accumulate = tc->th_dport; 1074 tc->th_dport = proxy_server_port; 1075 accumulate -= tc->th_dport; 1076 accumulate += twowords(&pip->ip_dst); 1077 accumulate -= twowords(&proxy_server_address); 1078 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1079 1080 accumulate = twowords(&pip->ip_dst); 1081 pip->ip_dst = proxy_server_address; 1082 accumulate -= twowords(&pip->ip_dst); 1083 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1084 } 1085 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, 1086 tc->th_sport, tc->th_dport, 1087 IPPROTO_TCP, create); 1088 if (lnk == NULL) 1089 return (PKT_ALIAS_IGNORED); 1090 if (lnk != NULL) { 1091 u_short alias_port; 1092 struct in_addr alias_address; 1093 int accumulate; 1094 struct alias_data ad = { 1095 .lnk = lnk, 1096 .oaddr = NULL, 1097 .aaddr = &alias_address, 1098 .aport = &alias_port, 1099 .sport = &tc->th_sport, 1100 .dport = &tc->th_dport, 1101 .maxpktsize = maxpacketsize 1102 }; 1103 1104 /* Save original destination address, if this is a proxy packet. 1105 Also modify packet to include destination encoding. This may 1106 change the size of IP header. */ 1107 if (proxy_type != 0) { 1108 SetProxyPort(lnk, dest_port); 1109 SetProxyAddress(lnk, dest_address); 1110 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type); 1111 tc = (struct tcphdr *)ip_next(pip); 1112 } 1113 /* Get alias address and port */ 1114 alias_port = GetAliasPort(lnk); 1115 alias_address = GetAliasAddress(lnk); 1116 1117 /* Monitor TCP connection state */ 1118 tc = (struct tcphdr *)ip_next(pip); 1119 TcpMonitorOut(tc->th_flags, lnk); 1120 1121 /* Walk out chain. */ 1122 error = find_handler(OUT, TCP, la, pip, &ad); 1123 1124 /* Adjust TCP checksum since source port is being aliased */ 1125 /* and source address is being altered */ 1126 accumulate = tc->th_sport; 1127 tc->th_sport = alias_port; 1128 accumulate -= tc->th_sport; 1129 accumulate += twowords(&pip->ip_src); 1130 accumulate -= twowords(&alias_address); 1131 1132 /* Modify sequence number if necessary */ 1133 if (GetAckModified(lnk) == 1) { 1134 int delta; 1135 1136 tc = (struct tcphdr *)ip_next(pip); 1137 delta = GetDeltaSeqOut(tc->th_seq, lnk); 1138 if (delta != 0) { 1139 accumulate += twowords(&tc->th_seq); 1140 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1141 accumulate -= twowords(&tc->th_seq); 1142 } 1143 } 1144 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1145 1146 /* Change source address */ 1147 accumulate = twowords(&pip->ip_src); 1148 pip->ip_src = alias_address; 1149 accumulate -= twowords(&pip->ip_src); 1150 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1151 1152 return (PKT_ALIAS_OK); 1153 } 1154 return (PKT_ALIAS_IGNORED); 1155 } 1156 1157 1158 1159 1160 /* Fragment Handling 1161 1162 FragmentIn() 1163 FragmentOut() 1164 1165 The packet aliasing module has a limited ability for handling IP 1166 fragments. If the ICMP, TCP or UDP header is in the first fragment 1167 received, then the ID number of the IP packet is saved, and other 1168 fragments are identified according to their ID number and IP address 1169 they were sent from. Pointers to unresolved fragments can also be 1170 saved and recalled when a header fragment is seen. 1171 */ 1172 1173 /* Local prototypes */ 1174 static int FragmentIn(struct libalias *la, struct in_addr ip_src, 1175 struct in_addr *ip_dst, u_short ip_id, u_short *ip_sum); 1176 static int FragmentOut(struct libalias *, struct in_addr *ip_src, 1177 u_short *ip_sum); 1178 1179 static int 1180 FragmentIn(struct libalias *la, struct in_addr ip_src, struct in_addr *ip_dst, 1181 u_short ip_id, u_short *ip_sum) 1182 { 1183 struct alias_link *lnk; 1184 1185 LIBALIAS_LOCK_ASSERT(la); 1186 lnk = FindFragmentIn2(la, ip_src, *ip_dst, ip_id); 1187 if (lnk != NULL) { 1188 struct in_addr original_address; 1189 1190 GetFragmentAddr(lnk, &original_address); 1191 DifferentialChecksum(ip_sum, 1192 &original_address, ip_dst, 2); 1193 *ip_dst = original_address; 1194 1195 return (PKT_ALIAS_OK); 1196 } 1197 return (PKT_ALIAS_UNRESOLVED_FRAGMENT); 1198 } 1199 1200 static int 1201 FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum) 1202 { 1203 struct in_addr alias_address; 1204 1205 LIBALIAS_LOCK_ASSERT(la); 1206 alias_address = FindAliasAddress(la, *ip_src); 1207 DifferentialChecksum(ip_sum, 1208 &alias_address, ip_src, 2); 1209 *ip_src = alias_address; 1210 1211 return (PKT_ALIAS_OK); 1212 } 1213 1214 1215 1216 1217 1218 1219 /* Outside World Access 1220 1221 PacketAliasSaveFragment() 1222 PacketAliasGetFragment() 1223 PacketAliasFragmentIn() 1224 PacketAliasIn() 1225 PacketAliasOut() 1226 PacketUnaliasOut() 1227 1228 (prototypes in alias.h) 1229 */ 1230 1231 int 1232 LibAliasSaveFragment(struct libalias *la, char *ptr) 1233 { 1234 int iresult; 1235 struct alias_link *lnk; 1236 struct ip *pip; 1237 1238 LIBALIAS_LOCK(la); 1239 pip = (struct ip *)ptr; 1240 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id); 1241 iresult = PKT_ALIAS_ERROR; 1242 if (lnk != NULL) { 1243 SetFragmentPtr(lnk, ptr); 1244 iresult = PKT_ALIAS_OK; 1245 } 1246 LIBALIAS_UNLOCK(la); 1247 return (iresult); 1248 } 1249 1250 char * 1251 LibAliasGetFragment(struct libalias *la, char *ptr) 1252 { 1253 struct alias_link *lnk; 1254 char *fptr; 1255 struct ip *pip; 1256 1257 LIBALIAS_LOCK(la); 1258 pip = (struct ip *)ptr; 1259 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id); 1260 if (lnk != NULL) { 1261 GetFragmentPtr(lnk, &fptr); 1262 SetFragmentPtr(lnk, NULL); 1263 SetExpire(lnk, 0); /* Deletes link */ 1264 } else 1265 fptr = NULL; 1266 1267 LIBALIAS_UNLOCK(la); 1268 return (fptr); 1269 } 1270 1271 void 1272 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly 1273 * de-aliased header 1274 * fragment */ 1275 char *ptr_fragment /* Points to fragment which must be 1276 * de-aliased */ 1277 ) 1278 { 1279 struct ip *pip; 1280 struct ip *fpip; 1281 1282 LIBALIAS_LOCK(la); 1283 (void)la; 1284 pip = (struct ip *)ptr; 1285 fpip = (struct ip *)ptr_fragment; 1286 1287 DifferentialChecksum(&fpip->ip_sum, 1288 &pip->ip_dst, &fpip->ip_dst, 2); 1289 fpip->ip_dst = pip->ip_dst; 1290 LIBALIAS_UNLOCK(la); 1291 } 1292 1293 /* Local prototypes */ 1294 static int 1295 LibAliasOutLocked(struct libalias *la, char *ptr, 1296 int maxpacketsize, int create); 1297 static int 1298 LibAliasInLocked(struct libalias *la, char *ptr, 1299 int maxpacketsize); 1300 1301 int 1302 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) 1303 { 1304 int res; 1305 1306 LIBALIAS_LOCK(la); 1307 res = LibAliasInLocked(la, ptr, maxpacketsize); 1308 LIBALIAS_UNLOCK(la); 1309 return (res); 1310 } 1311 1312 static int 1313 LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize) 1314 { 1315 struct in_addr alias_addr; 1316 struct ip *pip; 1317 int iresult; 1318 1319 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1320 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1321 iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1); 1322 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1323 goto getout; 1324 } 1325 HouseKeeping(la); 1326 ClearCheckNewLink(la); 1327 pip = (struct ip *)ptr; 1328 alias_addr = pip->ip_dst; 1329 1330 /* Defense against mangled packets */ 1331 if (ntohs(pip->ip_len) > maxpacketsize 1332 || (pip->ip_hl << 2) > maxpacketsize) { 1333 iresult = PKT_ALIAS_IGNORED; 1334 goto getout; 1335 } 1336 1337 iresult = PKT_ALIAS_IGNORED; 1338 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1339 switch (pip->ip_p) { 1340 case IPPROTO_ICMP: 1341 iresult = IcmpAliasIn(la, pip); 1342 break; 1343 case IPPROTO_UDP: 1344 iresult = UdpAliasIn(la, pip); 1345 break; 1346 case IPPROTO_TCP: 1347 iresult = TcpAliasIn(la, pip); 1348 break; 1349 #ifdef _KERNEL 1350 case IPPROTO_SCTP: 1351 iresult = SctpAlias(la, pip, SN_TO_LOCAL); 1352 break; 1353 #endif 1354 case IPPROTO_GRE: { 1355 int error; 1356 struct alias_data ad = { 1357 .lnk = NULL, 1358 .oaddr = NULL, 1359 .aaddr = NULL, 1360 .aport = NULL, 1361 .sport = NULL, 1362 .dport = NULL, 1363 .maxpktsize = 0 1364 }; 1365 1366 /* Walk out chain. */ 1367 error = find_handler(IN, IP, la, pip, &ad); 1368 if (error == 0) 1369 iresult = PKT_ALIAS_OK; 1370 else 1371 iresult = ProtoAliasIn(la, pip->ip_src, 1372 &pip->ip_dst, pip->ip_p, &pip->ip_sum); 1373 } 1374 break; 1375 default: 1376 iresult = ProtoAliasIn(la, pip->ip_src, &pip->ip_dst, 1377 pip->ip_p, &pip->ip_sum); 1378 break; 1379 } 1380 1381 if (ntohs(pip->ip_off) & IP_MF) { 1382 struct alias_link *lnk; 1383 1384 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); 1385 if (lnk != NULL) { 1386 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1387 SetFragmentAddr(lnk, pip->ip_dst); 1388 } else { 1389 iresult = PKT_ALIAS_ERROR; 1390 } 1391 } 1392 } else { 1393 iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id, 1394 &pip->ip_sum); 1395 } 1396 1397 getout: 1398 return (iresult); 1399 } 1400 1401 1402 1403 /* Unregistered address ranges */ 1404 1405 /* 10.0.0.0 -> 10.255.255.255 */ 1406 #define UNREG_ADDR_A_LOWER 0x0a000000 1407 #define UNREG_ADDR_A_UPPER 0x0affffff 1408 1409 /* 172.16.0.0 -> 172.31.255.255 */ 1410 #define UNREG_ADDR_B_LOWER 0xac100000 1411 #define UNREG_ADDR_B_UPPER 0xac1fffff 1412 1413 /* 192.168.0.0 -> 192.168.255.255 */ 1414 #define UNREG_ADDR_C_LOWER 0xc0a80000 1415 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1416 1417 /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */ 1418 #define UNREG_ADDR_CGN_LOWER 0x64400000 1419 #define UNREG_ADDR_CGN_UPPER 0x647fffff 1420 1421 int 1422 LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize) 1423 { 1424 int res; 1425 1426 LIBALIAS_LOCK(la); 1427 res = LibAliasOutLocked(la, ptr, maxpacketsize, 1); 1428 LIBALIAS_UNLOCK(la); 1429 return (res); 1430 } 1431 1432 int 1433 LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create) 1434 { 1435 int res; 1436 1437 LIBALIAS_LOCK(la); 1438 res = LibAliasOutLocked(la, ptr, maxpacketsize, create); 1439 LIBALIAS_UNLOCK(la); 1440 return (res); 1441 } 1442 1443 static int 1444 LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */ 1445 int maxpacketsize, /* How much the packet data may grow (FTP 1446 * and IRC inline changes) */ 1447 int create /* Create new entries ? */ 1448 ) 1449 { 1450 int iresult; 1451 struct in_addr addr_save; 1452 struct ip *pip; 1453 1454 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1455 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1456 iresult = LibAliasInLocked(la, ptr, maxpacketsize); 1457 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1458 goto getout; 1459 } 1460 HouseKeeping(la); 1461 ClearCheckNewLink(la); 1462 pip = (struct ip *)ptr; 1463 1464 /* Defense against mangled packets */ 1465 if (ntohs(pip->ip_len) > maxpacketsize 1466 || (pip->ip_hl << 2) > maxpacketsize) { 1467 iresult = PKT_ALIAS_IGNORED; 1468 goto getout; 1469 } 1470 1471 addr_save = GetDefaultAliasAddress(la); 1472 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY || 1473 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) { 1474 u_long addr; 1475 int iclass; 1476 1477 iclass = 0; 1478 addr = ntohl(pip->ip_src.s_addr); 1479 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1480 iclass = 3; 1481 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1482 iclass = 2; 1483 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1484 iclass = 1; 1485 else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER && 1486 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) 1487 iclass = 4; 1488 1489 if (iclass == 0) { 1490 SetDefaultAliasAddress(la, pip->ip_src); 1491 } 1492 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { 1493 SetDefaultAliasAddress(la, pip->ip_src); 1494 } 1495 iresult = PKT_ALIAS_IGNORED; 1496 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1497 switch (pip->ip_p) { 1498 case IPPROTO_ICMP: 1499 iresult = IcmpAliasOut(la, pip, create); 1500 break; 1501 case IPPROTO_UDP: 1502 iresult = UdpAliasOut(la, pip, maxpacketsize, create); 1503 break; 1504 case IPPROTO_TCP: 1505 iresult = TcpAliasOut(la, pip, maxpacketsize, create); 1506 break; 1507 #ifdef _KERNEL 1508 case IPPROTO_SCTP: 1509 iresult = SctpAlias(la, pip, SN_TO_GLOBAL); 1510 break; 1511 #endif 1512 case IPPROTO_GRE: { 1513 int error; 1514 struct alias_data ad = { 1515 .lnk = NULL, 1516 .oaddr = NULL, 1517 .aaddr = NULL, 1518 .aport = NULL, 1519 .sport = NULL, 1520 .dport = NULL, 1521 .maxpktsize = 0 1522 }; 1523 /* Walk out chain. */ 1524 error = find_handler(OUT, IP, la, pip, &ad); 1525 if (error == 0) 1526 iresult = PKT_ALIAS_OK; 1527 else 1528 iresult = ProtoAliasOut(la, &pip->ip_src, 1529 pip->ip_dst, pip->ip_p, &pip->ip_sum, create); 1530 } 1531 break; 1532 default: 1533 iresult = ProtoAliasOut(la, &pip->ip_src, 1534 pip->ip_dst, pip->ip_p, &pip->ip_sum, create); 1535 break; 1536 } 1537 } else { 1538 iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum); 1539 } 1540 1541 SetDefaultAliasAddress(la, addr_save); 1542 getout: 1543 return (iresult); 1544 } 1545 1546 int 1547 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */ 1548 int maxpacketsize /* for error checking */ 1549 ) 1550 { 1551 struct ip *pip; 1552 struct icmp *ic; 1553 struct udphdr *ud; 1554 struct tcphdr *tc; 1555 struct alias_link *lnk; 1556 int iresult = PKT_ALIAS_IGNORED; 1557 1558 LIBALIAS_LOCK(la); 1559 pip = (struct ip *)ptr; 1560 1561 /* Defense against mangled packets */ 1562 if (ntohs(pip->ip_len) > maxpacketsize 1563 || (pip->ip_hl << 2) > maxpacketsize) 1564 goto getout; 1565 1566 ud = (struct udphdr *)ip_next(pip); 1567 tc = (struct tcphdr *)ip_next(pip); 1568 ic = (struct icmp *)ip_next(pip); 1569 1570 /* Find a link */ 1571 if (pip->ip_p == IPPROTO_UDP) 1572 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1573 ud->uh_dport, ud->uh_sport, 1574 IPPROTO_UDP, 0); 1575 else if (pip->ip_p == IPPROTO_TCP) 1576 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1577 tc->th_dport, tc->th_sport, 1578 IPPROTO_TCP, 0); 1579 else if (pip->ip_p == IPPROTO_ICMP) 1580 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1581 else 1582 lnk = NULL; 1583 1584 /* Change it from an aliased packet to an unaliased packet */ 1585 if (lnk != NULL) { 1586 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) { 1587 int accumulate; 1588 struct in_addr original_address; 1589 u_short original_port; 1590 1591 original_address = GetOriginalAddress(lnk); 1592 original_port = GetOriginalPort(lnk); 1593 1594 /* Adjust TCP/UDP checksum */ 1595 accumulate = twowords(&pip->ip_src); 1596 accumulate -= twowords(&original_address); 1597 1598 if (pip->ip_p == IPPROTO_UDP) { 1599 accumulate += ud->uh_sport; 1600 accumulate -= original_port; 1601 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1602 } else { 1603 accumulate += tc->th_sport; 1604 accumulate -= original_port; 1605 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1606 } 1607 1608 /* Adjust IP checksum */ 1609 DifferentialChecksum(&pip->ip_sum, 1610 &original_address, &pip->ip_src, 2); 1611 1612 /* Un-alias source address and port number */ 1613 pip->ip_src = original_address; 1614 if (pip->ip_p == IPPROTO_UDP) 1615 ud->uh_sport = original_port; 1616 else 1617 tc->th_sport = original_port; 1618 1619 iresult = PKT_ALIAS_OK; 1620 1621 } else if (pip->ip_p == IPPROTO_ICMP) { 1622 1623 int accumulate; 1624 struct in_addr original_address; 1625 u_short original_id; 1626 1627 original_address = GetOriginalAddress(lnk); 1628 original_id = GetOriginalPort(lnk); 1629 1630 /* Adjust ICMP checksum */ 1631 accumulate = twowords(&pip->ip_src); 1632 accumulate -= twowords(&original_address); 1633 accumulate += ic->icmp_id; 1634 accumulate -= original_id; 1635 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1636 1637 /* Adjust IP checksum */ 1638 DifferentialChecksum(&pip->ip_sum, 1639 &original_address, &pip->ip_src, 2); 1640 1641 /* Un-alias source address and port number */ 1642 pip->ip_src = original_address; 1643 ic->icmp_id = original_id; 1644 1645 iresult = PKT_ALIAS_OK; 1646 } 1647 } 1648 getout: 1649 LIBALIAS_UNLOCK(la); 1650 return (iresult); 1651 1652 } 1653 1654 #ifndef _KERNEL 1655 1656 int 1657 LibAliasRefreshModules(void) 1658 { 1659 char buf[256], conf[] = "/etc/libalias.conf"; 1660 FILE *fd; 1661 int i, len; 1662 1663 fd = fopen(conf, "r"); 1664 if (fd == NULL) 1665 err(1, "fopen(%s)", conf); 1666 1667 LibAliasUnLoadAllModule(); 1668 1669 for (;;) { 1670 fgets(buf, 256, fd); 1671 if (feof(fd)) 1672 break; 1673 len = strlen(buf); 1674 if (len > 1) { 1675 for (i = 0; i < len; i++) 1676 if (!isspace(buf[i])) 1677 break; 1678 if (buf[i] == '#') 1679 continue; 1680 buf[len - 1] = '\0'; 1681 LibAliasLoadModule(buf); 1682 } 1683 } 1684 fclose(fd); 1685 return (0); 1686 } 1687 1688 int 1689 LibAliasLoadModule(char *path) 1690 { 1691 struct dll *t; 1692 void *handle; 1693 struct proto_handler *m; 1694 const char *error; 1695 moduledata_t *p; 1696 1697 handle = dlopen (path, RTLD_LAZY); 1698 if (!handle) { 1699 fprintf(stderr, "%s\n", dlerror()); 1700 return (EINVAL); 1701 } 1702 1703 p = dlsym(handle, "alias_mod"); 1704 if ((error = dlerror()) != NULL) { 1705 fprintf(stderr, "%s\n", dlerror()); 1706 return (EINVAL); 1707 } 1708 1709 t = malloc(sizeof(struct dll)); 1710 if (t == NULL) 1711 return (ENOMEM); 1712 strncpy(t->name, p->name, DLL_LEN); 1713 t->handle = handle; 1714 if (attach_dll(t) == EEXIST) { 1715 free(t); 1716 fprintf(stderr, "dll conflict\n"); 1717 return (EEXIST); 1718 } 1719 1720 m = dlsym(t->handle, "handlers"); 1721 if ((error = dlerror()) != NULL) { 1722 fprintf(stderr, "%s\n", error); 1723 return (EINVAL); 1724 } 1725 1726 LibAliasAttachHandlers(m); 1727 return (0); 1728 } 1729 1730 int 1731 LibAliasUnLoadAllModule(void) 1732 { 1733 struct dll *t; 1734 struct proto_handler *p; 1735 1736 /* Unload all modules then reload everything. */ 1737 while ((p = first_handler()) != NULL) { 1738 LibAliasDetachHandlers(p); 1739 } 1740 while ((t = walk_dll_chain()) != NULL) { 1741 dlclose(t->handle); 1742 free(t); 1743 } 1744 return (1); 1745 } 1746 1747 #endif 1748 1749 #ifdef _KERNEL 1750 /* 1751 * m_megapullup() - this function is a big hack. 1752 * Thankfully, it's only used in ng_nat and ipfw+nat. 1753 * 1754 * It allocates an mbuf with cluster and copies the specified part of the chain 1755 * into cluster, so that it is all contiguous and can be accessed via a plain 1756 * (char *) pointer. This is required, because libalias doesn't know how to 1757 * handle mbuf chains. 1758 * 1759 * On success, m_megapullup returns an mbuf (possibly with cluster) containing 1760 * the input packet, on failure NULL. The input packet is always consumed. 1761 */ 1762 struct mbuf * 1763 m_megapullup(struct mbuf *m, int len) 1764 { 1765 struct mbuf *mcl; 1766 1767 if (len > m->m_pkthdr.len) 1768 goto bad; 1769 1770 if (m->m_next == NULL && M_WRITABLE(m)) 1771 return (m); 1772 1773 if (len <= MJUMPAGESIZE) 1774 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR); 1775 else if (len <= MJUM9BYTES) 1776 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); 1777 else if (len <= MJUM16BYTES) 1778 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES); 1779 else 1780 goto bad; 1781 if (mcl == NULL) 1782 goto bad; 1783 m_align(mcl, len); 1784 m_move_pkthdr(mcl, m); 1785 m_copydata(m, 0, len, mtod(mcl, caddr_t)); 1786 mcl->m_len = mcl->m_pkthdr.len = len; 1787 m_freem(m); 1788 1789 return (mcl); 1790 bad: 1791 m_freem(m); 1792 return (NULL); 1793 } 1794 #endif 1795