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 #include <sys/types.h> 115 116 #include <netinet/in_systm.h> 117 #include <netinet/in.h> 118 #include <netinet/ip.h> 119 #include <netinet/ip_icmp.h> 120 #include <netinet/tcp.h> 121 #include <netinet/udp.h> 122 123 #include <stdio.h> 124 125 #include "alias_local.h" 126 #include "alias.h" 127 128 #define NETBIOS_NS_PORT_NUMBER 137 129 #define NETBIOS_DGM_PORT_NUMBER 138 130 #define FTP_CONTROL_PORT_NUMBER 21 131 #define IRC_CONTROL_PORT_NUMBER_1 6667 132 #define IRC_CONTROL_PORT_NUMBER_2 6668 133 #define CUSEEME_PORT_NUMBER 7648 134 #define RTSP_CONTROL_PORT_NUMBER_1 554 135 #define RTSP_CONTROL_PORT_NUMBER_2 7070 136 #define TFTP_PORT_NUMBER 69 137 #define PPTP_CONTROL_PORT_NUMBER 1723 138 139 static __inline int 140 twowords(void *p) 141 { 142 uint8_t *c = p; 143 144 #if BYTE_ORDER == LITTLE_ENDIAN 145 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0]; 146 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2]; 147 #else 148 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1]; 149 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3]; 150 #endif 151 return (s1 + s2); 152 } 153 154 /* TCP Handling Routines 155 156 TcpMonitorIn() -- These routines monitor TCP connections, and 157 TcpMonitorOut() delete a link when a connection is closed. 158 159 These routines look for SYN, FIN and RST flags to determine when TCP 160 connections open and close. When a TCP connection closes, the data 161 structure containing packet aliasing information is deleted after 162 a timeout period. 163 */ 164 165 /* Local prototypes */ 166 static void TcpMonitorIn(struct ip *, struct alias_link *); 167 168 static void TcpMonitorOut(struct ip *, struct alias_link *); 169 170 171 static void 172 TcpMonitorIn(struct ip *pip, struct alias_link *lnk) 173 { 174 struct tcphdr *tc; 175 176 tc = (struct tcphdr *)ip_next(pip); 177 178 switch (GetStateIn(lnk)) { 179 case ALIAS_TCP_STATE_NOT_CONNECTED: 180 if (tc->th_flags & TH_RST) 181 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED); 182 else if (tc->th_flags & TH_SYN) 183 SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED); 184 break; 185 case ALIAS_TCP_STATE_CONNECTED: 186 if (tc->th_flags & (TH_FIN | TH_RST)) 187 SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED); 188 break; 189 } 190 } 191 192 static void 193 TcpMonitorOut(struct ip *pip, struct alias_link *lnk) 194 { 195 struct tcphdr *tc; 196 197 tc = (struct tcphdr *)ip_next(pip); 198 199 switch (GetStateOut(lnk)) { 200 case ALIAS_TCP_STATE_NOT_CONNECTED: 201 if (tc->th_flags & TH_RST) 202 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED); 203 else if (tc->th_flags & TH_SYN) 204 SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED); 205 break; 206 case ALIAS_TCP_STATE_CONNECTED: 207 if (tc->th_flags & (TH_FIN | TH_RST)) 208 SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED); 209 break; 210 } 211 } 212 213 214 215 216 217 /* Protocol Specific Packet Aliasing Routines 218 219 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2() 220 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2() 221 ProtoAliasIn(), ProtoAliasOut() 222 UdpAliasIn(), UdpAliasOut() 223 TcpAliasIn(), TcpAliasOut() 224 225 These routines handle protocol specific details of packet aliasing. 226 One may observe a certain amount of repetitive arithmetic in these 227 functions, the purpose of which is to compute a revised checksum 228 without actually summing over the entire data packet, which could be 229 unnecessarily time consuming. 230 231 The purpose of the packet aliasing routines is to replace the source 232 address of the outgoing packet and then correctly put it back for 233 any incoming packets. For TCP and UDP, ports are also re-mapped. 234 235 For ICMP echo/timestamp requests and replies, the following scheme 236 is used: the ID number is replaced by an alias for the outgoing 237 packet. 238 239 ICMP error messages are handled by looking at the IP fragment 240 in the data section of the message. 241 242 For TCP and UDP protocols, a port number is chosen for an outgoing 243 packet, and then incoming packets are identified by IP address and 244 port numbers. For TCP packets, there is additional logic in the event 245 that sequence and ACK numbers have been altered (as in the case for 246 FTP data port commands). 247 248 The port numbers used by the packet aliasing module are not true 249 ports in the Unix sense. No sockets are actually bound to ports. 250 They are more correctly thought of as placeholders. 251 252 All packets go through the aliasing mechanism, whether they come from 253 the gateway machine or other machines on a local area network. 254 */ 255 256 257 /* Local prototypes */ 258 static int IcmpAliasIn1(struct libalias *, struct ip *); 259 static int IcmpAliasIn2(struct libalias *, struct ip *); 260 static int IcmpAliasIn(struct libalias *, struct ip *); 261 262 static int IcmpAliasOut1(struct libalias *, struct ip *, int create); 263 static int IcmpAliasOut2(struct libalias *, struct ip *); 264 static int IcmpAliasOut(struct libalias *, struct ip *, int create); 265 266 static int ProtoAliasIn(struct libalias *, struct ip *); 267 static int ProtoAliasOut(struct libalias *, struct ip *, int create); 268 269 static int UdpAliasIn(struct libalias *, struct ip *); 270 static int UdpAliasOut(struct libalias *, struct ip *, int create); 271 272 static int TcpAliasIn(struct libalias *, struct ip *); 273 static int TcpAliasOut(struct libalias *, struct ip *, int, int create); 274 275 276 static int 277 IcmpAliasIn1(struct libalias *la, struct ip *pip) 278 { 279 /* 280 De-alias incoming echo and timestamp replies. 281 Alias incoming echo and timestamp requests. 282 */ 283 struct alias_link *lnk; 284 struct icmp *ic; 285 286 ic = (struct icmp *)ip_next(pip); 287 288 /* Get source address from ICMP data field and restore original data */ 289 lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1); 290 if (lnk != NULL) { 291 u_short original_id; 292 int accumulate; 293 294 original_id = GetOriginalPort(lnk); 295 296 /* Adjust ICMP checksum */ 297 accumulate = ic->icmp_id; 298 accumulate -= original_id; 299 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 300 301 /* Put original sequence number back in */ 302 ic->icmp_id = original_id; 303 304 /* Put original address back into IP header */ 305 { 306 struct in_addr original_address; 307 308 original_address = GetOriginalAddress(lnk); 309 DifferentialChecksum(&pip->ip_sum, 310 &original_address, &pip->ip_dst, 2); 311 pip->ip_dst = original_address; 312 } 313 314 return (PKT_ALIAS_OK); 315 } 316 return (PKT_ALIAS_IGNORED); 317 } 318 319 static int 320 IcmpAliasIn2(struct libalias *la, struct ip *pip) 321 { 322 /* 323 Alias incoming ICMP error messages containing 324 IP header and first 64 bits of datagram. 325 */ 326 struct ip *ip; 327 struct icmp *ic, *ic2; 328 struct udphdr *ud; 329 struct tcphdr *tc; 330 struct alias_link *lnk; 331 332 ic = (struct icmp *)ip_next(pip); 333 ip = &ic->icmp_ip; 334 335 ud = (struct udphdr *)ip_next(ip); 336 tc = (struct tcphdr *)ip_next(ip); 337 ic2 = (struct icmp *)ip_next(ip); 338 339 if (ip->ip_p == IPPROTO_UDP) 340 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src, 341 ud->uh_dport, ud->uh_sport, 342 IPPROTO_UDP, 0); 343 else if (ip->ip_p == IPPROTO_TCP) 344 lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src, 345 tc->th_dport, tc->th_sport, 346 IPPROTO_TCP, 0); 347 else if (ip->ip_p == IPPROTO_ICMP) { 348 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 349 lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 350 else 351 lnk = NULL; 352 } else 353 lnk = NULL; 354 355 if (lnk != NULL) { 356 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) { 357 int accumulate, accumulate2; 358 struct in_addr original_address; 359 u_short original_port; 360 361 original_address = GetOriginalAddress(lnk); 362 original_port = GetOriginalPort(lnk); 363 364 /* Adjust ICMP checksum */ 365 accumulate = twowords(&ip->ip_src); 366 accumulate -= twowords(&original_address); 367 accumulate += ud->uh_sport; 368 accumulate -= original_port; 369 accumulate2 = accumulate; 370 accumulate2 += ip->ip_sum; 371 ADJUST_CHECKSUM(accumulate, ip->ip_sum); 372 accumulate2 -= ip->ip_sum; 373 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum); 374 375 /* Un-alias address in IP header */ 376 DifferentialChecksum(&pip->ip_sum, 377 &original_address, &pip->ip_dst, 2); 378 pip->ip_dst = original_address; 379 380 /* Un-alias address and port number of original IP packet 381 fragment contained in ICMP data section */ 382 ip->ip_src = original_address; 383 ud->uh_sport = original_port; 384 } else if (ip->ip_p == IPPROTO_ICMP) { 385 int accumulate, accumulate2; 386 struct in_addr original_address; 387 u_short original_id; 388 389 original_address = GetOriginalAddress(lnk); 390 original_id = GetOriginalPort(lnk); 391 392 /* Adjust ICMP checksum */ 393 accumulate = twowords(&ip->ip_src); 394 accumulate -= twowords(&original_address); 395 accumulate += ic2->icmp_id; 396 accumulate -= original_id; 397 accumulate2 = accumulate; 398 accumulate2 += ip->ip_sum; 399 ADJUST_CHECKSUM(accumulate, ip->ip_sum); 400 accumulate2 -= ip->ip_sum; 401 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum); 402 403 /* Un-alias address in IP header */ 404 DifferentialChecksum(&pip->ip_sum, 405 &original_address, &pip->ip_dst, 2); 406 pip->ip_dst = original_address; 407 408 /* Un-alias address of original IP packet and sequence number of 409 embedded ICMP datagram */ 410 ip->ip_src = original_address; 411 ic2->icmp_id = original_id; 412 } 413 return (PKT_ALIAS_OK); 414 } 415 return (PKT_ALIAS_IGNORED); 416 } 417 418 419 static int 420 IcmpAliasIn(struct libalias *la, struct ip *pip) 421 { 422 int iresult; 423 struct icmp *ic; 424 425 /* Return if proxy-only mode is enabled */ 426 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 427 return (PKT_ALIAS_OK); 428 429 ic = (struct icmp *)ip_next(pip); 430 431 iresult = PKT_ALIAS_IGNORED; 432 switch (ic->icmp_type) { 433 case ICMP_ECHOREPLY: 434 case ICMP_TSTAMPREPLY: 435 if (ic->icmp_code == 0) { 436 iresult = IcmpAliasIn1(la, pip); 437 } 438 break; 439 case ICMP_UNREACH: 440 case ICMP_SOURCEQUENCH: 441 case ICMP_TIMXCEED: 442 case ICMP_PARAMPROB: 443 iresult = IcmpAliasIn2(la, pip); 444 break; 445 case ICMP_ECHO: 446 case ICMP_TSTAMP: 447 iresult = IcmpAliasIn1(la, pip); 448 break; 449 } 450 return (iresult); 451 } 452 453 454 static int 455 IcmpAliasOut1(struct libalias *la, struct ip *pip, int create) 456 { 457 /* 458 Alias outgoing echo and timestamp requests. 459 De-alias outgoing echo and timestamp replies. 460 */ 461 struct alias_link *lnk; 462 struct icmp *ic; 463 464 ic = (struct icmp *)ip_next(pip); 465 466 /* Save overwritten data for when echo packet returns */ 467 lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create); 468 if (lnk != NULL) { 469 u_short alias_id; 470 int accumulate; 471 472 alias_id = GetAliasPort(lnk); 473 474 /* Since data field is being modified, adjust ICMP checksum */ 475 accumulate = ic->icmp_id; 476 accumulate -= alias_id; 477 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 478 479 /* Alias sequence number */ 480 ic->icmp_id = alias_id; 481 482 /* Change source address */ 483 { 484 struct in_addr alias_address; 485 486 alias_address = GetAliasAddress(lnk); 487 DifferentialChecksum(&pip->ip_sum, 488 &alias_address, &pip->ip_src, 2); 489 pip->ip_src = alias_address; 490 } 491 492 return (PKT_ALIAS_OK); 493 } 494 return (PKT_ALIAS_IGNORED); 495 } 496 497 498 static int 499 IcmpAliasOut2(struct libalias *la, struct ip *pip) 500 { 501 /* 502 Alias outgoing ICMP error messages containing 503 IP header and first 64 bits of datagram. 504 */ 505 struct ip *ip; 506 struct icmp *ic, *ic2; 507 struct udphdr *ud; 508 struct tcphdr *tc; 509 struct alias_link *lnk; 510 511 ic = (struct icmp *)ip_next(pip); 512 ip = &ic->icmp_ip; 513 514 ud = (struct udphdr *)ip_next(ip); 515 tc = (struct tcphdr *)ip_next(ip); 516 ic2 = (struct icmp *)ip_next(ip); 517 518 if (ip->ip_p == IPPROTO_UDP) 519 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src, 520 ud->uh_dport, ud->uh_sport, 521 IPPROTO_UDP, 0); 522 else if (ip->ip_p == IPPROTO_TCP) 523 lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src, 524 tc->th_dport, tc->th_sport, 525 IPPROTO_TCP, 0); 526 else if (ip->ip_p == IPPROTO_ICMP) { 527 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) 528 lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); 529 else 530 lnk = NULL; 531 } else 532 lnk = NULL; 533 534 if (lnk != NULL) { 535 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) { 536 int accumulate; 537 struct in_addr alias_address; 538 u_short alias_port; 539 540 alias_address = GetAliasAddress(lnk); 541 alias_port = GetAliasPort(lnk); 542 543 /* Adjust ICMP checksum */ 544 accumulate = twowords(&ip->ip_dst); 545 accumulate -= twowords(&alias_address); 546 accumulate += ud->uh_dport; 547 accumulate -= alias_port; 548 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 549 550 /* 551 * Alias address in IP header if it comes from the host 552 * the original TCP/UDP packet was destined for. 553 */ 554 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 555 DifferentialChecksum(&pip->ip_sum, 556 &alias_address, &pip->ip_src, 2); 557 pip->ip_src = alias_address; 558 } 559 /* Alias address and port number of original IP packet 560 fragment contained in ICMP data section */ 561 ip->ip_dst = alias_address; 562 ud->uh_dport = alias_port; 563 } else if (ip->ip_p == IPPROTO_ICMP) { 564 int accumulate; 565 struct in_addr alias_address; 566 u_short alias_id; 567 568 alias_address = GetAliasAddress(lnk); 569 alias_id = GetAliasPort(lnk); 570 571 /* Adjust ICMP checksum */ 572 accumulate = twowords(&ip->ip_dst); 573 accumulate -= twowords(&alias_address); 574 accumulate += ic2->icmp_id; 575 accumulate -= alias_id; 576 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 577 578 /* 579 * Alias address in IP header if it comes from the host 580 * the original ICMP message was destined for. 581 */ 582 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { 583 DifferentialChecksum(&pip->ip_sum, 584 &alias_address, &pip->ip_src, 2); 585 pip->ip_src = alias_address; 586 } 587 /* Alias address of original IP packet and sequence number of 588 embedded ICMP datagram */ 589 ip->ip_dst = alias_address; 590 ic2->icmp_id = alias_id; 591 } 592 return (PKT_ALIAS_OK); 593 } 594 return (PKT_ALIAS_IGNORED); 595 } 596 597 598 static int 599 IcmpAliasOut(struct libalias *la, struct ip *pip, int create) 600 { 601 int iresult; 602 struct icmp *ic; 603 604 (void)create; 605 606 /* Return if proxy-only mode is enabled */ 607 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 608 return (PKT_ALIAS_OK); 609 610 ic = (struct icmp *)ip_next(pip); 611 612 iresult = PKT_ALIAS_IGNORED; 613 switch (ic->icmp_type) { 614 case ICMP_ECHO: 615 case ICMP_TSTAMP: 616 if (ic->icmp_code == 0) { 617 iresult = IcmpAliasOut1(la, pip, create); 618 } 619 break; 620 case ICMP_UNREACH: 621 case ICMP_SOURCEQUENCH: 622 case ICMP_TIMXCEED: 623 case ICMP_PARAMPROB: 624 iresult = IcmpAliasOut2(la, pip); 625 break; 626 case ICMP_ECHOREPLY: 627 case ICMP_TSTAMPREPLY: 628 iresult = IcmpAliasOut1(la, pip, create); 629 } 630 return (iresult); 631 } 632 633 634 635 static int 636 ProtoAliasIn(struct libalias *la, struct ip *pip) 637 { 638 /* 639 Handle incoming IP packets. The 640 only thing which is done in this case is to alias 641 the dest IP address of the packet to our inside 642 machine. 643 */ 644 struct alias_link *lnk; 645 646 /* Return if proxy-only mode is enabled */ 647 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 648 return (PKT_ALIAS_OK); 649 650 lnk = FindProtoIn(la, pip->ip_src, pip->ip_dst, pip->ip_p); 651 if (lnk != NULL) { 652 struct in_addr original_address; 653 654 original_address = GetOriginalAddress(lnk); 655 656 /* Restore original IP address */ 657 DifferentialChecksum(&pip->ip_sum, 658 &original_address, &pip->ip_dst, 2); 659 pip->ip_dst = original_address; 660 661 return (PKT_ALIAS_OK); 662 } 663 return (PKT_ALIAS_IGNORED); 664 } 665 666 667 static int 668 ProtoAliasOut(struct libalias *la, struct ip *pip, int create) 669 { 670 /* 671 Handle outgoing IP packets. The 672 only thing which is done in this case is to alias 673 the source IP address of the packet. 674 */ 675 struct alias_link *lnk; 676 677 (void)create; 678 679 /* Return if proxy-only mode is enabled */ 680 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 681 return (PKT_ALIAS_OK); 682 683 lnk = FindProtoOut(la, pip->ip_src, pip->ip_dst, pip->ip_p); 684 if (lnk != NULL) { 685 struct in_addr alias_address; 686 687 alias_address = GetAliasAddress(lnk); 688 689 /* Change source address */ 690 DifferentialChecksum(&pip->ip_sum, 691 &alias_address, &pip->ip_src, 2); 692 pip->ip_src = alias_address; 693 694 return (PKT_ALIAS_OK); 695 } 696 return (PKT_ALIAS_IGNORED); 697 } 698 699 700 static int 701 UdpAliasIn(struct libalias *la, struct ip *pip) 702 { 703 struct udphdr *ud; 704 struct alias_link *lnk; 705 706 /* Return if proxy-only mode is enabled */ 707 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 708 return (PKT_ALIAS_OK); 709 710 ud = (struct udphdr *)ip_next(pip); 711 712 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, 713 ud->uh_sport, ud->uh_dport, 714 IPPROTO_UDP, 1); 715 if (lnk != NULL) { 716 struct in_addr alias_address; 717 struct in_addr original_address; 718 u_short alias_port; 719 int accumulate; 720 int r = 0; 721 722 alias_address = GetAliasAddress(lnk); 723 original_address = GetOriginalAddress(lnk); 724 alias_port = ud->uh_dport; 725 ud->uh_dport = GetOriginalPort(lnk); 726 727 /* Special processing for IP encoding protocols */ 728 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 729 AliasHandleCUSeeMeIn(la, pip, original_address); 730 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 731 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 732 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) 733 r = AliasHandleUdpNbt(la, pip, lnk, &original_address, ud->uh_dport); 734 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 735 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) 736 r = AliasHandleUdpNbtNS(la, pip, lnk, &alias_address, &alias_port, 737 &original_address, &ud->uh_dport); 738 739 /* If UDP checksum is not zero, then adjust since destination port */ 740 /* is being unaliased and destination address is being altered. */ 741 if (ud->uh_sum != 0) { 742 accumulate = alias_port; 743 accumulate -= ud->uh_dport; 744 accumulate += twowords(&alias_address); 745 accumulate -= twowords(&original_address); 746 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 747 } 748 /* Restore original IP address */ 749 DifferentialChecksum(&pip->ip_sum, 750 &original_address, &pip->ip_dst, 2); 751 pip->ip_dst = original_address; 752 753 /* 754 * If we cannot figure out the packet, ignore it. 755 */ 756 if (r < 0) 757 return (PKT_ALIAS_IGNORED); 758 else 759 return (PKT_ALIAS_OK); 760 } 761 return (PKT_ALIAS_IGNORED); 762 } 763 764 static int 765 UdpAliasOut(struct libalias *la, struct ip *pip, int create) 766 { 767 struct udphdr *ud; 768 struct alias_link *lnk; 769 770 /* Return if proxy-only mode is enabled */ 771 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) 772 return (PKT_ALIAS_OK); 773 774 ud = (struct udphdr *)ip_next(pip); 775 776 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, 777 ud->uh_sport, ud->uh_dport, 778 IPPROTO_UDP, create); 779 if (lnk != NULL) { 780 u_short alias_port; 781 struct in_addr alias_address; 782 783 alias_address = GetAliasAddress(lnk); 784 alias_port = GetAliasPort(lnk); 785 786 /* Special processing for IP encoding protocols */ 787 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) 788 AliasHandleCUSeeMeOut(la, pip, lnk); 789 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */ 790 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER 791 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) 792 AliasHandleUdpNbt(la, pip, lnk, &alias_address, alias_port); 793 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER 794 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) 795 AliasHandleUdpNbtNS(la, pip, lnk, &pip->ip_src, &ud->uh_sport, 796 &alias_address, &alias_port); 797 /* 798 * We don't know in advance what TID the TFTP server will choose, 799 * so we create a wilcard link (destination port is unspecified) 800 * that will match any TID from a given destination. 801 */ 802 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER) 803 FindRtspOut(la, pip->ip_src, pip->ip_dst, 804 ud->uh_sport, alias_port, IPPROTO_UDP); 805 806 /* If UDP checksum is not zero, adjust since source port is */ 807 /* being aliased and source address is being altered */ 808 if (ud->uh_sum != 0) { 809 int accumulate; 810 811 accumulate = ud->uh_sport; 812 accumulate -= alias_port; 813 accumulate += twowords(&pip->ip_src); 814 accumulate -= twowords(&alias_address); 815 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 816 } 817 /* Put alias port in UDP header */ 818 ud->uh_sport = alias_port; 819 820 /* Change source address */ 821 DifferentialChecksum(&pip->ip_sum, 822 &alias_address, &pip->ip_src, 2); 823 pip->ip_src = alias_address; 824 825 return (PKT_ALIAS_OK); 826 } 827 return (PKT_ALIAS_IGNORED); 828 } 829 830 831 832 static int 833 TcpAliasIn(struct libalias *la, struct ip *pip) 834 { 835 struct tcphdr *tc; 836 struct alias_link *lnk; 837 838 tc = (struct tcphdr *)ip_next(pip); 839 840 lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, 841 tc->th_sport, tc->th_dport, 842 IPPROTO_TCP, 843 !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)); 844 if (lnk != NULL) { 845 struct in_addr alias_address; 846 struct in_addr original_address; 847 struct in_addr proxy_address; 848 u_short alias_port; 849 u_short proxy_port; 850 int accumulate; 851 852 /* Special processing for IP encoding protocols */ 853 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 854 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 855 AliasHandlePptpIn(la, pip, lnk); 856 else if (la->skinnyPort != 0 && (ntohs(tc->th_dport) == la->skinnyPort 857 || ntohs(tc->th_sport) == la->skinnyPort)) 858 AliasHandleSkinny(la, pip, lnk); 859 860 alias_address = GetAliasAddress(lnk); 861 original_address = GetOriginalAddress(lnk); 862 proxy_address = GetProxyAddress(lnk); 863 alias_port = tc->th_dport; 864 tc->th_dport = GetOriginalPort(lnk); 865 proxy_port = GetProxyPort(lnk); 866 867 /* Adjust TCP checksum since destination port is being unaliased */ 868 /* and destination port is being altered. */ 869 accumulate = alias_port; 870 accumulate -= tc->th_dport; 871 accumulate += twowords(&alias_address); 872 accumulate -= twowords(&original_address); 873 874 /* If this is a proxy, then modify the TCP source port and 875 checksum accumulation */ 876 if (proxy_port != 0) { 877 accumulate += tc->th_sport; 878 tc->th_sport = proxy_port; 879 accumulate -= tc->th_sport; 880 accumulate += twowords(&pip->ip_src); 881 accumulate -= twowords(&proxy_address); 882 } 883 /* See if ACK number needs to be modified */ 884 if (GetAckModified(lnk) == 1) { 885 int delta; 886 887 delta = GetDeltaAckIn(pip, lnk); 888 if (delta != 0) { 889 accumulate += twowords(&tc->th_ack); 890 tc->th_ack = htonl(ntohl(tc->th_ack) - delta); 891 accumulate -= twowords(&tc->th_ack); 892 } 893 } 894 ADJUST_CHECKSUM(accumulate, tc->th_sum); 895 896 /* Restore original IP address */ 897 accumulate = twowords(&pip->ip_dst); 898 pip->ip_dst = original_address; 899 accumulate -= twowords(&pip->ip_dst); 900 901 /* If this is a transparent proxy packet, then modify the source 902 address */ 903 if (proxy_address.s_addr != 0) { 904 accumulate += twowords(&pip->ip_src); 905 pip->ip_src = proxy_address; 906 accumulate -= twowords(&pip->ip_src); 907 } 908 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 909 910 /* Monitor TCP connection state */ 911 TcpMonitorIn(pip, lnk); 912 913 return (PKT_ALIAS_OK); 914 } 915 return (PKT_ALIAS_IGNORED); 916 } 917 918 static int 919 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) 920 { 921 int proxy_type; 922 u_short dest_port; 923 u_short proxy_server_port; 924 struct in_addr dest_address; 925 struct in_addr proxy_server_address; 926 struct tcphdr *tc; 927 struct alias_link *lnk; 928 929 tc = (struct tcphdr *)ip_next(pip); 930 931 proxy_type = ProxyCheck(la, pip, &proxy_server_address, &proxy_server_port); 932 933 if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) 934 return (PKT_ALIAS_OK); 935 936 /* If this is a transparent proxy, save original destination, 937 then alter the destination and adjust checksums */ 938 dest_port = tc->th_dport; 939 dest_address = pip->ip_dst; 940 if (proxy_type != 0) { 941 int accumulate; 942 943 accumulate = tc->th_dport; 944 tc->th_dport = proxy_server_port; 945 accumulate -= tc->th_dport; 946 accumulate += twowords(&pip->ip_dst); 947 accumulate -= twowords(&proxy_server_address); 948 ADJUST_CHECKSUM(accumulate, tc->th_sum); 949 950 accumulate = twowords(&pip->ip_dst); 951 pip->ip_dst = proxy_server_address; 952 accumulate -= twowords(&pip->ip_dst); 953 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 954 } 955 lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, 956 tc->th_sport, tc->th_dport, 957 IPPROTO_TCP, create); 958 if (lnk == NULL) 959 return (PKT_ALIAS_IGNORED); 960 if (lnk != NULL) { 961 u_short alias_port; 962 struct in_addr alias_address; 963 int accumulate; 964 965 /* Save original destination address, if this is a proxy packet. 966 Also modify packet to include destination encoding. This may 967 change the size of IP header. */ 968 if (proxy_type != 0) { 969 SetProxyPort(lnk, dest_port); 970 SetProxyAddress(lnk, dest_address); 971 ProxyModify(la, lnk, pip, maxpacketsize, proxy_type); 972 tc = (struct tcphdr *)ip_next(pip); 973 } 974 /* Get alias address and port */ 975 alias_port = GetAliasPort(lnk); 976 alias_address = GetAliasAddress(lnk); 977 978 /* Monitor TCP connection state */ 979 TcpMonitorOut(pip, lnk); 980 981 /* Special processing for IP encoding protocols */ 982 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER 983 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) 984 AliasHandleFtpOut(la, pip, lnk, maxpacketsize); 985 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 986 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) 987 AliasHandleIrcOut(la, pip, lnk, maxpacketsize); 988 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1 989 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1 990 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2 991 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 992 AliasHandleRtspOut(la, pip, lnk, maxpacketsize); 993 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER 994 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) 995 AliasHandlePptpOut(la, pip, lnk); 996 else if (la->skinnyPort != 0 && (ntohs(tc->th_sport) == la->skinnyPort 997 || ntohs(tc->th_dport) == la->skinnyPort)) 998 AliasHandleSkinny(la, pip, lnk); 999 1000 /* Adjust TCP checksum since source port is being aliased */ 1001 /* and source address is being altered */ 1002 accumulate = tc->th_sport; 1003 tc->th_sport = alias_port; 1004 accumulate -= tc->th_sport; 1005 accumulate += twowords(&pip->ip_src); 1006 accumulate -= twowords(&alias_address); 1007 1008 /* Modify sequence number if necessary */ 1009 if (GetAckModified(lnk) == 1) { 1010 int delta; 1011 1012 delta = GetDeltaSeqOut(pip, lnk); 1013 if (delta != 0) { 1014 accumulate += twowords(&tc->th_seq); 1015 tc->th_seq = htonl(ntohl(tc->th_seq) + delta); 1016 accumulate -= twowords(&tc->th_seq); 1017 } 1018 } 1019 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1020 1021 /* Change source address */ 1022 accumulate = twowords(&pip->ip_src); 1023 pip->ip_src = alias_address; 1024 accumulate -= twowords(&pip->ip_src); 1025 ADJUST_CHECKSUM(accumulate, pip->ip_sum); 1026 1027 return (PKT_ALIAS_OK); 1028 } 1029 return (PKT_ALIAS_IGNORED); 1030 } 1031 1032 1033 1034 1035 /* Fragment Handling 1036 1037 FragmentIn() 1038 FragmentOut() 1039 1040 The packet aliasing module has a limited ability for handling IP 1041 fragments. If the ICMP, TCP or UDP header is in the first fragment 1042 received, then the ID number of the IP packet is saved, and other 1043 fragments are identified according to their ID number and IP address 1044 they were sent from. Pointers to unresolved fragments can also be 1045 saved and recalled when a header fragment is seen. 1046 */ 1047 1048 /* Local prototypes */ 1049 static int FragmentIn(struct libalias *, struct ip *); 1050 static int FragmentOut(struct libalias *, struct ip *); 1051 1052 1053 static int 1054 FragmentIn(struct libalias *la, struct ip *pip) 1055 { 1056 struct alias_link *lnk; 1057 1058 lnk = FindFragmentIn2(la, pip->ip_src, pip->ip_dst, pip->ip_id); 1059 if (lnk != NULL) { 1060 struct in_addr original_address; 1061 1062 GetFragmentAddr(lnk, &original_address); 1063 DifferentialChecksum(&pip->ip_sum, 1064 &original_address, &pip->ip_dst, 2); 1065 pip->ip_dst = original_address; 1066 1067 return (PKT_ALIAS_OK); 1068 } 1069 return (PKT_ALIAS_UNRESOLVED_FRAGMENT); 1070 } 1071 1072 1073 static int 1074 FragmentOut(struct libalias *la, struct ip *pip) 1075 { 1076 struct in_addr alias_address; 1077 1078 alias_address = FindAliasAddress(la, pip->ip_src); 1079 DifferentialChecksum(&pip->ip_sum, 1080 &alias_address, &pip->ip_src, 2); 1081 pip->ip_src = alias_address; 1082 1083 return (PKT_ALIAS_OK); 1084 } 1085 1086 1087 1088 1089 1090 1091 /* Outside World Access 1092 1093 PacketAliasSaveFragment() 1094 PacketAliasGetFragment() 1095 PacketAliasFragmentIn() 1096 PacketAliasIn() 1097 PacketAliasOut() 1098 PacketUnaliasOut() 1099 1100 (prototypes in alias.h) 1101 */ 1102 1103 1104 int 1105 LibAliasSaveFragment(struct libalias *la, char *ptr) 1106 { 1107 int iresult; 1108 struct alias_link *lnk; 1109 struct ip *pip; 1110 1111 pip = (struct ip *)ptr; 1112 lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id); 1113 iresult = PKT_ALIAS_ERROR; 1114 if (lnk != NULL) { 1115 SetFragmentPtr(lnk, ptr); 1116 iresult = PKT_ALIAS_OK; 1117 } 1118 return (iresult); 1119 } 1120 1121 1122 char * 1123 LibAliasGetFragment(struct libalias *la, char *ptr) 1124 { 1125 struct alias_link *lnk; 1126 char *fptr; 1127 struct ip *pip; 1128 1129 pip = (struct ip *)ptr; 1130 lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id); 1131 if (lnk != NULL) { 1132 GetFragmentPtr(lnk, &fptr); 1133 SetFragmentPtr(lnk, NULL); 1134 SetExpire(lnk, 0); /* Deletes link */ 1135 1136 return (fptr); 1137 } else { 1138 return (NULL); 1139 } 1140 } 1141 1142 1143 void 1144 LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly 1145 * de-aliased header 1146 * fragment */ 1147 char *ptr_fragment /* Points to fragment which must be 1148 * de-aliased */ 1149 ) 1150 { 1151 struct ip *pip; 1152 struct ip *fpip; 1153 1154 (void)la; 1155 pip = (struct ip *)ptr; 1156 fpip = (struct ip *)ptr_fragment; 1157 1158 DifferentialChecksum(&fpip->ip_sum, 1159 &pip->ip_dst, &fpip->ip_dst, 2); 1160 fpip->ip_dst = pip->ip_dst; 1161 } 1162 1163 1164 int 1165 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) 1166 { 1167 struct in_addr alias_addr; 1168 struct ip *pip; 1169 int iresult; 1170 1171 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1172 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1173 iresult = PacketAliasOut(ptr, maxpacketsize); 1174 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1175 return (iresult); 1176 } 1177 HouseKeeping(la); 1178 ClearCheckNewLink(la); 1179 pip = (struct ip *)ptr; 1180 alias_addr = pip->ip_dst; 1181 1182 /* Defense against mangled packets */ 1183 if (ntohs(pip->ip_len) > maxpacketsize 1184 || (pip->ip_hl << 2) > maxpacketsize) 1185 return (PKT_ALIAS_IGNORED); 1186 1187 iresult = PKT_ALIAS_IGNORED; 1188 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1189 switch (pip->ip_p) { 1190 case IPPROTO_ICMP: 1191 iresult = IcmpAliasIn(la, pip); 1192 break; 1193 case IPPROTO_UDP: 1194 iresult = UdpAliasIn(la, pip); 1195 break; 1196 case IPPROTO_TCP: 1197 iresult = TcpAliasIn(la, pip); 1198 break; 1199 case IPPROTO_GRE: 1200 if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY || 1201 AliasHandlePptpGreIn(la, pip) == 0) 1202 iresult = PKT_ALIAS_OK; 1203 else 1204 iresult = ProtoAliasIn(la, pip); 1205 break; 1206 default: 1207 iresult = ProtoAliasIn(la, pip); 1208 break; 1209 } 1210 1211 if (ntohs(pip->ip_off) & IP_MF) { 1212 struct alias_link *lnk; 1213 1214 lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); 1215 if (lnk != NULL) { 1216 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; 1217 SetFragmentAddr(lnk, pip->ip_dst); 1218 } else { 1219 iresult = PKT_ALIAS_ERROR; 1220 } 1221 } 1222 } else { 1223 iresult = FragmentIn(la, pip); 1224 } 1225 1226 return (iresult); 1227 } 1228 1229 1230 1231 /* Unregistered address ranges */ 1232 1233 /* 10.0.0.0 -> 10.255.255.255 */ 1234 #define UNREG_ADDR_A_LOWER 0x0a000000 1235 #define UNREG_ADDR_A_UPPER 0x0affffff 1236 1237 /* 172.16.0.0 -> 172.31.255.255 */ 1238 #define UNREG_ADDR_B_LOWER 0xac100000 1239 #define UNREG_ADDR_B_UPPER 0xac1fffff 1240 1241 /* 192.168.0.0 -> 192.168.255.255 */ 1242 #define UNREG_ADDR_C_LOWER 0xc0a80000 1243 #define UNREG_ADDR_C_UPPER 0xc0a8ffff 1244 1245 int 1246 LibAliasOut(struct libalias *la, char *ptr, /* valid IP packet */ 1247 int maxpacketsize /* How much the packet data may grow (FTP 1248 * and IRC inline changes) */ 1249 ) 1250 { 1251 return (LibAliasOutTry(la, ptr, maxpacketsize, 1)); 1252 } 1253 1254 int 1255 LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */ 1256 int maxpacketsize, /* How much the packet data may grow (FTP 1257 * and IRC inline changes) */ 1258 int create /* Create new entries ? */ 1259 ) 1260 { 1261 int iresult; 1262 struct in_addr addr_save; 1263 struct ip *pip; 1264 1265 if (la->packetAliasMode & PKT_ALIAS_REVERSE) { 1266 la->packetAliasMode &= ~PKT_ALIAS_REVERSE; 1267 iresult = PacketAliasIn(ptr, maxpacketsize); 1268 la->packetAliasMode |= PKT_ALIAS_REVERSE; 1269 return (iresult); 1270 } 1271 HouseKeeping(la); 1272 ClearCheckNewLink(la); 1273 pip = (struct ip *)ptr; 1274 1275 /* Defense against mangled packets */ 1276 if (ntohs(pip->ip_len) > maxpacketsize 1277 || (pip->ip_hl << 2) > maxpacketsize) 1278 return (PKT_ALIAS_IGNORED); 1279 1280 addr_save = GetDefaultAliasAddress(la); 1281 if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) { 1282 u_long addr; 1283 int iclass; 1284 1285 iclass = 0; 1286 addr = ntohl(pip->ip_src.s_addr); 1287 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) 1288 iclass = 3; 1289 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) 1290 iclass = 2; 1291 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) 1292 iclass = 1; 1293 1294 if (iclass == 0) { 1295 SetDefaultAliasAddress(la, pip->ip_src); 1296 } 1297 } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { 1298 SetDefaultAliasAddress(la, pip->ip_src); 1299 } 1300 iresult = PKT_ALIAS_IGNORED; 1301 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 1302 switch (pip->ip_p) { 1303 case IPPROTO_ICMP: 1304 iresult = IcmpAliasOut(la, pip, create); 1305 break; 1306 case IPPROTO_UDP: 1307 iresult = UdpAliasOut(la, pip, create); 1308 break; 1309 case IPPROTO_TCP: 1310 iresult = TcpAliasOut(la, pip, maxpacketsize, create); 1311 break; 1312 case IPPROTO_GRE: 1313 if (AliasHandlePptpGreOut(la, pip) == 0) 1314 iresult = PKT_ALIAS_OK; 1315 else 1316 iresult = ProtoAliasOut(la, pip, create); 1317 break; 1318 default: 1319 iresult = ProtoAliasOut(la, pip, create); 1320 break; 1321 } 1322 } else { 1323 iresult = FragmentOut(la, pip); 1324 } 1325 1326 SetDefaultAliasAddress(la, addr_save); 1327 return (iresult); 1328 } 1329 1330 int 1331 LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */ 1332 int maxpacketsize /* for error checking */ 1333 ) 1334 { 1335 struct ip *pip; 1336 struct icmp *ic; 1337 struct udphdr *ud; 1338 struct tcphdr *tc; 1339 struct alias_link *lnk; 1340 int iresult = PKT_ALIAS_IGNORED; 1341 1342 pip = (struct ip *)ptr; 1343 1344 /* Defense against mangled packets */ 1345 if (ntohs(pip->ip_len) > maxpacketsize 1346 || (pip->ip_hl << 2) > maxpacketsize) 1347 return (iresult); 1348 1349 ud = (struct udphdr *)ip_next(pip); 1350 tc = (struct tcphdr *)ip_next(pip); 1351 ic = (struct icmp *)ip_next(pip); 1352 1353 /* Find a link */ 1354 if (pip->ip_p == IPPROTO_UDP) 1355 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1356 ud->uh_dport, ud->uh_sport, 1357 IPPROTO_UDP, 0); 1358 else if (pip->ip_p == IPPROTO_TCP) 1359 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, 1360 tc->th_dport, tc->th_sport, 1361 IPPROTO_TCP, 0); 1362 else if (pip->ip_p == IPPROTO_ICMP) 1363 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0); 1364 else 1365 lnk = NULL; 1366 1367 /* Change it from an aliased packet to an unaliased packet */ 1368 if (lnk != NULL) { 1369 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) { 1370 int accumulate; 1371 struct in_addr original_address; 1372 u_short original_port; 1373 1374 original_address = GetOriginalAddress(lnk); 1375 original_port = GetOriginalPort(lnk); 1376 1377 /* Adjust TCP/UDP checksum */ 1378 accumulate = twowords(&pip->ip_src); 1379 accumulate -= twowords(&original_address); 1380 1381 if (pip->ip_p == IPPROTO_UDP) { 1382 accumulate += ud->uh_sport; 1383 accumulate -= original_port; 1384 ADJUST_CHECKSUM(accumulate, ud->uh_sum); 1385 } else { 1386 accumulate += tc->th_sport; 1387 accumulate -= original_port; 1388 ADJUST_CHECKSUM(accumulate, tc->th_sum); 1389 } 1390 1391 /* Adjust IP checksum */ 1392 DifferentialChecksum(&pip->ip_sum, 1393 &original_address, &pip->ip_src, 2); 1394 1395 /* Un-alias source address and port number */ 1396 pip->ip_src = original_address; 1397 if (pip->ip_p == IPPROTO_UDP) 1398 ud->uh_sport = original_port; 1399 else 1400 tc->th_sport = original_port; 1401 1402 iresult = PKT_ALIAS_OK; 1403 1404 } else if (pip->ip_p == IPPROTO_ICMP) { 1405 1406 int accumulate; 1407 struct in_addr original_address; 1408 u_short original_id; 1409 1410 original_address = GetOriginalAddress(lnk); 1411 original_id = GetOriginalPort(lnk); 1412 1413 /* Adjust ICMP checksum */ 1414 accumulate = twowords(&pip->ip_src); 1415 accumulate -= twowords(&original_address); 1416 accumulate += ic->icmp_id; 1417 accumulate -= original_id; 1418 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); 1419 1420 /* Adjust IP checksum */ 1421 DifferentialChecksum(&pip->ip_sum, 1422 &original_address, &pip->ip_src, 2); 1423 1424 /* Un-alias source address and port number */ 1425 pip->ip_src = original_address; 1426 ic->icmp_id = original_id; 1427 1428 iresult = PKT_ALIAS_OK; 1429 } 1430 } 1431 return (iresult); 1432 1433 } 1434