1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 847 LIBALIAS_LOCK_ASSERT(la); 848 849 ud = ValidateUdpLength(pip); 850 if (ud == NULL) 851 return (PKT_ALIAS_IGNORED); 852 853 /* Return if proxy-only mode is enabled and not proxyrule found.*/ 854 proxy_type = ProxyCheck(la, &proxy_server_address, &proxy_server_port, 855 pip->ip_src, pip->ip_dst, ud->uh_dport, pip->ip_p); 856 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 857 return (PKT_ALIAS_OK); 858 859 /* If this is a transparent proxy, save original destination, 860 * then alter the destination and adjust checksums */ 861 dest_port = ud->uh_dport; 862 dest_address = pip->ip_dst; 863 864 if (proxy_type != 0) { 865 int accumulate; 866 867 accumulate = twowords(&pip->ip_dst); 868 accumulate -= twowords(&proxy_server_address); 869 870 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 871 872 if (ud->uh_sum != 0) { 873 accumulate = twowords(&pip->ip_dst); 874 accumulate -= twowords(&proxy_server_address); 875 accumulate += ud->uh_dport; 876 accumulate -= proxy_server_port; 877 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 878 } 879 pip->ip_dst = proxy_server_address; 880 ud->uh_dport = proxy_server_port; 881 } 882 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, 883 ud->uh_sport, ud->uh_dport, 884 IPPROTO_UDP, create); 885 if (lnk != NULL) { 886 u_short alias_port; 887 struct in_addr alias_address; 888 struct alias_data ad = { 889 .lnk = lnk, 890 .oaddr = NULL, 891 .aaddr = &alias_address, 892 .aport = &alias_port, 893 .sport = &ud->uh_sport, 894 .dport = &ud->uh_dport, 895 .maxpktsize = 0 896 }; 897 898 /* Save original destination address, if this is a proxy packet. 899 * Also modify packet to include destination encoding. This may 900 * change the size of IP header. */ 901 if (proxy_type != 0) { 902 SetProxyPort(lnk, dest_port); 903 SetProxyAddress(lnk, dest_address); 904 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type); 905 ud = (struct udphdr *)ip_next(pip); 906 } 907 908 alias_address = GetAliasAddress(lnk); 909 alias_port = GetAliasPort(lnk); 910 911 /* Walk out chain. */ 912 find_handler(OUT, UDP, la, pip, &ad); 913 914 /* If UDP checksum is not zero, adjust since source port is */ 915 /* being aliased and source address is being altered */ 916 if (ud->uh_sum != 0) { 917 int accumulate; 918 919 accumulate = ud->uh_sport; 920 accumulate -= alias_port; 921 accumulate += twowords(&pip->ip_src); 922 accumulate -= twowords(&alias_address); 923 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 924 } 925 /* Put alias port in UDP header */ 926 ud->uh_sport = alias_port; 927 928 /* Change source address */ 929 DifferentialChecksum(&pip->ip_sum, 930 &alias_address, &pip->ip_src, 2); 931 pip->ip_src = alias_address; 932 933 return (PKT_ALIAS_OK); 934 } 935 return (PKT_ALIAS_IGNORED); 936 } 937 938 static int 939 TcpAliasIn(struct libalias *la, struct ip *pip) 940 { 941 struct tcphdr *tc; 942 struct alias_link *lnk; 943 size_t dlen; 944 945 LIBALIAS_LOCK_ASSERT(la); 946 947 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 948 if (dlen < sizeof(struct tcphdr)) 949 return (PKT_ALIAS_IGNORED); 950 tc = (struct tcphdr *)ip_next(pip); 951 952 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, 953 tc->th_sport, tc->th_dport, 954 IPPROTO_TCP, 955 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)); 956 if (lnk != NULL) { 957 struct in_addr alias_address; 958 struct in_addr original_address; 959 struct in_addr proxy_address; 960 u_short alias_port; 961 u_short proxy_port; 962 int accumulate; 963 964 /* 965 * The init of MANY vars is a bit below, but aliashandlepptpin 966 * seems to need the destination port that came within the 967 * packet and not the original one looks below [*]. 968 */ 969 970 struct alias_data ad = { 971 .lnk = lnk, 972 .oaddr = NULL, 973 .aaddr = NULL, 974 .aport = NULL, 975 .sport = &tc->th_sport, 976 .dport = &tc->th_dport, 977 .maxpktsize = 0 978 }; 979 980 /* Walk out chain. */ 981 find_handler(IN, TCP, la, pip, &ad); 982 983 alias_address = GetAliasAddress(lnk); 984 original_address = GetOriginalAddress(lnk); 985 proxy_address = GetProxyAddress(lnk); 986 alias_port = tc->th_dport; 987 tc->th_dport = GetOriginalPort(lnk); 988 proxy_port = GetProxyPort(lnk); 989 990 /* 991 * Look above, if anyone is going to add find_handler AFTER 992 * this aliashandlepptpin/point, please redo alias_data too. 993 * Uncommenting the piece here below should be enough. 994 */ 995 #if 0 996 struct alias_data ad = { 997 .lnk = lnk, 998 .oaddr = &original_address, 999 .aaddr = &alias_address, 1000 .aport = &alias_port, 1001 .sport = &ud->uh_sport, 1002 .dport = &ud->uh_dport, 1003 .maxpktsize = 0 1004 }; 1005 1006 /* Walk out chain. */ 1007 error = find_handler(la, pip, &ad); 1008 if (error == EHDNOF) 1009 printf("Protocol handler not found\n"); 1010 #endif 1011 1012 /* Adjust TCP checksum since destination port is being 1013 * unaliased and destination port is being altered. */ 1014 accumulate = alias_port; 1015 accumulate -= tc->th_dport; 1016 accumulate += twowords(&alias_address); 1017 accumulate -= twowords(&original_address); 1018 1019 /* If this is a proxy, then modify the TCP source port 1020 * and checksum accumulation */ 1021 if (proxy_port != 0) { 1022 accumulate += tc->th_sport; 1023 tc->th_sport = proxy_port; 1024 accumulate -= tc->th_sport; 1025 accumulate += twowords(&pip->ip_src); 1026 accumulate -= twowords(&proxy_address); 1027 } 1028 /* See if ACK number needs to be modified */ 1029 if (GetAckModified(lnk) == 1) { 1030 int delta; 1031 1032 tc = (struct tcphdr *)ip_next(pip); 1033 delta = GetDeltaAckIn(tc->th_ack, lnk); 1034 if (delta != 0) { 1035 accumulate += twowords(&tc->th_ack); 1036 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 1037 accumulate -= twowords(&tc->th_ack); 1038 } 1039 } 1040 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1041 1042 /* Restore original IP address */ 1043 accumulate = twowords(&pip->ip_dst); 1044 pip->ip_dst = original_address; 1045 accumulate -= twowords(&pip->ip_dst); 1046 1047 /* If this is a transparent proxy packet, 1048 * then modify the source address */ 1049 if (proxy_address.s_addr != 0) { 1050 accumulate += twowords(&pip->ip_src); 1051 pip->ip_src = proxy_address; 1052 accumulate -= twowords(&pip->ip_src); 1053 } 1054 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1055 1056 /* Monitor TCP connection state */ 1057 tc = (struct tcphdr *)ip_next(pip); 1058 TcpMonitorIn(tc->th_flags, lnk); 1059 1060 return (PKT_ALIAS_OK); 1061 } 1062 return (PKT_ALIAS_IGNORED); 1063 } 1064 1065 static int 1066 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) 1067 { 1068 int proxy_type; 1069 u_short dest_port; 1070 u_short proxy_server_port; 1071 size_t dlen; 1072 struct in_addr dest_address; 1073 struct in_addr proxy_server_address; 1074 struct tcphdr *tc; 1075 struct alias_link *lnk; 1076 1077 LIBALIAS_LOCK_ASSERT(la); 1078 1079 dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 1080 if (dlen < sizeof(struct tcphdr)) 1081 return (PKT_ALIAS_IGNORED); 1082 tc = (struct tcphdr *)ip_next(pip); 1083 1084 if (create) 1085 proxy_type = ProxyCheck(la, &proxy_server_address, 1086 &proxy_server_port, pip->ip_src, pip->ip_dst, 1087 tc->th_dport, pip->ip_p); 1088 else 1089 proxy_type = 0; 1090 1091 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 1092 return (PKT_ALIAS_OK); 1093 1094 /* If this is a transparent proxy, save original destination, 1095 * then alter the destination and adjust checksums */ 1096 dest_port = tc->th_dport; 1097 dest_address = pip->ip_dst; 1098 if (proxy_type != 0) { 1099 int accumulate; 1100 1101 accumulate = tc->th_dport; 1102 tc->th_dport = proxy_server_port; 1103 accumulate -= tc->th_dport; 1104 accumulate += twowords(&pip->ip_dst); 1105 accumulate -= twowords(&proxy_server_address); 1106 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1107 1108 accumulate = twowords(&pip->ip_dst); 1109 pip->ip_dst = proxy_server_address; 1110 accumulate -= twowords(&pip->ip_dst); 1111 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1112 } 1113 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, 1114 tc->th_sport, tc->th_dport, 1115 IPPROTO_TCP, create); 1116 if (lnk == NULL) 1117 return (PKT_ALIAS_IGNORED); 1118 if (lnk != NULL) { 1119 u_short alias_port; 1120 struct in_addr alias_address; 1121 int accumulate; 1122 struct alias_data ad = { 1123 .lnk = lnk, 1124 .oaddr = NULL, 1125 .aaddr = &alias_address, 1126 .aport = &alias_port, 1127 .sport = &tc->th_sport, 1128 .dport = &tc->th_dport, 1129 .maxpktsize = maxpacketsize 1130 }; 1131 1132 /* Save original destination address, if this is a proxy packet. 1133 * Also modify packet to include destination 1134 * encoding. This may change the size of IP header. */ 1135 if (proxy_type != 0) { 1136 SetProxyPort(lnk, dest_port); 1137 SetProxyAddress(lnk, dest_address); 1138 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type); 1139 tc = (struct tcphdr *)ip_next(pip); 1140 } 1141 /* Get alias address and port */ 1142 alias_port = GetAliasPort(lnk); 1143 alias_address = GetAliasAddress(lnk); 1144 1145 /* Monitor TCP connection state */ 1146 tc = (struct tcphdr *)ip_next(pip); 1147 TcpMonitorOut(tc->th_flags, lnk); 1148 1149 /* Walk out chain. */ 1150 find_handler(OUT, TCP, la, pip, &ad); 1151 1152 /* Adjust TCP checksum since source port is being aliased 1153 * and source address is being altered */ 1154 accumulate = tc->th_sport; 1155 tc->th_sport = alias_port; 1156 accumulate -= tc->th_sport; 1157 accumulate += twowords(&pip->ip_src); 1158 accumulate -= twowords(&alias_address); 1159 1160 /* Modify sequence number if necessary */ 1161 if (GetAckModified(lnk) == 1) { 1162 int delta; 1163 1164 tc = (struct tcphdr *)ip_next(pip); 1165 delta = GetDeltaSeqOut(tc->th_seq, lnk); 1166 if (delta != 0) { 1167 accumulate += twowords(&tc->th_seq); 1168 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1169 accumulate -= twowords(&tc->th_seq); 1170 } 1171 } 1172 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1173 1174 /* Change source address */ 1175 accumulate = twowords(&pip->ip_src); 1176 pip->ip_src = alias_address; 1177 accumulate -= twowords(&pip->ip_src); 1178 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1179 1180 return (PKT_ALIAS_OK); 1181 } 1182 return (PKT_ALIAS_IGNORED); 1183 } 1184 1185 /* Fragment Handling 1186 1187 FragmentIn() 1188 FragmentOut() 1189 1190 The packet aliasing module has a limited ability for handling IP 1191 fragments. If the ICMP, TCP or UDP header is in the first fragment 1192 received, then the ID number of the IP packet is saved, and other 1193 fragments are identified according to their ID number and IP address 1194 they were sent from. Pointers to unresolved fragments can also be 1195 saved and recalled when a header fragment is seen. 1196 */ 1197 1198 /* Local prototypes */ 1199 static int FragmentIn(struct libalias *la, struct in_addr ip_src, 1200 struct ip *pip, u_short ip_id, u_short *ip_sum); 1201 static int FragmentOut(struct libalias *, struct ip *pip, 1202 u_short *ip_sum); 1203 1204 static int 1205 FragmentIn(struct libalias *la, struct in_addr ip_src, struct ip *pip, 1206 u_short ip_id, u_short *ip_sum) 1207 { 1208 struct alias_link *lnk; 1209 1210 LIBALIAS_LOCK_ASSERT(la); 1211 lnk = FindFragmentIn2(la, ip_src, pip->ip_dst, ip_id); 1212 if (lnk != NULL) { 1213 struct in_addr original_address; 1214 1215 GetFragmentAddr(lnk, &original_address); 1216 DifferentialChecksum(ip_sum, 1217 &original_address, &pip->ip_dst, 2); 1218 pip->ip_dst = original_address; 1219 1220 return (PKT_ALIAS_OK); 1221 } 1222 return (PKT_ALIAS_UNRESOLVED_FRAGMENT); 1223 } 1224 1225 static int 1226 FragmentOut(struct libalias *la, struct ip *pip, u_short *ip_sum) 1227 { 1228 struct in_addr alias_address; 1229 1230 LIBALIAS_LOCK_ASSERT(la); 1231 alias_address = FindAliasAddress(la, pip->ip_src); 1232 DifferentialChecksum(ip_sum, 1233 &alias_address, &pip->ip_src, 2); 1234 pip->ip_src = alias_address; 1235 1236 return (PKT_ALIAS_OK); 1237 } 1238 1239 /* Outside World Access 1240 1241 PacketAliasSaveFragment() 1242 PacketAliasGetFragment() 1243 PacketAliasFragmentIn() 1244 PacketAliasIn() 1245 PacketAliasOut() 1246 PacketUnaliasOut() 1247 1248 (prototypes in alias.h) 1249 */ 1250 1251 int 1252 LibAliasSaveFragment(struct libalias *la, void *ptr) 1253 { 1254 int iresult; 1255 struct alias_link *lnk; 1256 struct ip *pip; 1257 1258 LIBALIAS_LOCK(la); 1259 pip = (struct ip *)ptr; 1260 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id); 1261 iresult = PKT_ALIAS_ERROR; 1262 if (lnk != NULL) { 1263 SetFragmentPtr(lnk, ptr); 1264 iresult = PKT_ALIAS_OK; 1265 } 1266 LIBALIAS_UNLOCK(la); 1267 return (iresult); 1268 } 1269 1270 void * 1271 LibAliasGetFragment(struct libalias *la, void *ptr) 1272 { 1273 struct alias_link *lnk; 1274 void *fptr; 1275 struct ip *pip; 1276 1277 LIBALIAS_LOCK(la); 1278 pip = (struct ip *)ptr; 1279 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id); 1280 if (lnk != NULL) { 1281 GetFragmentPtr(lnk, &fptr); 1282 SetFragmentPtr(lnk, NULL); 1283 SetExpire(lnk, 0); /* Deletes link */ 1284 } else 1285 fptr = NULL; 1286 1287 LIBALIAS_UNLOCK(la); 1288 return (fptr); 1289 } 1290 1291 void 1292 LibAliasFragmentIn(struct libalias *la, 1293 void *ptr, /* Points to correctly de-aliased header fragment */ 1294 void *ptr_fragment /* fragment which must be de-aliased */ 1295 ) 1296 { 1297 struct ip *pip; 1298 struct ip *fpip; 1299 1300 LIBALIAS_LOCK(la); 1301 (void)la; 1302 pip = (struct ip *)ptr; 1303 fpip = (struct ip *)ptr_fragment; 1304 1305 DifferentialChecksum(&fpip->ip_sum, 1306 &pip->ip_dst, &fpip->ip_dst, 2); 1307 fpip->ip_dst = pip->ip_dst; 1308 LIBALIAS_UNLOCK(la); 1309 } 1310 1311 /* Local prototypes */ 1312 static int 1313 LibAliasOutLocked(struct libalias *la, struct ip *pip, 1314 int maxpacketsize, int create); 1315 static int 1316 LibAliasInLocked(struct libalias *la, struct ip *pip, 1317 int maxpacketsize); 1318 1319 int 1320 LibAliasIn(struct libalias *la, void *ptr, int maxpacketsize) 1321 { 1322 int res; 1323 1324 LIBALIAS_LOCK(la); 1325 res = LibAliasInLocked(la, (struct ip *)ptr, maxpacketsize); 1326 LIBALIAS_UNLOCK(la); 1327 return (res); 1328 } 1329 1330 static int 1331 LibAliasInLocked(struct libalias *la, struct ip *pip, int maxpacketsize) 1332 { 1333 struct in_addr alias_addr; 1334 int iresult; 1335 1336 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1337 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1338 iresult = LibAliasOutLocked(la, pip, maxpacketsize, 1); 1339 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1340 goto getout; 1341 } 1342 HouseKeeping(la); 1343 alias_addr = pip->ip_dst; 1344 1345 /* Defense against mangled packets */ 1346 if (ntohs(pip->ip_len) > maxpacketsize 1347 || (pip->ip_hl << 2) > maxpacketsize) { 1348 iresult = PKT_ALIAS_IGNORED; 1349 goto getout; 1350 } 1351 1352 if (FRAG_NO_HDR(pip)) { 1353 iresult = FragmentIn(la, pip->ip_src, pip, pip->ip_id, 1354 &pip->ip_sum); 1355 goto getout; 1356 } 1357 1358 iresult = PKT_ALIAS_IGNORED; 1359 switch (pip->ip_p) { 1360 case IPPROTO_ICMP: 1361 iresult = IcmpAliasIn(la, pip); 1362 break; 1363 case IPPROTO_UDP: 1364 iresult = UdpAliasIn(la, pip); 1365 break; 1366 case IPPROTO_TCP: 1367 iresult = TcpAliasIn(la, pip); 1368 break; 1369 #ifdef _KERNEL 1370 case IPPROTO_SCTP: 1371 iresult = SctpAlias(la, pip, SN_TO_LOCAL); 1372 break; 1373 #endif 1374 case IPPROTO_GRE: { 1375 int error; 1376 struct alias_data ad = { 1377 .lnk = NULL, 1378 .oaddr = NULL, 1379 .aaddr = NULL, 1380 .aport = NULL, 1381 .sport = NULL, 1382 .dport = NULL, 1383 .maxpktsize = 0 1384 }; 1385 1386 /* Walk out chain. */ 1387 error = find_handler(IN, IP, la, pip, &ad); 1388 if (error == 0) 1389 iresult = PKT_ALIAS_OK; 1390 else 1391 iresult = ProtoAliasIn(la, pip->ip_src, 1392 pip, pip->ip_p, &pip->ip_sum); 1393 break; 1394 } 1395 default: 1396 iresult = ProtoAliasIn(la, pip->ip_src, pip, 1397 pip->ip_p, &pip->ip_sum); 1398 break; 1399 } 1400 1401 if (MF_ISSET(pip)) { 1402 struct alias_link *lnk; 1403 1404 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); 1405 if (lnk != NULL) { 1406 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1407 SetFragmentAddr(lnk, pip->ip_dst); 1408 } else { 1409 iresult = PKT_ALIAS_ERROR; 1410 } 1411 } 1412 1413 getout: 1414 return (iresult); 1415 } 1416 1417 /* Unregistered address ranges */ 1418 1419 /* 10.0.0.0 -> 10.255.255.255 */ 1420 #define UNREG_ADDR_A_LOWER 0x0a000000 1421 #define UNREG_ADDR_A_UPPER 0x0affffff 1422 1423 /* 172.16.0.0 -> 172.31.255.255 */ 1424 #define UNREG_ADDR_B_LOWER 0xac100000 1425 #define UNREG_ADDR_B_UPPER 0xac1fffff 1426 1427 /* 192.168.0.0 -> 192.168.255.255 */ 1428 #define UNREG_ADDR_C_LOWER 0xc0a80000 1429 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1430 1431 /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */ 1432 #define UNREG_ADDR_CGN_LOWER 0x64400000 1433 #define UNREG_ADDR_CGN_UPPER 0x647fffff 1434 1435 int 1436 LibAliasOut(struct libalias *la, void *ptr, int maxpacketsize) 1437 { 1438 int res; 1439 1440 LIBALIAS_LOCK(la); 1441 res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, 1); 1442 LIBALIAS_UNLOCK(la); 1443 return (res); 1444 } 1445 1446 int 1447 LibAliasOutTry(struct libalias *la, void *ptr, int maxpacketsize, int create) 1448 { 1449 int res; 1450 1451 LIBALIAS_LOCK(la); 1452 res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, create); 1453 LIBALIAS_UNLOCK(la); 1454 return (res); 1455 } 1456 1457 static int 1458 LibAliasOutLocked(struct libalias *la, 1459 struct ip *pip, /* valid IP packet */ 1460 int maxpacketsize, /* How much the packet data may grow (FTP and IRC inline changes) */ 1461 int create /* Create new entries ? */ 1462 ) 1463 { 1464 int iresult; 1465 struct in_addr addr_save; 1466 1467 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1468 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1469 iresult = LibAliasInLocked(la, pip, maxpacketsize); 1470 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1471 goto getout; 1472 } 1473 HouseKeeping(la); 1474 1475 /* Defense against mangled packets */ 1476 if (ntohs(pip->ip_len) > maxpacketsize 1477 || (pip->ip_hl << 2) > maxpacketsize) { 1478 iresult = PKT_ALIAS_IGNORED; 1479 goto getout; 1480 } 1481 1482 addr_save = GetDefaultAliasAddress(la); 1483 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY || 1484 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) { 1485 u_long addr; 1486 int iclass; 1487 1488 iclass = 0; 1489 addr = ntohl(pip->ip_src.s_addr); 1490 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1491 iclass = 3; 1492 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1493 iclass = 2; 1494 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1495 iclass = 1; 1496 else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER && 1497 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) 1498 iclass = 4; 1499 1500 if (iclass == 0) { 1501 SetDefaultAliasAddress(la, pip->ip_src); 1502 } 1503 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { 1504 SetDefaultAliasAddress(la, pip->ip_src); 1505 } 1506 1507 if (FRAG_NO_HDR(pip)) { 1508 iresult = FragmentOut(la, pip, &pip->ip_sum); 1509 goto getout_restore; 1510 } 1511 1512 iresult = PKT_ALIAS_IGNORED; 1513 switch (pip->ip_p) { 1514 case IPPROTO_ICMP: 1515 iresult = IcmpAliasOut(la, pip, create); 1516 break; 1517 case IPPROTO_UDP: 1518 iresult = UdpAliasOut(la, pip, maxpacketsize, create); 1519 break; 1520 case IPPROTO_TCP: 1521 iresult = TcpAliasOut(la, pip, maxpacketsize, create); 1522 break; 1523 #ifdef _KERNEL 1524 case IPPROTO_SCTP: 1525 iresult = SctpAlias(la, pip, SN_TO_GLOBAL); 1526 break; 1527 #endif 1528 case IPPROTO_GRE: { 1529 int error; 1530 struct alias_data ad = { 1531 .lnk = NULL, 1532 .oaddr = NULL, 1533 .aaddr = NULL, 1534 .aport = NULL, 1535 .sport = NULL, 1536 .dport = NULL, 1537 .maxpktsize = 0 1538 }; 1539 /* Walk out chain. */ 1540 error = find_handler(OUT, IP, la, pip, &ad); 1541 if (error == 0) 1542 iresult = PKT_ALIAS_OK; 1543 else 1544 iresult = ProtoAliasOut(la, pip, 1545 pip->ip_dst, pip->ip_p, &pip->ip_sum, create); 1546 break; 1547 } 1548 default: 1549 iresult = ProtoAliasOut(la, pip, 1550 pip->ip_dst, pip->ip_p, &pip->ip_sum, create); 1551 break; 1552 } 1553 1554 getout_restore: 1555 SetDefaultAliasAddress(la, addr_save); 1556 getout: 1557 return (iresult); 1558 } 1559 1560 int 1561 LibAliasUnaliasOut(struct libalias *la, 1562 void *ptr, /* valid IP packet */ 1563 int maxpacketsize /* for error checking */ 1564 ) 1565 { 1566 struct ip *pip; 1567 struct icmp *ic; 1568 struct udphdr *ud; 1569 struct tcphdr *tc; 1570 struct alias_link *lnk; 1571 int iresult = PKT_ALIAS_IGNORED; 1572 1573 LIBALIAS_LOCK(la); 1574 pip = (struct ip *)ptr; 1575 1576 /* Defense against mangled packets */ 1577 if (ntohs(pip->ip_len) > maxpacketsize 1578 || (pip->ip_hl << 2) > maxpacketsize) 1579 goto getout; 1580 1581 ud = (struct udphdr *)ip_next(pip); 1582 tc = (struct tcphdr *)ip_next(pip); 1583 ic = (struct icmp *)ip_next(pip); 1584 1585 /* Find a link */ 1586 if (pip->ip_p == IPPROTO_UDP) 1587 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1588 ud->uh_dport, ud->uh_sport, 1589 IPPROTO_UDP, 0); 1590 else if (pip->ip_p == IPPROTO_TCP) 1591 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1592 tc->th_dport, tc->th_sport, 1593 IPPROTO_TCP, 0); 1594 else if (pip->ip_p == IPPROTO_ICMP) 1595 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1596 else 1597 lnk = NULL; 1598 1599 /* Change it from an aliased packet to an unaliased packet */ 1600 if (lnk != NULL) { 1601 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) { 1602 int accumulate; 1603 struct in_addr original_address; 1604 u_short original_port; 1605 1606 original_address = GetOriginalAddress(lnk); 1607 original_port = GetOriginalPort(lnk); 1608 1609 /* Adjust TCP/UDP checksum */ 1610 accumulate = twowords(&pip->ip_src); 1611 accumulate -= twowords(&original_address); 1612 1613 if (pip->ip_p == IPPROTO_UDP) { 1614 accumulate += ud->uh_sport; 1615 accumulate -= original_port; 1616 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1617 } else { 1618 accumulate += tc->th_sport; 1619 accumulate -= original_port; 1620 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1621 } 1622 1623 /* Adjust IP checksum */ 1624 DifferentialChecksum(&pip->ip_sum, 1625 &original_address, &pip->ip_src, 2); 1626 1627 /* Un-alias source address and port number */ 1628 pip->ip_src = original_address; 1629 if (pip->ip_p == IPPROTO_UDP) 1630 ud->uh_sport = original_port; 1631 else 1632 tc->th_sport = original_port; 1633 1634 iresult = PKT_ALIAS_OK; 1635 } else if (pip->ip_p == IPPROTO_ICMP) { 1636 int accumulate; 1637 struct in_addr original_address; 1638 u_short original_id; 1639 1640 original_address = GetOriginalAddress(lnk); 1641 original_id = GetOriginalPort(lnk); 1642 1643 /* Adjust ICMP checksum */ 1644 accumulate = twowords(&pip->ip_src); 1645 accumulate -= twowords(&original_address); 1646 accumulate += ic->icmp_id; 1647 accumulate -= original_id; 1648 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1649 1650 /* Adjust IP checksum */ 1651 DifferentialChecksum(&pip->ip_sum, 1652 &original_address, &pip->ip_src, 2); 1653 1654 /* Un-alias source address and port number */ 1655 pip->ip_src = original_address; 1656 ic->icmp_id = original_id; 1657 1658 iresult = PKT_ALIAS_OK; 1659 } 1660 } 1661 getout: 1662 LIBALIAS_UNLOCK(la); 1663 return (iresult); 1664 } 1665 1666 #ifndef _KERNEL 1667 1668 int 1669 LibAliasRefreshModules(void) 1670 { 1671 char buf[256], conf[] = "/etc/libalias.conf"; 1672 FILE *fd; 1673 int i, len; 1674 1675 fd = fopen(conf, "r"); 1676 if (fd == NULL) 1677 err(1, "fopen(%s)", conf); 1678 1679 LibAliasUnLoadAllModule(); 1680 1681 for (;;) { 1682 fgets(buf, 256, fd); 1683 if (feof(fd)) 1684 break; 1685 len = strlen(buf); 1686 if (len > 1) { 1687 for (i = 0; i < len; i++) 1688 if (!isspace(buf[i])) 1689 break; 1690 if (buf[i] == '#') 1691 continue; 1692 buf[len - 1] = '\0'; 1693 LibAliasLoadModule(buf); 1694 } 1695 } 1696 fclose(fd); 1697 return (0); 1698 } 1699 1700 int 1701 LibAliasLoadModule(char *path) 1702 { 1703 struct dll *t; 1704 void *handle; 1705 struct proto_handler *m; 1706 const char *error; 1707 moduledata_t *p; 1708 1709 handle = dlopen (path, RTLD_LAZY); 1710 if (!handle) { 1711 fprintf(stderr, "%s\n", dlerror()); 1712 return (EINVAL); 1713 } 1714 1715 p = dlsym(handle, "alias_mod"); 1716 if ((error = dlerror()) != NULL) { 1717 fprintf(stderr, "%s\n", dlerror()); 1718 return (EINVAL); 1719 } 1720 1721 t = malloc(sizeof(struct dll)); 1722 if (t == NULL) 1723 return (ENOMEM); 1724 strncpy(t->name, p->name, DLL_LEN); 1725 t->handle = handle; 1726 if (attach_dll(t) == EEXIST) { 1727 free(t); 1728 fprintf(stderr, "dll conflict\n"); 1729 return (EEXIST); 1730 } 1731 1732 m = dlsym(t->handle, "handlers"); 1733 if ((error = dlerror()) != NULL) { 1734 fprintf(stderr, "%s\n", error); 1735 return (EINVAL); 1736 } 1737 1738 LibAliasAttachHandlers(m); 1739 return (0); 1740 } 1741 1742 int 1743 LibAliasUnLoadAllModule(void) 1744 { 1745 struct dll *t; 1746 struct proto_handler *p; 1747 1748 /* Unload all modules then reload everything. */ 1749 while ((p = first_handler()) != NULL) { 1750 LibAliasDetachHandlers(p); 1751 } 1752 while ((t = walk_dll_chain()) != NULL) { 1753 dlclose(t->handle); 1754 free(t); 1755 } 1756 return (1); 1757 } 1758 1759 #endif 1760 1761 #ifdef _KERNEL 1762 /* 1763 * m_megapullup() - this function is a big hack. 1764 * Thankfully, it's only used in ng_nat and ipfw+nat. 1765 * 1766 * It allocates an mbuf with cluster and copies the specified part of the chain 1767 * into cluster, so that it is all contiguous and can be accessed via a plain 1768 * (char *) pointer. This is required, because libalias doesn't know how to 1769 * handle mbuf chains. 1770 * 1771 * On success, m_megapullup returns an mbuf (possibly with cluster) containing 1772 * the input packet, on failure NULL. The input packet is always consumed. 1773 */ 1774 struct mbuf * 1775 m_megapullup(struct mbuf *m, int len) 1776 { 1777 struct mbuf *mcl; 1778 1779 if (len > m->m_pkthdr.len) 1780 goto bad; 1781 1782 if (m->m_next == NULL && M_WRITABLE(m)) 1783 return (m); 1784 1785 if (len <= MJUMPAGESIZE) 1786 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR); 1787 else if (len <= MJUM9BYTES) 1788 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); 1789 else if (len <= MJUM16BYTES) 1790 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES); 1791 else 1792 goto bad; 1793 if (mcl == NULL) 1794 goto bad; 1795 m_align(mcl, len); 1796 m_move_pkthdr(mcl, m); 1797 m_copydata(m, 0, len, mtod(mcl, caddr_t)); 1798 mcl->m_len = mcl->m_pkthdr.len = len; 1799 m_freem(m); 1800 1801 return (mcl); 1802 bad: 1803 m_freem(m); 1804 return (NULL); 1805 } 1806 #endif 1807