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