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