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