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