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 struct icmp *ic; 446 int dlen, iresult; 447 448 LIBALIAS_LOCK_ASSERT(la); 449 450 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 451 if (dlen < ICMP_MINLEN) 452 return (PKT_ALIAS_IGNORED); 453 454 /* Return if proxy-only mode is enabled */ 455 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 456 return (PKT_ALIAS_OK); 457 458 ic = (struct icmp *)ip_next(pip); 459 460 iresult = PKT_ALIAS_IGNORED; 461 switch (ic->icmp_type) { 462 case ICMP_ECHOREPLY: 463 case ICMP_TSTAMPREPLY: 464 if (ic->icmp_code == 0) { 465 iresult = IcmpAliasIn1(la, pip); 466 } 467 break; 468 case ICMP_UNREACH: 469 case ICMP_SOURCEQUENCH: 470 case ICMP_TIMXCEED: 471 case ICMP_PARAMPROB: 472 if (dlen < ICMP_ADVLENMIN || 473 dlen < ICMP_ADVLEN(ic)) 474 return (PKT_ALIAS_IGNORED); 475 iresult = IcmpAliasIn2(la, pip); 476 break; 477 case ICMP_ECHO: 478 case ICMP_TSTAMP: 479 iresult = IcmpAliasIn1(la, pip); 480 break; 481 } 482 return (iresult); 483 } 484 485 486 static int 487 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create) 488 { 489 /* 490 Alias outgoing echo and timestamp requests. 491 De-alias outgoing echo and timestamp replies. 492 */ 493 struct alias_link *lnk; 494 struct icmp *ic; 495 496 LIBALIAS_LOCK_ASSERT(la); 497 ic = (struct icmp *)ip_next(pip); 498 499 /* Save overwritten data for when echo packet returns */ 500 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create); 501 if (lnk != NULL) { 502 u_short alias_id; 503 int accumulate; 504 505 alias_id = GetAliasPort(lnk); 506 507 /* Since data field is being modified, adjust ICMP checksum */ 508 accumulate = ic->icmp_id; 509 accumulate -= alias_id; 510 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 511 512 /* Alias sequence number */ 513 ic->icmp_id = alias_id; 514 515 /* Change source address */ 516 { 517 struct in_addr alias_address; 518 519 alias_address = GetAliasAddress(lnk); 520 DifferentialChecksum(&pip->ip_sum, 521 &alias_address, &pip->ip_src, 2); 522 pip->ip_src = alias_address; 523 } 524 525 return (PKT_ALIAS_OK); 526 } 527 return (PKT_ALIAS_IGNORED); 528 } 529 530 531 static int 532 IcmpAliasOut2(struct libalias *la, struct ip *pip) 533 { 534 /* 535 Alias outgoing ICMP error messages containing 536 IP header and first 64 bits of datagram. 537 */ 538 struct ip *ip; 539 struct icmp *ic, *ic2; 540 struct udphdr *ud; 541 struct tcphdr *tc; 542 struct alias_link *lnk; 543 544 LIBALIAS_LOCK_ASSERT(la); 545 ic = (struct icmp *)ip_next(pip); 546 ip = &ic->icmp_ip; 547 548 ud = (struct udphdr *)ip_next(ip); 549 tc = (struct tcphdr *)ip_next(ip); 550 ic2 = (struct icmp *)ip_next(ip); 551 552 if (ip->ip_p == IPPROTO_UDP) 553 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src, 554 ud->uh_dport, ud->uh_sport, 555 IPPROTO_UDP, 0); 556 else if (ip->ip_p == IPPROTO_TCP) 557 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src, 558 tc->th_dport, tc->th_sport, 559 IPPROTO_TCP, 0); 560 else if (ip->ip_p == IPPROTO_ICMP) { 561 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 562 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 563 else 564 lnk = NULL; 565 } else 566 lnk = NULL; 567 568 if (lnk != NULL) { 569 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) { 570 int accumulate; 571 struct in_addr alias_address; 572 u_short alias_port; 573 574 alias_address = GetAliasAddress(lnk); 575 alias_port = GetAliasPort(lnk); 576 577 /* Adjust ICMP checksum */ 578 accumulate = twowords(&ip->ip_dst); 579 accumulate -= twowords(&alias_address); 580 accumulate += ud->uh_dport; 581 accumulate -= alias_port; 582 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 583 584 /* 585 * Alias address in IP header if it comes from the host 586 * the original TCP/UDP packet was destined for. 587 */ 588 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 589 DifferentialChecksum(&pip->ip_sum, 590 &alias_address, &pip->ip_src, 2); 591 pip->ip_src = alias_address; 592 } 593 /* Alias address and port number of original IP packet 594 fragment contained in ICMP data section */ 595 ip->ip_dst = alias_address; 596 ud->uh_dport = alias_port; 597 } else if (ip->ip_p == IPPROTO_ICMP) { 598 int accumulate; 599 struct in_addr alias_address; 600 u_short alias_id; 601 602 alias_address = GetAliasAddress(lnk); 603 alias_id = GetAliasPort(lnk); 604 605 /* Adjust ICMP checksum */ 606 accumulate = twowords(&ip->ip_dst); 607 accumulate -= twowords(&alias_address); 608 accumulate += ic2->icmp_id; 609 accumulate -= alias_id; 610 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 611 612 /* 613 * Alias address in IP header if it comes from the host 614 * the original ICMP message was destined for. 615 */ 616 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 617 DifferentialChecksum(&pip->ip_sum, 618 &alias_address, &pip->ip_src, 2); 619 pip->ip_src = alias_address; 620 } 621 /* Alias address of original IP packet and sequence number of 622 embedded ICMP datagram */ 623 ip->ip_dst = alias_address; 624 ic2->icmp_id = alias_id; 625 } 626 return (PKT_ALIAS_OK); 627 } 628 return (PKT_ALIAS_IGNORED); 629 } 630 631 632 static int 633 IcmpAliasOut(struct libalias *la, struct ip *pip, int create) 634 { 635 int iresult; 636 struct icmp *ic; 637 638 LIBALIAS_LOCK_ASSERT(la); 639 (void)create; 640 641 /* Return if proxy-only mode is enabled */ 642 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 643 return (PKT_ALIAS_OK); 644 645 ic = (struct icmp *)ip_next(pip); 646 647 iresult = PKT_ALIAS_IGNORED; 648 switch (ic->icmp_type) { 649 case ICMP_ECHO: 650 case ICMP_TSTAMP: 651 if (ic->icmp_code == 0) { 652 iresult = IcmpAliasOut1(la, pip, create); 653 } 654 break; 655 case ICMP_UNREACH: 656 case ICMP_SOURCEQUENCH: 657 case ICMP_TIMXCEED: 658 case ICMP_PARAMPROB: 659 iresult = IcmpAliasOut2(la, pip); 660 break; 661 case ICMP_ECHOREPLY: 662 case ICMP_TSTAMPREPLY: 663 iresult = IcmpAliasOut1(la, pip, create); 664 } 665 return (iresult); 666 } 667 668 static int 669 ProtoAliasIn(struct libalias *la, struct in_addr ip_src, 670 struct in_addr *ip_dst, u_char ip_p, u_short *ip_sum) 671 { 672 /* 673 Handle incoming IP packets. The 674 only thing which is done in this case is to alias 675 the dest IP address of the packet to our inside 676 machine. 677 */ 678 struct alias_link *lnk; 679 680 LIBALIAS_LOCK_ASSERT(la); 681 /* Return if proxy-only mode is enabled */ 682 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 683 return (PKT_ALIAS_OK); 684 685 lnk = FindProtoIn(la, ip_src, *ip_dst, ip_p); 686 if (lnk != NULL) { 687 struct in_addr original_address; 688 689 original_address = GetOriginalAddress(lnk); 690 691 /* Restore original IP address */ 692 DifferentialChecksum(ip_sum, 693 &original_address, ip_dst, 2); 694 *ip_dst = original_address; 695 696 return (PKT_ALIAS_OK); 697 } 698 return (PKT_ALIAS_IGNORED); 699 } 700 701 static int 702 ProtoAliasOut(struct libalias *la, struct in_addr *ip_src, 703 struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create) 704 { 705 /* 706 Handle outgoing IP packets. The 707 only thing which is done in this case is to alias 708 the source IP address of the packet. 709 */ 710 struct alias_link *lnk; 711 712 LIBALIAS_LOCK_ASSERT(la); 713 714 /* Return if proxy-only mode is enabled */ 715 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 716 return (PKT_ALIAS_OK); 717 718 if (!create) 719 return (PKT_ALIAS_IGNORED); 720 721 lnk = FindProtoOut(la, *ip_src, ip_dst, ip_p); 722 if (lnk != NULL) { 723 struct in_addr alias_address; 724 725 alias_address = GetAliasAddress(lnk); 726 727 /* Change source address */ 728 DifferentialChecksum(ip_sum, 729 &alias_address, ip_src, 2); 730 *ip_src = alias_address; 731 732 return (PKT_ALIAS_OK); 733 } 734 return (PKT_ALIAS_IGNORED); 735 } 736 737 738 static int 739 UdpAliasIn(struct libalias *la, struct ip *pip) 740 { 741 struct udphdr *ud; 742 struct alias_link *lnk; 743 int dlen; 744 745 LIBALIAS_LOCK_ASSERT(la); 746 747 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 748 if (dlen < sizeof(struct udphdr)) 749 return (PKT_ALIAS_IGNORED); 750 751 ud = (struct udphdr *)ip_next(pip); 752 if (dlen < ntohs(ud->uh_ulen)) 753 return (PKT_ALIAS_IGNORED); 754 755 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, 756 ud->uh_sport, ud->uh_dport, 757 IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)); 758 if (lnk != NULL) { 759 struct in_addr alias_address; 760 struct in_addr original_address; 761 struct in_addr proxy_address; 762 u_short alias_port; 763 u_short proxy_port; 764 int accumulate; 765 int error; 766 struct alias_data ad = { 767 .lnk = lnk, 768 .oaddr = &original_address, 769 .aaddr = &alias_address, 770 .aport = &alias_port, 771 .sport = &ud->uh_sport, 772 .dport = &ud->uh_dport, 773 .maxpktsize = 0 774 }; 775 776 alias_address = GetAliasAddress(lnk); 777 original_address = GetOriginalAddress(lnk); 778 proxy_address = GetProxyAddress(lnk); 779 alias_port = ud->uh_dport; 780 ud->uh_dport = GetOriginalPort(lnk); 781 proxy_port = GetProxyPort(lnk); 782 783 /* Walk out chain. */ 784 error = find_handler(IN, UDP, la, pip, &ad); 785 /* If we cannot figure out the packet, ignore it. */ 786 if (error < 0) 787 return (PKT_ALIAS_IGNORED); 788 789 /* If UDP checksum is not zero, then adjust since destination port */ 790 /* is being unaliased and destination address is being altered. */ 791 if (ud->uh_sum != 0) { 792 accumulate = alias_port; 793 accumulate -= ud->uh_dport; 794 accumulate += twowords(&alias_address); 795 accumulate -= twowords(&original_address); 796 797 /* If this is a proxy packet, modify checksum because of source change.*/ 798 if (proxy_port != 0) { 799 accumulate += ud->uh_sport; 800 accumulate -= proxy_port; 801 } 802 803 if (proxy_address.s_addr != 0) { 804 accumulate += twowords(&pip->ip_src); 805 accumulate -= twowords(&proxy_address); 806 } 807 808 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 809 } 810 /* XXX: Could the two if's below be concatenated to one ? */ 811 /* Restore source port and/or address in case of proxying*/ 812 813 if (proxy_port != 0) 814 ud->uh_sport = proxy_port; 815 816 if (proxy_address.s_addr != 0) { 817 DifferentialChecksum(&pip->ip_sum, 818 &proxy_address, &pip->ip_src, 2); 819 pip->ip_src = proxy_address; 820 } 821 822 /* Restore original IP address */ 823 DifferentialChecksum(&pip->ip_sum, 824 &original_address, &pip->ip_dst, 2); 825 pip->ip_dst = original_address; 826 827 return (PKT_ALIAS_OK); 828 } 829 return (PKT_ALIAS_IGNORED); 830 } 831 832 static int 833 UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) 834 { 835 struct udphdr *ud; 836 struct alias_link *lnk; 837 struct in_addr dest_address; 838 struct in_addr proxy_server_address; 839 u_short dest_port; 840 u_short proxy_server_port; 841 int proxy_type; 842 int dlen, error; 843 844 LIBALIAS_LOCK_ASSERT(la); 845 846 /* Return if proxy-only mode is enabled and not proxyrule found.*/ 847 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 848 if (dlen < sizeof(struct udphdr)) 849 return (PKT_ALIAS_IGNORED); 850 851 ud = (struct udphdr *)ip_next(pip); 852 if (dlen < ntohs(ud->uh_ulen)) 853 return (PKT_ALIAS_IGNORED); 854 855 proxy_type = ProxyCheck(la, &proxy_server_address, 856 &proxy_server_port, pip->ip_src, pip->ip_dst, 857 ud->uh_dport, pip->ip_p); 858 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 859 return (PKT_ALIAS_OK); 860 861 /* If this is a transparent proxy, save original destination, 862 * then alter the destination and adjust checksums */ 863 dest_port = ud->uh_dport; 864 dest_address = pip->ip_dst; 865 866 if (proxy_type != 0) { 867 int accumulate; 868 869 accumulate = twowords(&pip->ip_dst); 870 accumulate -= twowords(&proxy_server_address); 871 872 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 873 874 if (ud->uh_sum != 0) { 875 accumulate = twowords(&pip->ip_dst); 876 accumulate -= twowords(&proxy_server_address); 877 accumulate += ud->uh_dport; 878 accumulate -= proxy_server_port; 879 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 880 } 881 pip->ip_dst = proxy_server_address; 882 ud->uh_dport = proxy_server_port; 883 } 884 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, 885 ud->uh_sport, ud->uh_dport, 886 IPPROTO_UDP, create); 887 if (lnk != NULL) { 888 u_short alias_port; 889 struct in_addr alias_address; 890 struct alias_data ad = { 891 .lnk = lnk, 892 .oaddr = NULL, 893 .aaddr = &alias_address, 894 .aport = &alias_port, 895 .sport = &ud->uh_sport, 896 .dport = &ud->uh_dport, 897 .maxpktsize = 0 898 }; 899 900 /* Save original destination address, if this is a proxy packet. 901 * Also modify packet to include destination encoding. This may 902 * change the size of IP header. */ 903 if (proxy_type != 0) { 904 SetProxyPort(lnk, dest_port); 905 SetProxyAddress(lnk, dest_address); 906 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type); 907 ud = (struct udphdr *)ip_next(pip); 908 } 909 910 alias_address = GetAliasAddress(lnk); 911 alias_port = GetAliasPort(lnk); 912 913 /* Walk out chain. */ 914 error = find_handler(OUT, UDP, la, pip, &ad); 915 916 /* If UDP checksum is not zero, adjust since source port is */ 917 /* being aliased and source address is being altered */ 918 if (ud->uh_sum != 0) { 919 int accumulate; 920 921 accumulate = ud->uh_sport; 922 accumulate -= alias_port; 923 accumulate += twowords(&pip->ip_src); 924 accumulate -= twowords(&alias_address); 925 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 926 } 927 /* Put alias port in UDP header */ 928 ud->uh_sport = alias_port; 929 930 /* Change source address */ 931 DifferentialChecksum(&pip->ip_sum, 932 &alias_address, &pip->ip_src, 2); 933 pip->ip_src = alias_address; 934 935 return (PKT_ALIAS_OK); 936 } 937 return (PKT_ALIAS_IGNORED); 938 } 939 940 941 942 static int 943 TcpAliasIn(struct libalias *la, struct ip *pip) 944 { 945 struct tcphdr *tc; 946 struct alias_link *lnk; 947 int dlen; 948 949 LIBALIAS_LOCK_ASSERT(la); 950 951 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 952 if (dlen < sizeof(struct tcphdr)) 953 return (PKT_ALIAS_IGNORED); 954 tc = (struct tcphdr *)ip_next(pip); 955 956 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, 957 tc->th_sport, tc->th_dport, 958 IPPROTO_TCP, 959 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)); 960 if (lnk != NULL) { 961 struct in_addr alias_address; 962 struct in_addr original_address; 963 struct in_addr proxy_address; 964 u_short alias_port; 965 u_short proxy_port; 966 int accumulate, error; 967 968 /* 969 * The init of MANY vars is a bit below, but aliashandlepptpin 970 * seems to need the destination port that came within the 971 * packet and not the original one looks below [*]. 972 */ 973 974 struct alias_data ad = { 975 .lnk = lnk, 976 .oaddr = NULL, 977 .aaddr = NULL, 978 .aport = NULL, 979 .sport = &tc->th_sport, 980 .dport = &tc->th_dport, 981 .maxpktsize = 0 982 }; 983 984 /* Walk out chain. */ 985 error = find_handler(IN, TCP, la, pip, &ad); 986 987 alias_address = GetAliasAddress(lnk); 988 original_address = GetOriginalAddress(lnk); 989 proxy_address = GetProxyAddress(lnk); 990 alias_port = tc->th_dport; 991 tc->th_dport = GetOriginalPort(lnk); 992 proxy_port = GetProxyPort(lnk); 993 994 /* 995 * Look above, if anyone is going to add find_handler AFTER 996 * this aliashandlepptpin/point, please redo alias_data too. 997 * Uncommenting the piece here below should be enough. 998 */ 999 #if 0 1000 struct alias_data ad = { 1001 .lnk = lnk, 1002 .oaddr = &original_address, 1003 .aaddr = &alias_address, 1004 .aport = &alias_port, 1005 .sport = &ud->uh_sport, 1006 .dport = &ud->uh_dport, 1007 .maxpktsize = 0 1008 }; 1009 1010 /* Walk out chain. */ 1011 error = find_handler(la, pip, &ad); 1012 if (error == EHDNOF) 1013 printf("Protocol handler not found\n"); 1014 #endif 1015 1016 /* Adjust TCP checksum since destination port is being unaliased */ 1017 /* and destination port is being altered. */ 1018 accumulate = alias_port; 1019 accumulate -= tc->th_dport; 1020 accumulate += twowords(&alias_address); 1021 accumulate -= twowords(&original_address); 1022 1023 /* If this is a proxy, then modify the TCP source port and 1024 checksum accumulation */ 1025 if (proxy_port != 0) { 1026 accumulate += tc->th_sport; 1027 tc->th_sport = proxy_port; 1028 accumulate -= tc->th_sport; 1029 accumulate += twowords(&pip->ip_src); 1030 accumulate -= twowords(&proxy_address); 1031 } 1032 /* See if ACK number needs to be modified */ 1033 if (GetAckModified(lnk) == 1) { 1034 int delta; 1035 1036 tc = (struct tcphdr *)ip_next(pip); 1037 delta = GetDeltaAckIn(tc->th_ack, lnk); 1038 if (delta != 0) { 1039 accumulate += twowords(&tc->th_ack); 1040 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 1041 accumulate -= twowords(&tc->th_ack); 1042 } 1043 } 1044 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1045 1046 /* Restore original IP address */ 1047 accumulate = twowords(&pip->ip_dst); 1048 pip->ip_dst = original_address; 1049 accumulate -= twowords(&pip->ip_dst); 1050 1051 /* If this is a transparent proxy packet, then modify the source 1052 address */ 1053 if (proxy_address.s_addr != 0) { 1054 accumulate += twowords(&pip->ip_src); 1055 pip->ip_src = proxy_address; 1056 accumulate -= twowords(&pip->ip_src); 1057 } 1058 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1059 1060 /* Monitor TCP connection state */ 1061 tc = (struct tcphdr *)ip_next(pip); 1062 TcpMonitorIn(tc->th_flags, lnk); 1063 1064 return (PKT_ALIAS_OK); 1065 } 1066 return (PKT_ALIAS_IGNORED); 1067 } 1068 1069 static int 1070 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) 1071 { 1072 int dlen, proxy_type, error; 1073 u_short dest_port; 1074 u_short proxy_server_port; 1075 struct in_addr dest_address; 1076 struct in_addr proxy_server_address; 1077 struct tcphdr *tc; 1078 struct alias_link *lnk; 1079 1080 LIBALIAS_LOCK_ASSERT(la); 1081 1082 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 1083 if (dlen < sizeof(struct tcphdr)) 1084 return (PKT_ALIAS_IGNORED); 1085 tc = (struct tcphdr *)ip_next(pip); 1086 1087 if (create) 1088 proxy_type = ProxyCheck(la, &proxy_server_address, 1089 &proxy_server_port, pip->ip_src, pip->ip_dst, 1090 tc->th_dport, pip->ip_p); 1091 else 1092 proxy_type = 0; 1093 1094 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 1095 return (PKT_ALIAS_OK); 1096 1097 /* If this is a transparent proxy, save original destination, 1098 then alter the destination and adjust checksums */ 1099 dest_port = tc->th_dport; 1100 dest_address = pip->ip_dst; 1101 if (proxy_type != 0) { 1102 int accumulate; 1103 1104 accumulate = tc->th_dport; 1105 tc->th_dport = proxy_server_port; 1106 accumulate -= tc->th_dport; 1107 accumulate += twowords(&pip->ip_dst); 1108 accumulate -= twowords(&proxy_server_address); 1109 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1110 1111 accumulate = twowords(&pip->ip_dst); 1112 pip->ip_dst = proxy_server_address; 1113 accumulate -= twowords(&pip->ip_dst); 1114 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1115 } 1116 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, 1117 tc->th_sport, tc->th_dport, 1118 IPPROTO_TCP, create); 1119 if (lnk == NULL) 1120 return (PKT_ALIAS_IGNORED); 1121 if (lnk != NULL) { 1122 u_short alias_port; 1123 struct in_addr alias_address; 1124 int accumulate; 1125 struct alias_data ad = { 1126 .lnk = lnk, 1127 .oaddr = NULL, 1128 .aaddr = &alias_address, 1129 .aport = &alias_port, 1130 .sport = &tc->th_sport, 1131 .dport = &tc->th_dport, 1132 .maxpktsize = maxpacketsize 1133 }; 1134 1135 /* Save original destination address, if this is a proxy packet. 1136 Also modify packet to include destination encoding. This may 1137 change the size of IP header. */ 1138 if (proxy_type != 0) { 1139 SetProxyPort(lnk, dest_port); 1140 SetProxyAddress(lnk, dest_address); 1141 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type); 1142 tc = (struct tcphdr *)ip_next(pip); 1143 } 1144 /* Get alias address and port */ 1145 alias_port = GetAliasPort(lnk); 1146 alias_address = GetAliasAddress(lnk); 1147 1148 /* Monitor TCP connection state */ 1149 tc = (struct tcphdr *)ip_next(pip); 1150 TcpMonitorOut(tc->th_flags, lnk); 1151 1152 /* Walk out chain. */ 1153 error = find_handler(OUT, TCP, la, pip, &ad); 1154 1155 /* Adjust TCP checksum since source port is being aliased */ 1156 /* and source address is being altered */ 1157 accumulate = tc->th_sport; 1158 tc->th_sport = alias_port; 1159 accumulate -= tc->th_sport; 1160 accumulate += twowords(&pip->ip_src); 1161 accumulate -= twowords(&alias_address); 1162 1163 /* Modify sequence number if necessary */ 1164 if (GetAckModified(lnk) == 1) { 1165 int delta; 1166 1167 tc = (struct tcphdr *)ip_next(pip); 1168 delta = GetDeltaSeqOut(tc->th_seq, lnk); 1169 if (delta != 0) { 1170 accumulate += twowords(&tc->th_seq); 1171 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1172 accumulate -= twowords(&tc->th_seq); 1173 } 1174 } 1175 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1176 1177 /* Change source address */ 1178 accumulate = twowords(&pip->ip_src); 1179 pip->ip_src = alias_address; 1180 accumulate -= twowords(&pip->ip_src); 1181 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1182 1183 return (PKT_ALIAS_OK); 1184 } 1185 return (PKT_ALIAS_IGNORED); 1186 } 1187 1188 1189 1190 1191 /* Fragment Handling 1192 1193 FragmentIn() 1194 FragmentOut() 1195 1196 The packet aliasing module has a limited ability for handling IP 1197 fragments. If the ICMP, TCP or UDP header is in the first fragment 1198 received, then the ID number of the IP packet is saved, and other 1199 fragments are identified according to their ID number and IP address 1200 they were sent from. Pointers to unresolved fragments can also be 1201 saved and recalled when a header fragment is seen. 1202 */ 1203 1204 /* Local prototypes */ 1205 static int FragmentIn(struct libalias *la, struct in_addr ip_src, 1206 struct in_addr *ip_dst, u_short ip_id, u_short *ip_sum); 1207 static int FragmentOut(struct libalias *, struct in_addr *ip_src, 1208 u_short *ip_sum); 1209 1210 static int 1211 FragmentIn(struct libalias *la, struct in_addr ip_src, struct in_addr *ip_dst, 1212 u_short ip_id, u_short *ip_sum) 1213 { 1214 struct alias_link *lnk; 1215 1216 LIBALIAS_LOCK_ASSERT(la); 1217 lnk = FindFragmentIn2(la, ip_src, *ip_dst, ip_id); 1218 if (lnk != NULL) { 1219 struct in_addr original_address; 1220 1221 GetFragmentAddr(lnk, &original_address); 1222 DifferentialChecksum(ip_sum, 1223 &original_address, ip_dst, 2); 1224 *ip_dst = original_address; 1225 1226 return (PKT_ALIAS_OK); 1227 } 1228 return (PKT_ALIAS_UNRESOLVED_FRAGMENT); 1229 } 1230 1231 static int 1232 FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum) 1233 { 1234 struct in_addr alias_address; 1235 1236 LIBALIAS_LOCK_ASSERT(la); 1237 alias_address = FindAliasAddress(la, *ip_src); 1238 DifferentialChecksum(ip_sum, 1239 &alias_address, ip_src, 2); 1240 *ip_src = alias_address; 1241 1242 return (PKT_ALIAS_OK); 1243 } 1244 1245 1246 1247 1248 1249 1250 /* Outside World Access 1251 1252 PacketAliasSaveFragment() 1253 PacketAliasGetFragment() 1254 PacketAliasFragmentIn() 1255 PacketAliasIn() 1256 PacketAliasOut() 1257 PacketUnaliasOut() 1258 1259 (prototypes in alias.h) 1260 */ 1261 1262 int 1263 LibAliasSaveFragment(struct libalias *la, char *ptr) 1264 { 1265 int iresult; 1266 struct alias_link *lnk; 1267 struct ip *pip; 1268 1269 LIBALIAS_LOCK(la); 1270 pip = (struct ip *)ptr; 1271 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id); 1272 iresult = PKT_ALIAS_ERROR; 1273 if (lnk != NULL) { 1274 SetFragmentPtr(lnk, ptr); 1275 iresult = PKT_ALIAS_OK; 1276 } 1277 LIBALIAS_UNLOCK(la); 1278 return (iresult); 1279 } 1280 1281 char * 1282 LibAliasGetFragment(struct libalias *la, char *ptr) 1283 { 1284 struct alias_link *lnk; 1285 char *fptr; 1286 struct ip *pip; 1287 1288 LIBALIAS_LOCK(la); 1289 pip = (struct ip *)ptr; 1290 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id); 1291 if (lnk != NULL) { 1292 GetFragmentPtr(lnk, &fptr); 1293 SetFragmentPtr(lnk, NULL); 1294 SetExpire(lnk, 0); /* Deletes link */ 1295 } else 1296 fptr = NULL; 1297 1298 LIBALIAS_UNLOCK(la); 1299 return (fptr); 1300 } 1301 1302 void 1303 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly 1304 * de-aliased header 1305 * fragment */ 1306 char *ptr_fragment /* Points to fragment which must be 1307 * de-aliased */ 1308 ) 1309 { 1310 struct ip *pip; 1311 struct ip *fpip; 1312 1313 LIBALIAS_LOCK(la); 1314 (void)la; 1315 pip = (struct ip *)ptr; 1316 fpip = (struct ip *)ptr_fragment; 1317 1318 DifferentialChecksum(&fpip->ip_sum, 1319 &pip->ip_dst, &fpip->ip_dst, 2); 1320 fpip->ip_dst = pip->ip_dst; 1321 LIBALIAS_UNLOCK(la); 1322 } 1323 1324 /* Local prototypes */ 1325 static int 1326 LibAliasOutLocked(struct libalias *la, char *ptr, 1327 int maxpacketsize, int create); 1328 static int 1329 LibAliasInLocked(struct libalias *la, char *ptr, 1330 int maxpacketsize); 1331 1332 int 1333 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) 1334 { 1335 int res; 1336 1337 LIBALIAS_LOCK(la); 1338 res = LibAliasInLocked(la, ptr, maxpacketsize); 1339 LIBALIAS_UNLOCK(la); 1340 return (res); 1341 } 1342 1343 static int 1344 LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize) 1345 { 1346 struct in_addr alias_addr; 1347 struct ip *pip; 1348 int iresult; 1349 1350 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1351 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1352 iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1); 1353 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1354 goto getout; 1355 } 1356 HouseKeeping(la); 1357 ClearCheckNewLink(la); 1358 pip = (struct ip *)ptr; 1359 alias_addr = pip->ip_dst; 1360 1361 /* Defense against mangled packets */ 1362 if (ntohs(pip->ip_len) > maxpacketsize 1363 || (pip->ip_hl << 2) > maxpacketsize) { 1364 iresult = PKT_ALIAS_IGNORED; 1365 goto getout; 1366 } 1367 1368 iresult = PKT_ALIAS_IGNORED; 1369 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1370 switch (pip->ip_p) { 1371 case IPPROTO_ICMP: 1372 iresult = IcmpAliasIn(la, pip); 1373 break; 1374 case IPPROTO_UDP: 1375 iresult = UdpAliasIn(la, pip); 1376 break; 1377 case IPPROTO_TCP: 1378 iresult = TcpAliasIn(la, pip); 1379 break; 1380 #ifdef _KERNEL 1381 case IPPROTO_SCTP: 1382 iresult = SctpAlias(la, pip, SN_TO_LOCAL); 1383 break; 1384 #endif 1385 case IPPROTO_GRE: { 1386 int error; 1387 struct alias_data ad = { 1388 .lnk = NULL, 1389 .oaddr = NULL, 1390 .aaddr = NULL, 1391 .aport = NULL, 1392 .sport = NULL, 1393 .dport = NULL, 1394 .maxpktsize = 0 1395 }; 1396 1397 /* Walk out chain. */ 1398 error = find_handler(IN, IP, la, pip, &ad); 1399 if (error == 0) 1400 iresult = PKT_ALIAS_OK; 1401 else 1402 iresult = ProtoAliasIn(la, pip->ip_src, 1403 &pip->ip_dst, pip->ip_p, &pip->ip_sum); 1404 } 1405 break; 1406 default: 1407 iresult = ProtoAliasIn(la, pip->ip_src, &pip->ip_dst, 1408 pip->ip_p, &pip->ip_sum); 1409 break; 1410 } 1411 1412 if (ntohs(pip->ip_off) & IP_MF) { 1413 struct alias_link *lnk; 1414 1415 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); 1416 if (lnk != NULL) { 1417 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1418 SetFragmentAddr(lnk, pip->ip_dst); 1419 } else { 1420 iresult = PKT_ALIAS_ERROR; 1421 } 1422 } 1423 } else { 1424 iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id, 1425 &pip->ip_sum); 1426 } 1427 1428 getout: 1429 return (iresult); 1430 } 1431 1432 1433 1434 /* Unregistered address ranges */ 1435 1436 /* 10.0.0.0 -> 10.255.255.255 */ 1437 #define UNREG_ADDR_A_LOWER 0x0a000000 1438 #define UNREG_ADDR_A_UPPER 0x0affffff 1439 1440 /* 172.16.0.0 -> 172.31.255.255 */ 1441 #define UNREG_ADDR_B_LOWER 0xac100000 1442 #define UNREG_ADDR_B_UPPER 0xac1fffff 1443 1444 /* 192.168.0.0 -> 192.168.255.255 */ 1445 #define UNREG_ADDR_C_LOWER 0xc0a80000 1446 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1447 1448 /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */ 1449 #define UNREG_ADDR_CGN_LOWER 0x64400000 1450 #define UNREG_ADDR_CGN_UPPER 0x647fffff 1451 1452 int 1453 LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize) 1454 { 1455 int res; 1456 1457 LIBALIAS_LOCK(la); 1458 res = LibAliasOutLocked(la, ptr, maxpacketsize, 1); 1459 LIBALIAS_UNLOCK(la); 1460 return (res); 1461 } 1462 1463 int 1464 LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create) 1465 { 1466 int res; 1467 1468 LIBALIAS_LOCK(la); 1469 res = LibAliasOutLocked(la, ptr, maxpacketsize, create); 1470 LIBALIAS_UNLOCK(la); 1471 return (res); 1472 } 1473 1474 static int 1475 LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */ 1476 int maxpacketsize, /* How much the packet data may grow (FTP 1477 * and IRC inline changes) */ 1478 int create /* Create new entries ? */ 1479 ) 1480 { 1481 int iresult; 1482 struct in_addr addr_save; 1483 struct ip *pip; 1484 1485 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1486 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1487 iresult = LibAliasInLocked(la, ptr, maxpacketsize); 1488 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1489 goto getout; 1490 } 1491 HouseKeeping(la); 1492 ClearCheckNewLink(la); 1493 pip = (struct ip *)ptr; 1494 1495 /* Defense against mangled packets */ 1496 if (ntohs(pip->ip_len) > maxpacketsize 1497 || (pip->ip_hl << 2) > maxpacketsize) { 1498 iresult = PKT_ALIAS_IGNORED; 1499 goto getout; 1500 } 1501 1502 addr_save = GetDefaultAliasAddress(la); 1503 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY || 1504 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) { 1505 u_long addr; 1506 int iclass; 1507 1508 iclass = 0; 1509 addr = ntohl(pip->ip_src.s_addr); 1510 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1511 iclass = 3; 1512 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1513 iclass = 2; 1514 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1515 iclass = 1; 1516 else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER && 1517 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) 1518 iclass = 4; 1519 1520 if (iclass == 0) { 1521 SetDefaultAliasAddress(la, pip->ip_src); 1522 } 1523 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { 1524 SetDefaultAliasAddress(la, pip->ip_src); 1525 } 1526 iresult = PKT_ALIAS_IGNORED; 1527 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1528 switch (pip->ip_p) { 1529 case IPPROTO_ICMP: 1530 iresult = IcmpAliasOut(la, pip, create); 1531 break; 1532 case IPPROTO_UDP: 1533 iresult = UdpAliasOut(la, pip, maxpacketsize, create); 1534 break; 1535 case IPPROTO_TCP: 1536 iresult = TcpAliasOut(la, pip, maxpacketsize, create); 1537 break; 1538 #ifdef _KERNEL 1539 case IPPROTO_SCTP: 1540 iresult = SctpAlias(la, pip, SN_TO_GLOBAL); 1541 break; 1542 #endif 1543 case IPPROTO_GRE: { 1544 int error; 1545 struct alias_data ad = { 1546 .lnk = NULL, 1547 .oaddr = NULL, 1548 .aaddr = NULL, 1549 .aport = NULL, 1550 .sport = NULL, 1551 .dport = NULL, 1552 .maxpktsize = 0 1553 }; 1554 /* Walk out chain. */ 1555 error = find_handler(OUT, IP, la, pip, &ad); 1556 if (error == 0) 1557 iresult = PKT_ALIAS_OK; 1558 else 1559 iresult = ProtoAliasOut(la, &pip->ip_src, 1560 pip->ip_dst, pip->ip_p, &pip->ip_sum, create); 1561 } 1562 break; 1563 default: 1564 iresult = ProtoAliasOut(la, &pip->ip_src, 1565 pip->ip_dst, pip->ip_p, &pip->ip_sum, create); 1566 break; 1567 } 1568 } else { 1569 iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum); 1570 } 1571 1572 SetDefaultAliasAddress(la, addr_save); 1573 getout: 1574 return (iresult); 1575 } 1576 1577 int 1578 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */ 1579 int maxpacketsize /* for error checking */ 1580 ) 1581 { 1582 struct ip *pip; 1583 struct icmp *ic; 1584 struct udphdr *ud; 1585 struct tcphdr *tc; 1586 struct alias_link *lnk; 1587 int iresult = PKT_ALIAS_IGNORED; 1588 1589 LIBALIAS_LOCK(la); 1590 pip = (struct ip *)ptr; 1591 1592 /* Defense against mangled packets */ 1593 if (ntohs(pip->ip_len) > maxpacketsize 1594 || (pip->ip_hl << 2) > maxpacketsize) 1595 goto getout; 1596 1597 ud = (struct udphdr *)ip_next(pip); 1598 tc = (struct tcphdr *)ip_next(pip); 1599 ic = (struct icmp *)ip_next(pip); 1600 1601 /* Find a link */ 1602 if (pip->ip_p == IPPROTO_UDP) 1603 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1604 ud->uh_dport, ud->uh_sport, 1605 IPPROTO_UDP, 0); 1606 else if (pip->ip_p == IPPROTO_TCP) 1607 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1608 tc->th_dport, tc->th_sport, 1609 IPPROTO_TCP, 0); 1610 else if (pip->ip_p == IPPROTO_ICMP) 1611 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1612 else 1613 lnk = NULL; 1614 1615 /* Change it from an aliased packet to an unaliased packet */ 1616 if (lnk != NULL) { 1617 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) { 1618 int accumulate; 1619 struct in_addr original_address; 1620 u_short original_port; 1621 1622 original_address = GetOriginalAddress(lnk); 1623 original_port = GetOriginalPort(lnk); 1624 1625 /* Adjust TCP/UDP checksum */ 1626 accumulate = twowords(&pip->ip_src); 1627 accumulate -= twowords(&original_address); 1628 1629 if (pip->ip_p == IPPROTO_UDP) { 1630 accumulate += ud->uh_sport; 1631 accumulate -= original_port; 1632 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1633 } else { 1634 accumulate += tc->th_sport; 1635 accumulate -= original_port; 1636 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1637 } 1638 1639 /* Adjust IP checksum */ 1640 DifferentialChecksum(&pip->ip_sum, 1641 &original_address, &pip->ip_src, 2); 1642 1643 /* Un-alias source address and port number */ 1644 pip->ip_src = original_address; 1645 if (pip->ip_p == IPPROTO_UDP) 1646 ud->uh_sport = original_port; 1647 else 1648 tc->th_sport = original_port; 1649 1650 iresult = PKT_ALIAS_OK; 1651 1652 } else if (pip->ip_p == IPPROTO_ICMP) { 1653 1654 int accumulate; 1655 struct in_addr original_address; 1656 u_short original_id; 1657 1658 original_address = GetOriginalAddress(lnk); 1659 original_id = GetOriginalPort(lnk); 1660 1661 /* Adjust ICMP checksum */ 1662 accumulate = twowords(&pip->ip_src); 1663 accumulate -= twowords(&original_address); 1664 accumulate += ic->icmp_id; 1665 accumulate -= original_id; 1666 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1667 1668 /* Adjust IP checksum */ 1669 DifferentialChecksum(&pip->ip_sum, 1670 &original_address, &pip->ip_src, 2); 1671 1672 /* Un-alias source address and port number */ 1673 pip->ip_src = original_address; 1674 ic->icmp_id = original_id; 1675 1676 iresult = PKT_ALIAS_OK; 1677 } 1678 } 1679 getout: 1680 LIBALIAS_UNLOCK(la); 1681 return (iresult); 1682 1683 } 1684 1685 #ifndef _KERNEL 1686 1687 int 1688 LibAliasRefreshModules(void) 1689 { 1690 char buf[256], conf[] = "/etc/libalias.conf"; 1691 FILE *fd; 1692 int i, len; 1693 1694 fd = fopen(conf, "r"); 1695 if (fd == NULL) 1696 err(1, "fopen(%s)", conf); 1697 1698 LibAliasUnLoadAllModule(); 1699 1700 for (;;) { 1701 fgets(buf, 256, fd); 1702 if (feof(fd)) 1703 break; 1704 len = strlen(buf); 1705 if (len > 1) { 1706 for (i = 0; i < len; i++) 1707 if (!isspace(buf[i])) 1708 break; 1709 if (buf[i] == '#') 1710 continue; 1711 buf[len - 1] = '\0'; 1712 LibAliasLoadModule(buf); 1713 } 1714 } 1715 fclose(fd); 1716 return (0); 1717 } 1718 1719 int 1720 LibAliasLoadModule(char *path) 1721 { 1722 struct dll *t; 1723 void *handle; 1724 struct proto_handler *m; 1725 const char *error; 1726 moduledata_t *p; 1727 1728 handle = dlopen (path, RTLD_LAZY); 1729 if (!handle) { 1730 fprintf(stderr, "%s\n", dlerror()); 1731 return (EINVAL); 1732 } 1733 1734 p = dlsym(handle, "alias_mod"); 1735 if ((error = dlerror()) != NULL) { 1736 fprintf(stderr, "%s\n", dlerror()); 1737 return (EINVAL); 1738 } 1739 1740 t = malloc(sizeof(struct dll)); 1741 if (t == NULL) 1742 return (ENOMEM); 1743 strncpy(t->name, p->name, DLL_LEN); 1744 t->handle = handle; 1745 if (attach_dll(t) == EEXIST) { 1746 free(t); 1747 fprintf(stderr, "dll conflict\n"); 1748 return (EEXIST); 1749 } 1750 1751 m = dlsym(t->handle, "handlers"); 1752 if ((error = dlerror()) != NULL) { 1753 fprintf(stderr, "%s\n", error); 1754 return (EINVAL); 1755 } 1756 1757 LibAliasAttachHandlers(m); 1758 return (0); 1759 } 1760 1761 int 1762 LibAliasUnLoadAllModule(void) 1763 { 1764 struct dll *t; 1765 struct proto_handler *p; 1766 1767 /* Unload all modules then reload everything. */ 1768 while ((p = first_handler()) != NULL) { 1769 LibAliasDetachHandlers(p); 1770 } 1771 while ((t = walk_dll_chain()) != NULL) { 1772 dlclose(t->handle); 1773 free(t); 1774 } 1775 return (1); 1776 } 1777 1778 #endif 1779 1780 #ifdef _KERNEL 1781 /* 1782 * m_megapullup() - this function is a big hack. 1783 * Thankfully, it's only used in ng_nat and ipfw+nat. 1784 * 1785 * It allocates an mbuf with cluster and copies the specified part of the chain 1786 * into cluster, so that it is all contiguous and can be accessed via a plain 1787 * (char *) pointer. This is required, because libalias doesn't know how to 1788 * handle mbuf chains. 1789 * 1790 * On success, m_megapullup returns an mbuf (possibly with cluster) containing 1791 * the input packet, on failure NULL. The input packet is always consumed. 1792 */ 1793 struct mbuf * 1794 m_megapullup(struct mbuf *m, int len) 1795 { 1796 struct mbuf *mcl; 1797 1798 if (len > m->m_pkthdr.len) 1799 goto bad; 1800 1801 if (m->m_next == NULL && M_WRITABLE(m)) 1802 return (m); 1803 1804 if (len <= MJUMPAGESIZE) 1805 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR); 1806 else if (len <= MJUM9BYTES) 1807 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); 1808 else if (len <= MJUM16BYTES) 1809 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES); 1810 else 1811 goto bad; 1812 if (mcl == NULL) 1813 goto bad; 1814 m_align(mcl, len); 1815 m_move_pkthdr(mcl, m); 1816 m_copydata(m, 0, len, mtod(mcl, caddr_t)); 1817 mcl->m_len = mcl->m_pkthdr.len = len; 1818 m_freem(m); 1819 1820 return (mcl); 1821 bad: 1822 m_freem(m); 1823 return (NULL); 1824 } 1825 #endif 1826