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 alias_addr = pip->ip_dst; 1334 1335 /* Defense against mangled packets */ 1336 if (ntohs(pip->ip_len) > maxpacketsize 1337 || (pip->ip_hl << 2) > maxpacketsize) { 1338 iresult = PKT_ALIAS_IGNORED; 1339 goto getout; 1340 } 1341 1342 iresult = PKT_ALIAS_IGNORED; 1343 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1344 switch (pip->ip_p) { 1345 case IPPROTO_ICMP: 1346 iresult = IcmpAliasIn(la, pip); 1347 break; 1348 case IPPROTO_UDP: 1349 iresult = UdpAliasIn(la, pip); 1350 break; 1351 case IPPROTO_TCP: 1352 iresult = TcpAliasIn(la, pip); 1353 break; 1354 #ifdef _KERNEL 1355 case IPPROTO_SCTP: 1356 iresult = SctpAlias(la, pip, SN_TO_LOCAL); 1357 break; 1358 #endif 1359 case IPPROTO_GRE: { 1360 int error; 1361 struct alias_data ad = { 1362 .lnk = NULL, 1363 .oaddr = NULL, 1364 .aaddr = NULL, 1365 .aport = NULL, 1366 .sport = NULL, 1367 .dport = NULL, 1368 .maxpktsize = 0 1369 }; 1370 1371 /* Walk out chain. */ 1372 error = find_handler(IN, IP, la, pip, &ad); 1373 if (error == 0) 1374 iresult = PKT_ALIAS_OK; 1375 else 1376 iresult = ProtoAliasIn(la, pip->ip_src, 1377 pip, pip->ip_p, &pip->ip_sum); 1378 break; 1379 } 1380 default: 1381 iresult = ProtoAliasIn(la, pip->ip_src, pip, 1382 pip->ip_p, &pip->ip_sum); 1383 break; 1384 } 1385 1386 if (ntohs(pip->ip_off) & IP_MF) { 1387 struct alias_link *lnk; 1388 1389 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); 1390 if (lnk != NULL) { 1391 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1392 SetFragmentAddr(lnk, pip->ip_dst); 1393 } else { 1394 iresult = PKT_ALIAS_ERROR; 1395 } 1396 } 1397 } else { 1398 iresult = FragmentIn(la, pip->ip_src, pip, pip->ip_id, 1399 &pip->ip_sum); 1400 } 1401 1402 getout: 1403 return (iresult); 1404 } 1405 1406 /* Unregistered address ranges */ 1407 1408 /* 10.0.0.0 -> 10.255.255.255 */ 1409 #define UNREG_ADDR_A_LOWER 0x0a000000 1410 #define UNREG_ADDR_A_UPPER 0x0affffff 1411 1412 /* 172.16.0.0 -> 172.31.255.255 */ 1413 #define UNREG_ADDR_B_LOWER 0xac100000 1414 #define UNREG_ADDR_B_UPPER 0xac1fffff 1415 1416 /* 192.168.0.0 -> 192.168.255.255 */ 1417 #define UNREG_ADDR_C_LOWER 0xc0a80000 1418 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1419 1420 /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */ 1421 #define UNREG_ADDR_CGN_LOWER 0x64400000 1422 #define UNREG_ADDR_CGN_UPPER 0x647fffff 1423 1424 int 1425 LibAliasOut(struct libalias *la, void *ptr, int maxpacketsize) 1426 { 1427 int res; 1428 1429 LIBALIAS_LOCK(la); 1430 res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, 1); 1431 LIBALIAS_UNLOCK(la); 1432 return (res); 1433 } 1434 1435 int 1436 LibAliasOutTry(struct libalias *la, void *ptr, int maxpacketsize, int create) 1437 { 1438 int res; 1439 1440 LIBALIAS_LOCK(la); 1441 res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, create); 1442 LIBALIAS_UNLOCK(la); 1443 return (res); 1444 } 1445 1446 static int 1447 LibAliasOutLocked(struct libalias *la, 1448 struct ip *pip, /* valid IP packet */ 1449 int maxpacketsize, /* How much the packet data may grow (FTP and IRC inline changes) */ 1450 int create /* Create new entries ? */ 1451 ) 1452 { 1453 int iresult; 1454 struct in_addr addr_save; 1455 1456 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1457 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1458 iresult = LibAliasInLocked(la, pip, maxpacketsize); 1459 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1460 goto getout; 1461 } 1462 HouseKeeping(la); 1463 1464 /* Defense against mangled packets */ 1465 if (ntohs(pip->ip_len) > maxpacketsize 1466 || (pip->ip_hl << 2) > maxpacketsize) { 1467 iresult = PKT_ALIAS_IGNORED; 1468 goto getout; 1469 } 1470 1471 addr_save = GetDefaultAliasAddress(la); 1472 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY || 1473 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) { 1474 u_long addr; 1475 int iclass; 1476 1477 iclass = 0; 1478 addr = ntohl(pip->ip_src.s_addr); 1479 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1480 iclass = 3; 1481 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1482 iclass = 2; 1483 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1484 iclass = 1; 1485 else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER && 1486 la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) 1487 iclass = 4; 1488 1489 if (iclass == 0) { 1490 SetDefaultAliasAddress(la, pip->ip_src); 1491 } 1492 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { 1493 SetDefaultAliasAddress(la, pip->ip_src); 1494 } 1495 iresult = PKT_ALIAS_IGNORED; 1496 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1497 switch (pip->ip_p) { 1498 case IPPROTO_ICMP: 1499 iresult = IcmpAliasOut(la, pip, create); 1500 break; 1501 case IPPROTO_UDP: 1502 iresult = UdpAliasOut(la, pip, maxpacketsize, create); 1503 break; 1504 case IPPROTO_TCP: 1505 iresult = TcpAliasOut(la, pip, maxpacketsize, create); 1506 break; 1507 #ifdef _KERNEL 1508 case IPPROTO_SCTP: 1509 iresult = SctpAlias(la, pip, SN_TO_GLOBAL); 1510 break; 1511 #endif 1512 case IPPROTO_GRE: { 1513 int error; 1514 struct alias_data ad = { 1515 .lnk = NULL, 1516 .oaddr = NULL, 1517 .aaddr = NULL, 1518 .aport = NULL, 1519 .sport = NULL, 1520 .dport = NULL, 1521 .maxpktsize = 0 1522 }; 1523 /* Walk out chain. */ 1524 error = find_handler(OUT, IP, la, pip, &ad); 1525 if (error == 0) 1526 iresult = PKT_ALIAS_OK; 1527 else 1528 iresult = ProtoAliasOut(la, pip, 1529 pip->ip_dst, pip->ip_p, &pip->ip_sum, create); 1530 break; 1531 } 1532 default: 1533 iresult = ProtoAliasOut(la, pip, 1534 pip->ip_dst, pip->ip_p, &pip->ip_sum, create); 1535 break; 1536 } 1537 } else { 1538 iresult = FragmentOut(la, pip, &pip->ip_sum); 1539 } 1540 1541 SetDefaultAliasAddress(la, addr_save); 1542 getout: 1543 return (iresult); 1544 } 1545 1546 int 1547 LibAliasUnaliasOut(struct libalias *la, 1548 void *ptr, /* valid IP packet */ 1549 int maxpacketsize /* for error checking */ 1550 ) 1551 { 1552 struct ip *pip; 1553 struct icmp *ic; 1554 struct udphdr *ud; 1555 struct tcphdr *tc; 1556 struct alias_link *lnk; 1557 int iresult = PKT_ALIAS_IGNORED; 1558 1559 LIBALIAS_LOCK(la); 1560 pip = (struct ip *)ptr; 1561 1562 /* Defense against mangled packets */ 1563 if (ntohs(pip->ip_len) > maxpacketsize 1564 || (pip->ip_hl << 2) > maxpacketsize) 1565 goto getout; 1566 1567 ud = (struct udphdr *)ip_next(pip); 1568 tc = (struct tcphdr *)ip_next(pip); 1569 ic = (struct icmp *)ip_next(pip); 1570 1571 /* Find a link */ 1572 if (pip->ip_p == IPPROTO_UDP) 1573 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1574 ud->uh_dport, ud->uh_sport, 1575 IPPROTO_UDP, 0); 1576 else if (pip->ip_p == IPPROTO_TCP) 1577 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1578 tc->th_dport, tc->th_sport, 1579 IPPROTO_TCP, 0); 1580 else if (pip->ip_p == IPPROTO_ICMP) 1581 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1582 else 1583 lnk = NULL; 1584 1585 /* Change it from an aliased packet to an unaliased packet */ 1586 if (lnk != NULL) { 1587 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) { 1588 int accumulate; 1589 struct in_addr original_address; 1590 u_short original_port; 1591 1592 original_address = GetOriginalAddress(lnk); 1593 original_port = GetOriginalPort(lnk); 1594 1595 /* Adjust TCP/UDP checksum */ 1596 accumulate = twowords(&pip->ip_src); 1597 accumulate -= twowords(&original_address); 1598 1599 if (pip->ip_p == IPPROTO_UDP) { 1600 accumulate += ud->uh_sport; 1601 accumulate -= original_port; 1602 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1603 } else { 1604 accumulate += tc->th_sport; 1605 accumulate -= original_port; 1606 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1607 } 1608 1609 /* Adjust IP checksum */ 1610 DifferentialChecksum(&pip->ip_sum, 1611 &original_address, &pip->ip_src, 2); 1612 1613 /* Un-alias source address and port number */ 1614 pip->ip_src = original_address; 1615 if (pip->ip_p == IPPROTO_UDP) 1616 ud->uh_sport = original_port; 1617 else 1618 tc->th_sport = original_port; 1619 1620 iresult = PKT_ALIAS_OK; 1621 } else if (pip->ip_p == IPPROTO_ICMP) { 1622 int accumulate; 1623 struct in_addr original_address; 1624 u_short original_id; 1625 1626 original_address = GetOriginalAddress(lnk); 1627 original_id = GetOriginalPort(lnk); 1628 1629 /* Adjust ICMP checksum */ 1630 accumulate = twowords(&pip->ip_src); 1631 accumulate -= twowords(&original_address); 1632 accumulate += ic->icmp_id; 1633 accumulate -= original_id; 1634 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1635 1636 /* Adjust IP checksum */ 1637 DifferentialChecksum(&pip->ip_sum, 1638 &original_address, &pip->ip_src, 2); 1639 1640 /* Un-alias source address and port number */ 1641 pip->ip_src = original_address; 1642 ic->icmp_id = original_id; 1643 1644 iresult = PKT_ALIAS_OK; 1645 } 1646 } 1647 getout: 1648 LIBALIAS_UNLOCK(la); 1649 return (iresult); 1650 } 1651 1652 #ifndef _KERNEL 1653 1654 int 1655 LibAliasRefreshModules(void) 1656 { 1657 char buf[256], conf[] = "/etc/libalias.conf"; 1658 FILE *fd; 1659 int i, len; 1660 1661 fd = fopen(conf, "r"); 1662 if (fd == NULL) 1663 err(1, "fopen(%s)", conf); 1664 1665 LibAliasUnLoadAllModule(); 1666 1667 for (;;) { 1668 fgets(buf, 256, fd); 1669 if (feof(fd)) 1670 break; 1671 len = strlen(buf); 1672 if (len > 1) { 1673 for (i = 0; i < len; i++) 1674 if (!isspace(buf[i])) 1675 break; 1676 if (buf[i] == '#') 1677 continue; 1678 buf[len - 1] = '\0'; 1679 LibAliasLoadModule(buf); 1680 } 1681 } 1682 fclose(fd); 1683 return (0); 1684 } 1685 1686 int 1687 LibAliasLoadModule(char *path) 1688 { 1689 struct dll *t; 1690 void *handle; 1691 struct proto_handler *m; 1692 const char *error; 1693 moduledata_t *p; 1694 1695 handle = dlopen (path, RTLD_LAZY); 1696 if (!handle) { 1697 fprintf(stderr, "%s\n", dlerror()); 1698 return (EINVAL); 1699 } 1700 1701 p = dlsym(handle, "alias_mod"); 1702 if ((error = dlerror()) != NULL) { 1703 fprintf(stderr, "%s\n", dlerror()); 1704 return (EINVAL); 1705 } 1706 1707 t = malloc(sizeof(struct dll)); 1708 if (t == NULL) 1709 return (ENOMEM); 1710 strncpy(t->name, p->name, DLL_LEN); 1711 t->handle = handle; 1712 if (attach_dll(t) == EEXIST) { 1713 free(t); 1714 fprintf(stderr, "dll conflict\n"); 1715 return (EEXIST); 1716 } 1717 1718 m = dlsym(t->handle, "handlers"); 1719 if ((error = dlerror()) != NULL) { 1720 fprintf(stderr, "%s\n", error); 1721 return (EINVAL); 1722 } 1723 1724 LibAliasAttachHandlers(m); 1725 return (0); 1726 } 1727 1728 int 1729 LibAliasUnLoadAllModule(void) 1730 { 1731 struct dll *t; 1732 struct proto_handler *p; 1733 1734 /* Unload all modules then reload everything. */ 1735 while ((p = first_handler()) != NULL) { 1736 LibAliasDetachHandlers(p); 1737 } 1738 while ((t = walk_dll_chain()) != NULL) { 1739 dlclose(t->handle); 1740 free(t); 1741 } 1742 return (1); 1743 } 1744 1745 #endif 1746 1747 #ifdef _KERNEL 1748 /* 1749 * m_megapullup() - this function is a big hack. 1750 * Thankfully, it's only used in ng_nat and ipfw+nat. 1751 * 1752 * It allocates an mbuf with cluster and copies the specified part of the chain 1753 * into cluster, so that it is all contiguous and can be accessed via a plain 1754 * (char *) pointer. This is required, because libalias doesn't know how to 1755 * handle mbuf chains. 1756 * 1757 * On success, m_megapullup returns an mbuf (possibly with cluster) containing 1758 * the input packet, on failure NULL. The input packet is always consumed. 1759 */ 1760 struct mbuf * 1761 m_megapullup(struct mbuf *m, int len) 1762 { 1763 struct mbuf *mcl; 1764 1765 if (len > m->m_pkthdr.len) 1766 goto bad; 1767 1768 if (m->m_next == NULL && M_WRITABLE(m)) 1769 return (m); 1770 1771 if (len <= MJUMPAGESIZE) 1772 mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR); 1773 else if (len <= MJUM9BYTES) 1774 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); 1775 else if (len <= MJUM16BYTES) 1776 mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES); 1777 else 1778 goto bad; 1779 if (mcl == NULL) 1780 goto bad; 1781 m_align(mcl, len); 1782 m_move_pkthdr(mcl, m); 1783 m_copydata(m, 0, len, mtod(mcl, caddr_t)); 1784 mcl->m_len = mcl->m_pkthdr.len = len; 1785 m_freem(m); 1786 1787 return (mcl); 1788 bad: 1789 m_freem(m); 1790 return (NULL); 1791 } 1792 #endif 1793