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