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