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