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