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