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_db.c encapsulates all data structures used for storing 32 packet aliasing data. Other parts of the aliasing software 33 access data through functions provided in this file. 34 35 Data storage is based on the notion of a "link", which is 36 established for ICMP echo/reply packets, UDP datagrams and 37 TCP stream connections. A link stores the original source 38 and destination addresses. For UDP and TCP, it also stores 39 source and destination port numbers, as well as an alias 40 port number. Links are also used to store information about 41 fragments. 42 43 There is a facility for sweeping through and deleting old 44 links as new packets are sent through. A simple timeout is 45 used for ICMP and UDP links. TCP links are left alone unless 46 there is an incomplete connection, in which case the link 47 can be deleted after a certain amount of time. 48 49 50 Initial version: August, 1996 (cjm) 51 52 Version 1.4: September 16, 1996 (cjm) 53 Facility for handling incoming links added. 54 55 Version 1.6: September 18, 1996 (cjm) 56 ICMP data handling simplified. 57 58 Version 1.7: January 9, 1997 (cjm) 59 Fragment handling simplified. 60 Saves pointers for unresolved fragments. 61 Permits links for unspecified remote ports 62 or unspecified remote addresses. 63 Fixed bug which did not properly zero port 64 table entries after a link was deleted. 65 Cleaned up some obsolete comments. 66 67 Version 1.8: January 14, 1997 (cjm) 68 Fixed data type error in StartPoint(). 69 (This error did not exist prior to v1.7 70 and was discovered and fixed by Ari Suutari) 71 72 Version 1.9: February 1, 1997 73 Optionally, connections initiated from packet aliasing host 74 machine will will not have their port number aliased unless it 75 conflicts with an aliasing port already being used. (cjm) 76 77 All options earlier being #ifdef'ed are now available through 78 a new interface, SetPacketAliasMode(). This allows run time 79 control (which is now available in PPP+pktAlias through the 80 'alias' keyword). (ee) 81 82 Added ability to create an alias port without 83 either destination address or port specified. 84 port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee) 85 86 Removed K&R style function headers 87 and general cleanup. (ee) 88 89 Added packetAliasMode to replace compiler #defines's (ee) 90 91 Allocates sockets for partially specified 92 ports if ALIAS_USE_SOCKETS defined. (cjm) 93 94 Version 2.0: March, 1997 95 SetAliasAddress() will now clean up alias links 96 if the aliasing address is changed. (cjm) 97 98 PacketAliasPermanentLink() function added to support permanent 99 links. (J. Fortes suggested the need for this.) 100 Examples: 101 102 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port 103 104 (192.168.0.2, port 21) <-> alias port 3604, known dest addr 105 unknown dest port 106 107 These permanent links allow for incoming connections to 108 machines on the local network. They can be given with a 109 user-chosen amount of specificity, with increasing specificity 110 meaning more security. (cjm) 111 112 Quite a bit of rework to the basic engine. The portTable[] 113 array, which kept track of which ports were in use was replaced 114 by a table/linked list structure. (cjm) 115 116 SetExpire() function added. (cjm) 117 118 DeleteLink() no longer frees memory association with a pointer 119 to a fragment (this bug was first recognized by E. Eklund in 120 v1.9). 121 122 Version 2.1: May, 1997 (cjm) 123 Packet aliasing engine reworked so that it can handle 124 multiple external addresses rather than just a single 125 host address. 126 127 PacketAliasRedirectPort() and PacketAliasRedirectAddr() 128 added to the API. The first function is a more generalized 129 version of PacketAliasPermanentLink(). The second function 130 implements static network address translation. 131 132 Version 3.2: July, 2000 (salander and satoh) 133 Added FindNewPortGroup to get contiguous range of port values. 134 135 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing 136 link but not actually add one. 137 138 Added FindRtspOut, which is closely derived from FindUdpTcpOut, 139 except that the alias port (from FindNewPortGroup) is provided 140 as input. 141 142 See HISTORY file for additional revisions. 143 */ 144 145 #ifdef _KERNEL 146 #include <machine/stdarg.h> 147 #include <sys/param.h> 148 #include <sys/kernel.h> 149 #include <sys/module.h> 150 #include <sys/syslog.h> 151 #else 152 #include <stdarg.h> 153 #include <stdlib.h> 154 #include <stdio.h> 155 #include <sys/errno.h> 156 #include <sys/time.h> 157 #include <unistd.h> 158 #endif 159 160 #include <sys/socket.h> 161 #include <netinet/tcp.h> 162 163 #ifdef _KERNEL 164 #include <netinet/libalias/alias.h> 165 #include <netinet/libalias/alias_local.h> 166 #include <netinet/libalias/alias_mod.h> 167 #include <net/if.h> 168 #else 169 #include "alias.h" 170 #include "alias_local.h" 171 #include "alias_mod.h" 172 #endif 173 174 static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead); 175 176 177 /* 178 Constants (note: constants are also defined 179 near relevant functions or structs) 180 */ 181 182 /* Parameters used for cleanup of expired links */ 183 /* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */ 184 #define ALIAS_CLEANUP_INTERVAL_SECS 64 185 #define ALIAS_CLEANUP_MAX_SPOKES (LINK_TABLE_OUT_SIZE/5) 186 187 /* Timeouts (in seconds) for different link types */ 188 #define ICMP_EXPIRE_TIME 60 189 #define UDP_EXPIRE_TIME 60 190 #define PROTO_EXPIRE_TIME 60 191 #define FRAGMENT_ID_EXPIRE_TIME 10 192 #define FRAGMENT_PTR_EXPIRE_TIME 30 193 194 /* TCP link expire time for different cases */ 195 /* When the link has been used and closed - minimal grace time to 196 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */ 197 #ifndef TCP_EXPIRE_DEAD 198 #define TCP_EXPIRE_DEAD 10 199 #endif 200 201 /* When the link has been used and closed on one side - the other side 202 is allowed to still send data */ 203 #ifndef TCP_EXPIRE_SINGLEDEAD 204 #define TCP_EXPIRE_SINGLEDEAD 90 205 #endif 206 207 /* When the link isn't yet up */ 208 #ifndef TCP_EXPIRE_INITIAL 209 #define TCP_EXPIRE_INITIAL 300 210 #endif 211 212 /* When the link is up */ 213 #ifndef TCP_EXPIRE_CONNECTED 214 #define TCP_EXPIRE_CONNECTED 86400 215 #endif 216 217 218 /* Dummy port number codes used for FindLinkIn/Out() and AddLink(). 219 These constants can be anything except zero, which indicates an 220 unknown port number. */ 221 222 #define NO_DEST_PORT 1 223 #define NO_SRC_PORT 1 224 225 226 227 /* Data Structures 228 229 The fundamental data structure used in this program is 230 "struct alias_link". Whenever a TCP connection is made, 231 a UDP datagram is sent out, or an ICMP echo request is made, 232 a link record is made (if it has not already been created). 233 The link record is identified by the source address/port 234 and the destination address/port. In the case of an ICMP 235 echo request, the source port is treated as being equivalent 236 with the 16-bit ID number of the ICMP packet. 237 238 The link record also can store some auxiliary data. For 239 TCP connections that have had sequence and acknowledgment 240 modifications, data space is available to track these changes. 241 A state field is used to keep track in changes to the TCP 242 connection state. ID numbers of fragments can also be 243 stored in the auxiliary space. Pointers to unresolved 244 fragments can also be stored. 245 246 The link records support two independent chainings. Lookup 247 tables for input and out tables hold the initial pointers 248 the link chains. On input, the lookup table indexes on alias 249 port and link type. On output, the lookup table indexes on 250 source address, destination address, source port, destination 251 port and link type. 252 */ 253 254 struct ack_data_record { /* used to save changes to ACK/sequence 255 * numbers */ 256 u_long ack_old; 257 u_long ack_new; 258 int delta; 259 int active; 260 }; 261 262 struct tcp_state { /* Information about TCP connection */ 263 int in; /* State for outside -> inside */ 264 int out; /* State for inside -> outside */ 265 int index; /* Index to ACK data array */ 266 int ack_modified; /* Indicates whether ACK and 267 * sequence numbers */ 268 /* been modified */ 269 }; 270 271 #define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes 272 * saved for a modified TCP stream */ 273 struct tcp_dat { 274 struct tcp_state state; 275 struct ack_data_record ack[N_LINK_TCP_DATA]; 276 int fwhole; /* Which firewall record is used for this 277 * hole? */ 278 }; 279 280 struct server { /* LSNAT server pool (circular list) */ 281 struct in_addr addr; 282 u_short port; 283 struct server *next; 284 }; 285 286 struct alias_link { /* Main data structure */ 287 struct libalias *la; 288 struct in_addr src_addr; /* Address and port information */ 289 struct in_addr dst_addr; 290 struct in_addr alias_addr; 291 struct in_addr proxy_addr; 292 u_short src_port; 293 u_short dst_port; 294 u_short alias_port; 295 u_short proxy_port; 296 struct server *server; 297 298 int link_type; /* Type of link: TCP, UDP, ICMP, 299 * proto, frag */ 300 301 /* values for link_type */ 302 #define LINK_ICMP IPPROTO_ICMP 303 #define LINK_UDP IPPROTO_UDP 304 #define LINK_TCP IPPROTO_TCP 305 #define LINK_FRAGMENT_ID (IPPROTO_MAX + 1) 306 #define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2) 307 #define LINK_ADDR (IPPROTO_MAX + 3) 308 #define LINK_PPTP (IPPROTO_MAX + 4) 309 310 int flags; /* indicates special characteristics */ 311 int pflags; /* protocol-specific flags */ 312 313 /* flag bits */ 314 #define LINK_UNKNOWN_DEST_PORT 0x01 315 #define LINK_UNKNOWN_DEST_ADDR 0x02 316 #define LINK_PERMANENT 0x04 317 #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */ 318 #define LINK_UNFIREWALLED 0x08 319 320 int timestamp; /* Time link was last accessed */ 321 int expire_time; /* Expire time for link */ 322 #ifndef NO_USE_SOCKETS 323 int sockfd; /* socket descriptor */ 324 #endif 325 LIST_ENTRY (alias_link) list_out; /* Linked list of 326 * pointers for */ 327 LIST_ENTRY (alias_link) list_in; /* input and output 328 * lookup tables */ 329 330 union { /* Auxiliary data */ 331 char *frag_ptr; 332 struct in_addr frag_addr; 333 struct tcp_dat *tcp; 334 } data; 335 }; 336 337 /* Clean up procedure. */ 338 static void finishoff(void); 339 340 /* Kernel module definition. */ 341 #ifdef _KERNEL 342 MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing"); 343 344 MODULE_VERSION(libalias, 1); 345 346 static int 347 alias_mod_handler(module_t mod, int type, void *data) 348 { 349 int error; 350 351 switch (type) { 352 case MOD_LOAD: 353 error = 0; 354 handler_chain_init(); 355 break; 356 case MOD_QUIESCE: 357 case MOD_UNLOAD: 358 handler_chain_destroy(); 359 finishoff(); 360 error = 0; 361 break; 362 default: 363 error = EINVAL; 364 } 365 366 return (error); 367 } 368 369 static moduledata_t alias_mod = { 370 "alias", alias_mod_handler, NULL 371 }; 372 373 DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 374 #endif 375 376 /* Internal utility routines (used only in alias_db.c) 377 378 Lookup table starting points: 379 StartPointIn() -- link table initial search point for 380 incoming packets 381 StartPointOut() -- link table initial search point for 382 outgoing packets 383 384 Miscellaneous: 385 SeqDiff() -- difference between two TCP sequences 386 ShowAliasStats() -- send alias statistics to a monitor file 387 */ 388 389 390 /* Local prototypes */ 391 static u_int StartPointIn(struct in_addr, u_short, int); 392 393 static u_int 394 StartPointOut(struct in_addr, struct in_addr, 395 u_short, u_short, int); 396 397 static int SeqDiff(u_long, u_long); 398 399 #ifndef NO_FW_PUNCH 400 /* Firewall control */ 401 static void InitPunchFW(struct libalias *); 402 static void UninitPunchFW(struct libalias *); 403 static void ClearFWHole(struct alias_link *); 404 405 #endif 406 407 /* Log file control */ 408 static void ShowAliasStats(struct libalias *); 409 static int InitPacketAliasLog(struct libalias *); 410 static void UninitPacketAliasLog(struct libalias *); 411 412 static u_int 413 StartPointIn(struct in_addr alias_addr, 414 u_short alias_port, 415 int link_type) 416 { 417 u_int n; 418 419 n = alias_addr.s_addr; 420 if (link_type != LINK_PPTP) 421 n += alias_port; 422 n += link_type; 423 return (n % LINK_TABLE_IN_SIZE); 424 } 425 426 427 static u_int 428 StartPointOut(struct in_addr src_addr, struct in_addr dst_addr, 429 u_short src_port, u_short dst_port, int link_type) 430 { 431 u_int n; 432 433 n = src_addr.s_addr; 434 n += dst_addr.s_addr; 435 if (link_type != LINK_PPTP) { 436 n += src_port; 437 n += dst_port; 438 } 439 n += link_type; 440 441 return (n % LINK_TABLE_OUT_SIZE); 442 } 443 444 445 static int 446 SeqDiff(u_long x, u_long y) 447 { 448 /* Return the difference between two TCP sequence numbers */ 449 450 /* 451 This function is encapsulated in case there are any unusual 452 arithmetic conditions that need to be considered. 453 */ 454 455 return (ntohl(y) - ntohl(x)); 456 } 457 458 #ifdef _KERNEL 459 460 static void 461 AliasLog(char *str, const char *format, ...) 462 { 463 va_list ap; 464 465 va_start(ap, format); 466 vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap); 467 va_end(ap); 468 } 469 #else 470 static void 471 AliasLog(FILE *stream, const char *format, ...) 472 { 473 va_list ap; 474 475 va_start(ap, format); 476 vfprintf(stream, format, ap); 477 va_end(ap); 478 fflush(stream); 479 } 480 #endif 481 482 static void 483 ShowAliasStats(struct libalias *la) 484 { 485 486 LIBALIAS_LOCK_ASSERT(la); 487 /* Used for debugging */ 488 if (la->logDesc) { 489 int tot = la->icmpLinkCount + la->udpLinkCount + 490 la->tcpLinkCount + la->pptpLinkCount + 491 la->protoLinkCount + la->fragmentIdLinkCount + 492 la->fragmentPtrLinkCount; 493 494 AliasLog(la->logDesc, 495 "icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u", 496 la->icmpLinkCount, 497 la->udpLinkCount, 498 la->tcpLinkCount, 499 la->pptpLinkCount, 500 la->protoLinkCount, 501 la->fragmentIdLinkCount, 502 la->fragmentPtrLinkCount, tot); 503 #ifndef _KERNEL 504 AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount); 505 #endif 506 } 507 } 508 509 /* Internal routines for finding, deleting and adding links 510 511 Port Allocation: 512 GetNewPort() -- find and reserve new alias port number 513 GetSocket() -- try to allocate a socket for a given port 514 515 Link creation and deletion: 516 CleanupAliasData() - remove all link chains from lookup table 517 IncrementalCleanup() - look for stale links in a single chain 518 DeleteLink() - remove link 519 AddLink() - add link 520 ReLink() - change link 521 522 Link search: 523 FindLinkOut() - find link for outgoing packets 524 FindLinkIn() - find link for incoming packets 525 526 Port search: 527 FindNewPortGroup() - find an available group of ports 528 */ 529 530 /* Local prototypes */ 531 static int GetNewPort(struct libalias *, struct alias_link *, int); 532 #ifndef NO_USE_SOCKETS 533 static u_short GetSocket(struct libalias *, u_short, int *, int); 534 #endif 535 static void CleanupAliasData(struct libalias *); 536 537 static void IncrementalCleanup(struct libalias *); 538 539 static void DeleteLink(struct alias_link *); 540 541 static struct alias_link * 542 AddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr, 543 u_short, u_short, int, int); 544 545 static struct alias_link * 546 ReLink(struct alias_link *, 547 struct in_addr, struct in_addr, struct in_addr, 548 u_short, u_short, int, int); 549 550 static struct alias_link * 551 FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); 552 553 static struct alias_link * 554 FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); 555 556 557 #define ALIAS_PORT_BASE 0x08000 558 #define ALIAS_PORT_MASK 0x07fff 559 #define ALIAS_PORT_MASK_EVEN 0x07ffe 560 #define GET_NEW_PORT_MAX_ATTEMPTS 20 561 562 #define GET_ALIAS_PORT -1 563 #define GET_ALIAS_ID GET_ALIAS_PORT 564 565 #define FIND_EVEN_ALIAS_BASE 1 566 567 /* GetNewPort() allocates port numbers. Note that if a port number 568 is already in use, that does not mean that it cannot be used by 569 another link concurrently. This is because GetNewPort() looks for 570 unused triplets: (dest addr, dest port, alias port). */ 571 572 static int 573 GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param) 574 { 575 int i; 576 int max_trials; 577 u_short port_sys; 578 u_short port_net; 579 580 LIBALIAS_LOCK_ASSERT(la); 581 /* 582 Description of alias_port_param for GetNewPort(). When 583 this parameter is zero or positive, it precisely specifies 584 the port number. GetNewPort() will return this number 585 without check that it is in use. 586 587 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly 588 selected port number. 589 */ 590 591 if (alias_port_param == GET_ALIAS_PORT) { 592 /* 593 * The aliasing port is automatically selected by one of 594 * two methods below: 595 */ 596 max_trials = GET_NEW_PORT_MAX_ATTEMPTS; 597 598 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) { 599 /* 600 * When the PKT_ALIAS_SAME_PORTS option is chosen, 601 * the first try will be the actual source port. If 602 * this is already in use, the remainder of the 603 * trials will be random. 604 */ 605 port_net = lnk->src_port; 606 port_sys = ntohs(port_net); 607 } else { 608 /* First trial and all subsequent are random. */ 609 port_sys = random() & ALIAS_PORT_MASK; 610 port_sys += ALIAS_PORT_BASE; 611 port_net = htons(port_sys); 612 } 613 } else if (alias_port_param >= 0 && alias_port_param < 0x10000) { 614 lnk->alias_port = (u_short) alias_port_param; 615 return (0); 616 } else { 617 #ifdef LIBALIAS_DEBUG 618 fprintf(stderr, "PacketAlias/GetNewPort(): "); 619 fprintf(stderr, "input parameter error\n"); 620 #endif 621 return (-1); 622 } 623 624 625 /* Port number search */ 626 for (i = 0; i < max_trials; i++) { 627 int go_ahead; 628 struct alias_link *search_result; 629 630 search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr, 631 lnk->dst_port, port_net, 632 lnk->link_type, 0); 633 634 if (search_result == NULL) 635 go_ahead = 1; 636 else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED) 637 && (search_result->flags & LINK_PARTIALLY_SPECIFIED)) 638 go_ahead = 1; 639 else 640 go_ahead = 0; 641 642 if (go_ahead) { 643 #ifndef NO_USE_SOCKETS 644 if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS) 645 && (lnk->flags & LINK_PARTIALLY_SPECIFIED) 646 && ((lnk->link_type == LINK_TCP) || 647 (lnk->link_type == LINK_UDP))) { 648 if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) { 649 lnk->alias_port = port_net; 650 return (0); 651 } 652 } else { 653 #endif 654 lnk->alias_port = port_net; 655 return (0); 656 #ifndef NO_USE_SOCKETS 657 } 658 #endif 659 } 660 port_sys = random() & ALIAS_PORT_MASK; 661 port_sys += ALIAS_PORT_BASE; 662 port_net = htons(port_sys); 663 } 664 665 #ifdef LIBALIAS_DEBUG 666 fprintf(stderr, "PacketAlias/GetnewPort(): "); 667 fprintf(stderr, "could not find free port\n"); 668 #endif 669 670 return (-1); 671 } 672 673 #ifndef NO_USE_SOCKETS 674 static u_short 675 GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type) 676 { 677 int err; 678 int sock; 679 struct sockaddr_in sock_addr; 680 681 LIBALIAS_LOCK_ASSERT(la); 682 if (link_type == LINK_TCP) 683 sock = socket(AF_INET, SOCK_STREAM, 0); 684 else if (link_type == LINK_UDP) 685 sock = socket(AF_INET, SOCK_DGRAM, 0); 686 else { 687 #ifdef LIBALIAS_DEBUG 688 fprintf(stderr, "PacketAlias/GetSocket(): "); 689 fprintf(stderr, "incorrect link type\n"); 690 #endif 691 return (0); 692 } 693 694 if (sock < 0) { 695 #ifdef LIBALIAS_DEBUG 696 fprintf(stderr, "PacketAlias/GetSocket(): "); 697 fprintf(stderr, "socket() error %d\n", *sockfd); 698 #endif 699 return (0); 700 } 701 sock_addr.sin_family = AF_INET; 702 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); 703 sock_addr.sin_port = port_net; 704 705 err = bind(sock, 706 (struct sockaddr *)&sock_addr, 707 sizeof(sock_addr)); 708 if (err == 0) { 709 la->sockCount++; 710 *sockfd = sock; 711 return (1); 712 } else { 713 close(sock); 714 return (0); 715 } 716 } 717 #endif 718 719 /* FindNewPortGroup() returns a base port number for an available 720 range of contiguous port numbers. Note that if a port number 721 is already in use, that does not mean that it cannot be used by 722 another link concurrently. This is because FindNewPortGroup() 723 looks for unused triplets: (dest addr, dest port, alias port). */ 724 725 int 726 FindNewPortGroup(struct libalias *la, 727 struct in_addr dst_addr, 728 struct in_addr alias_addr, 729 u_short src_port, 730 u_short dst_port, 731 u_short port_count, 732 u_char proto, 733 u_char align) 734 { 735 int i, j; 736 int max_trials; 737 u_short port_sys; 738 int link_type; 739 740 LIBALIAS_LOCK_ASSERT(la); 741 /* 742 * Get link_type from protocol 743 */ 744 745 switch (proto) { 746 case IPPROTO_UDP: 747 link_type = LINK_UDP; 748 break; 749 case IPPROTO_TCP: 750 link_type = LINK_TCP; 751 break; 752 default: 753 return (0); 754 break; 755 } 756 757 /* 758 * The aliasing port is automatically selected by one of two 759 * methods below: 760 */ 761 max_trials = GET_NEW_PORT_MAX_ATTEMPTS; 762 763 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) { 764 /* 765 * When the ALIAS_SAME_PORTS option is chosen, the first 766 * try will be the actual source port. If this is already 767 * in use, the remainder of the trials will be random. 768 */ 769 port_sys = ntohs(src_port); 770 771 } else { 772 773 /* First trial and all subsequent are random. */ 774 if (align == FIND_EVEN_ALIAS_BASE) 775 port_sys = random() & ALIAS_PORT_MASK_EVEN; 776 else 777 port_sys = random() & ALIAS_PORT_MASK; 778 779 port_sys += ALIAS_PORT_BASE; 780 } 781 782 /* Port number search */ 783 for (i = 0; i < max_trials; i++) { 784 785 struct alias_link *search_result; 786 787 for (j = 0; j < port_count; j++) 788 if (0 != (search_result = FindLinkIn(la, dst_addr, alias_addr, 789 dst_port, htons(port_sys + j), 790 link_type, 0))) 791 break; 792 793 /* Found a good range, return base */ 794 if (j == port_count) 795 return (htons(port_sys)); 796 797 /* Find a new base to try */ 798 if (align == FIND_EVEN_ALIAS_BASE) 799 port_sys = random() & ALIAS_PORT_MASK_EVEN; 800 else 801 port_sys = random() & ALIAS_PORT_MASK; 802 803 port_sys += ALIAS_PORT_BASE; 804 } 805 806 #ifdef LIBALIAS_DEBUG 807 fprintf(stderr, "PacketAlias/FindNewPortGroup(): "); 808 fprintf(stderr, "could not find free port(s)\n"); 809 #endif 810 811 return (0); 812 } 813 814 static void 815 CleanupAliasData(struct libalias *la) 816 { 817 struct alias_link *lnk; 818 int i; 819 820 LIBALIAS_LOCK_ASSERT(la); 821 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) { 822 while ((lnk = LIST_FIRST(&la->linkTableOut[i])) != NULL) 823 DeleteLink(lnk); 824 } 825 826 la->cleanupIndex = 0; 827 } 828 829 830 static void 831 IncrementalCleanup(struct libalias *la) 832 { 833 struct alias_link *lnk, *lnk_tmp; 834 835 LIBALIAS_LOCK_ASSERT(la); 836 LIST_FOREACH_SAFE(lnk, &la->linkTableOut[la->cleanupIndex++], 837 list_out, lnk_tmp) { 838 if (la->timeStamp - lnk->timestamp > lnk->expire_time) 839 DeleteLink(lnk); 840 } 841 842 if (la->cleanupIndex == LINK_TABLE_OUT_SIZE) 843 la->cleanupIndex = 0; 844 } 845 846 static void 847 DeleteLink(struct alias_link *lnk) 848 { 849 struct libalias *la = lnk->la; 850 851 LIBALIAS_LOCK_ASSERT(la); 852 /* Don't do anything if the link is marked permanent */ 853 if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT) 854 return; 855 856 #ifndef NO_FW_PUNCH 857 /* Delete associated firewall hole, if any */ 858 ClearFWHole(lnk); 859 #endif 860 861 /* Free memory allocated for LSNAT server pool */ 862 if (lnk->server != NULL) { 863 struct server *head, *curr, *next; 864 865 head = curr = lnk->server; 866 do { 867 next = curr->next; 868 free(curr); 869 } while ((curr = next) != head); 870 } 871 /* Adjust output table pointers */ 872 LIST_REMOVE(lnk, list_out); 873 874 /* Adjust input table pointers */ 875 LIST_REMOVE(lnk, list_in); 876 #ifndef NO_USE_SOCKETS 877 /* Close socket, if one has been allocated */ 878 if (lnk->sockfd != -1) { 879 la->sockCount--; 880 close(lnk->sockfd); 881 } 882 #endif 883 /* Link-type dependent cleanup */ 884 switch (lnk->link_type) { 885 case LINK_ICMP: 886 la->icmpLinkCount--; 887 break; 888 case LINK_UDP: 889 la->udpLinkCount--; 890 break; 891 case LINK_TCP: 892 la->tcpLinkCount--; 893 free(lnk->data.tcp); 894 break; 895 case LINK_PPTP: 896 la->pptpLinkCount--; 897 break; 898 case LINK_FRAGMENT_ID: 899 la->fragmentIdLinkCount--; 900 break; 901 case LINK_FRAGMENT_PTR: 902 la->fragmentPtrLinkCount--; 903 if (lnk->data.frag_ptr != NULL) 904 free(lnk->data.frag_ptr); 905 break; 906 case LINK_ADDR: 907 break; 908 default: 909 la->protoLinkCount--; 910 break; 911 } 912 913 /* Free memory */ 914 free(lnk); 915 916 /* Write statistics, if logging enabled */ 917 if (la->packetAliasMode & PKT_ALIAS_LOG) { 918 ShowAliasStats(la); 919 } 920 } 921 922 923 static struct alias_link * 924 AddLink(struct libalias *la, struct in_addr src_addr, 925 struct in_addr dst_addr, 926 struct in_addr alias_addr, 927 u_short src_port, 928 u_short dst_port, 929 int alias_port_param, /* if less than zero, alias */ 930 int link_type) 931 { /* port will be automatically *//* chosen. 932 * If greater than */ 933 u_int start_point; /* zero, equal to alias port */ 934 struct alias_link *lnk; 935 936 LIBALIAS_LOCK_ASSERT(la); 937 lnk = malloc(sizeof(struct alias_link)); 938 if (lnk != NULL) { 939 /* Basic initialization */ 940 lnk->la = la; 941 lnk->src_addr = src_addr; 942 lnk->dst_addr = dst_addr; 943 lnk->alias_addr = alias_addr; 944 lnk->proxy_addr.s_addr = INADDR_ANY; 945 lnk->src_port = src_port; 946 lnk->dst_port = dst_port; 947 lnk->proxy_port = 0; 948 lnk->server = NULL; 949 lnk->link_type = link_type; 950 #ifndef NO_USE_SOCKETS 951 lnk->sockfd = -1; 952 #endif 953 lnk->flags = 0; 954 lnk->pflags = 0; 955 lnk->timestamp = la->timeStamp; 956 957 /* Expiration time */ 958 switch (link_type) { 959 case LINK_ICMP: 960 lnk->expire_time = ICMP_EXPIRE_TIME; 961 break; 962 case LINK_UDP: 963 lnk->expire_time = UDP_EXPIRE_TIME; 964 break; 965 case LINK_TCP: 966 lnk->expire_time = TCP_EXPIRE_INITIAL; 967 break; 968 case LINK_PPTP: 969 lnk->flags |= LINK_PERMANENT; /* no timeout. */ 970 break; 971 case LINK_FRAGMENT_ID: 972 lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME; 973 break; 974 case LINK_FRAGMENT_PTR: 975 lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME; 976 break; 977 case LINK_ADDR: 978 break; 979 default: 980 lnk->expire_time = PROTO_EXPIRE_TIME; 981 break; 982 } 983 984 /* Determine alias flags */ 985 if (dst_addr.s_addr == INADDR_ANY) 986 lnk->flags |= LINK_UNKNOWN_DEST_ADDR; 987 if (dst_port == 0) 988 lnk->flags |= LINK_UNKNOWN_DEST_PORT; 989 990 /* Determine alias port */ 991 if (GetNewPort(la, lnk, alias_port_param) != 0) { 992 free(lnk); 993 return (NULL); 994 } 995 /* Link-type dependent initialization */ 996 switch (link_type) { 997 struct tcp_dat *aux_tcp; 998 999 case LINK_ICMP: 1000 la->icmpLinkCount++; 1001 break; 1002 case LINK_UDP: 1003 la->udpLinkCount++; 1004 break; 1005 case LINK_TCP: 1006 aux_tcp = malloc(sizeof(struct tcp_dat)); 1007 if (aux_tcp != NULL) { 1008 int i; 1009 1010 la->tcpLinkCount++; 1011 aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED; 1012 aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED; 1013 aux_tcp->state.index = 0; 1014 aux_tcp->state.ack_modified = 0; 1015 for (i = 0; i < N_LINK_TCP_DATA; i++) 1016 aux_tcp->ack[i].active = 0; 1017 aux_tcp->fwhole = -1; 1018 lnk->data.tcp = aux_tcp; 1019 } else { 1020 #ifdef LIBALIAS_DEBUG 1021 fprintf(stderr, "PacketAlias/AddLink: "); 1022 fprintf(stderr, " cannot allocate auxiliary TCP data\n"); 1023 #endif 1024 free(lnk); 1025 return (NULL); 1026 } 1027 break; 1028 case LINK_PPTP: 1029 la->pptpLinkCount++; 1030 break; 1031 case LINK_FRAGMENT_ID: 1032 la->fragmentIdLinkCount++; 1033 break; 1034 case LINK_FRAGMENT_PTR: 1035 la->fragmentPtrLinkCount++; 1036 break; 1037 case LINK_ADDR: 1038 break; 1039 default: 1040 la->protoLinkCount++; 1041 break; 1042 } 1043 1044 /* Set up pointers for output lookup table */ 1045 start_point = StartPointOut(src_addr, dst_addr, 1046 src_port, dst_port, link_type); 1047 LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out); 1048 1049 /* Set up pointers for input lookup table */ 1050 start_point = StartPointIn(alias_addr, lnk->alias_port, link_type); 1051 LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in); 1052 } else { 1053 #ifdef LIBALIAS_DEBUG 1054 fprintf(stderr, "PacketAlias/AddLink(): "); 1055 fprintf(stderr, "malloc() call failed.\n"); 1056 #endif 1057 } 1058 if (la->packetAliasMode & PKT_ALIAS_LOG) { 1059 ShowAliasStats(la); 1060 } 1061 return (lnk); 1062 } 1063 1064 static struct alias_link * 1065 ReLink(struct alias_link *old_lnk, 1066 struct in_addr src_addr, 1067 struct in_addr dst_addr, 1068 struct in_addr alias_addr, 1069 u_short src_port, 1070 u_short dst_port, 1071 int alias_port_param, /* if less than zero, alias */ 1072 int link_type) 1073 { /* port will be automatically *//* chosen. 1074 * If greater than */ 1075 struct alias_link *new_lnk; /* zero, equal to alias port */ 1076 struct libalias *la = old_lnk->la; 1077 1078 LIBALIAS_LOCK_ASSERT(la); 1079 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1080 src_port, dst_port, alias_port_param, 1081 link_type); 1082 #ifndef NO_FW_PUNCH 1083 if (new_lnk != NULL && 1084 old_lnk->link_type == LINK_TCP && 1085 old_lnk->data.tcp->fwhole > 0) { 1086 PunchFWHole(new_lnk); 1087 } 1088 #endif 1089 DeleteLink(old_lnk); 1090 return (new_lnk); 1091 } 1092 1093 static struct alias_link * 1094 _FindLinkOut(struct libalias *la, struct in_addr src_addr, 1095 struct in_addr dst_addr, 1096 u_short src_port, 1097 u_short dst_port, 1098 int link_type, 1099 int replace_partial_links) 1100 { 1101 u_int i; 1102 struct alias_link *lnk; 1103 1104 LIBALIAS_LOCK_ASSERT(la); 1105 i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type); 1106 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) { 1107 if (lnk->dst_addr.s_addr == dst_addr.s_addr && 1108 lnk->src_addr.s_addr == src_addr.s_addr && 1109 lnk->src_port == src_port && 1110 lnk->dst_port == dst_port && 1111 lnk->link_type == link_type && 1112 lnk->server == NULL) { 1113 lnk->timestamp = la->timeStamp; 1114 break; 1115 } 1116 } 1117 1118 /* Search for partially specified links. */ 1119 if (lnk == NULL && replace_partial_links) { 1120 if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) { 1121 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0, 1122 link_type, 0); 1123 if (lnk == NULL) 1124 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 1125 dst_port, link_type, 0); 1126 } 1127 if (lnk == NULL && 1128 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) { 1129 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0, 1130 link_type, 0); 1131 } 1132 if (lnk != NULL) { 1133 lnk = ReLink(lnk, 1134 src_addr, dst_addr, lnk->alias_addr, 1135 src_port, dst_port, lnk->alias_port, 1136 link_type); 1137 } 1138 } 1139 return (lnk); 1140 } 1141 1142 static struct alias_link * 1143 FindLinkOut(struct libalias *la, struct in_addr src_addr, 1144 struct in_addr dst_addr, 1145 u_short src_port, 1146 u_short dst_port, 1147 int link_type, 1148 int replace_partial_links) 1149 { 1150 struct alias_link *lnk; 1151 1152 LIBALIAS_LOCK_ASSERT(la); 1153 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, 1154 link_type, replace_partial_links); 1155 1156 if (lnk == NULL) { 1157 /* 1158 * The following allows permanent links to be specified as 1159 * using the default source address (i.e. device interface 1160 * address) without knowing in advance what that address 1161 * is. 1162 */ 1163 if (la->aliasAddress.s_addr != INADDR_ANY && 1164 src_addr.s_addr == la->aliasAddress.s_addr) { 1165 lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port, 1166 link_type, replace_partial_links); 1167 } 1168 } 1169 return (lnk); 1170 } 1171 1172 1173 static struct alias_link * 1174 _FindLinkIn(struct libalias *la, struct in_addr dst_addr, 1175 struct in_addr alias_addr, 1176 u_short dst_port, 1177 u_short alias_port, 1178 int link_type, 1179 int replace_partial_links) 1180 { 1181 int flags_in; 1182 u_int start_point; 1183 struct alias_link *lnk; 1184 struct alias_link *lnk_fully_specified; 1185 struct alias_link *lnk_unknown_all; 1186 struct alias_link *lnk_unknown_dst_addr; 1187 struct alias_link *lnk_unknown_dst_port; 1188 1189 LIBALIAS_LOCK_ASSERT(la); 1190 /* Initialize pointers */ 1191 lnk_fully_specified = NULL; 1192 lnk_unknown_all = NULL; 1193 lnk_unknown_dst_addr = NULL; 1194 lnk_unknown_dst_port = NULL; 1195 1196 /* If either the dest addr or port is unknown, the search 1197 loop will have to know about this. */ 1198 1199 flags_in = 0; 1200 if (dst_addr.s_addr == INADDR_ANY) 1201 flags_in |= LINK_UNKNOWN_DEST_ADDR; 1202 if (dst_port == 0) 1203 flags_in |= LINK_UNKNOWN_DEST_PORT; 1204 1205 /* Search loop */ 1206 start_point = StartPointIn(alias_addr, alias_port, link_type); 1207 LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) { 1208 int flags; 1209 1210 flags = flags_in | lnk->flags; 1211 if (!(flags & LINK_PARTIALLY_SPECIFIED)) { 1212 if (lnk->alias_addr.s_addr == alias_addr.s_addr 1213 && lnk->alias_port == alias_port 1214 && lnk->dst_addr.s_addr == dst_addr.s_addr 1215 && lnk->dst_port == dst_port 1216 && lnk->link_type == link_type) { 1217 lnk_fully_specified = lnk; 1218 break; 1219 } 1220 } else if ((flags & LINK_UNKNOWN_DEST_ADDR) 1221 && (flags & LINK_UNKNOWN_DEST_PORT)) { 1222 if (lnk->alias_addr.s_addr == alias_addr.s_addr 1223 && lnk->alias_port == alias_port 1224 && lnk->link_type == link_type) { 1225 if (lnk_unknown_all == NULL) 1226 lnk_unknown_all = lnk; 1227 } 1228 } else if (flags & LINK_UNKNOWN_DEST_ADDR) { 1229 if (lnk->alias_addr.s_addr == alias_addr.s_addr 1230 && lnk->alias_port == alias_port 1231 && lnk->link_type == link_type 1232 && lnk->dst_port == dst_port) { 1233 if (lnk_unknown_dst_addr == NULL) 1234 lnk_unknown_dst_addr = lnk; 1235 } 1236 } else if (flags & LINK_UNKNOWN_DEST_PORT) { 1237 if (lnk->alias_addr.s_addr == alias_addr.s_addr 1238 && lnk->alias_port == alias_port 1239 && lnk->link_type == link_type 1240 && lnk->dst_addr.s_addr == dst_addr.s_addr) { 1241 if (lnk_unknown_dst_port == NULL) 1242 lnk_unknown_dst_port = lnk; 1243 } 1244 } 1245 } 1246 1247 1248 1249 if (lnk_fully_specified != NULL) { 1250 lnk_fully_specified->timestamp = la->timeStamp; 1251 lnk = lnk_fully_specified; 1252 } else if (lnk_unknown_dst_port != NULL) 1253 lnk = lnk_unknown_dst_port; 1254 else if (lnk_unknown_dst_addr != NULL) 1255 lnk = lnk_unknown_dst_addr; 1256 else if (lnk_unknown_all != NULL) 1257 lnk = lnk_unknown_all; 1258 else 1259 return (NULL); 1260 1261 if (replace_partial_links && 1262 (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) { 1263 struct in_addr src_addr; 1264 u_short src_port; 1265 1266 if (lnk->server != NULL) { /* LSNAT link */ 1267 src_addr = lnk->server->addr; 1268 src_port = lnk->server->port; 1269 lnk->server = lnk->server->next; 1270 } else { 1271 src_addr = lnk->src_addr; 1272 src_port = lnk->src_port; 1273 } 1274 1275 lnk = ReLink(lnk, 1276 src_addr, dst_addr, alias_addr, 1277 src_port, dst_port, alias_port, 1278 link_type); 1279 } 1280 return (lnk); 1281 } 1282 1283 static struct alias_link * 1284 FindLinkIn(struct libalias *la, struct in_addr dst_addr, 1285 struct in_addr alias_addr, 1286 u_short dst_port, 1287 u_short alias_port, 1288 int link_type, 1289 int replace_partial_links) 1290 { 1291 struct alias_link *lnk; 1292 1293 LIBALIAS_LOCK_ASSERT(la); 1294 lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port, 1295 link_type, replace_partial_links); 1296 1297 if (lnk == NULL) { 1298 /* 1299 * The following allows permanent links to be specified as 1300 * using the default aliasing address (i.e. device 1301 * interface address) without knowing in advance what that 1302 * address is. 1303 */ 1304 if (la->aliasAddress.s_addr != INADDR_ANY && 1305 alias_addr.s_addr == la->aliasAddress.s_addr) { 1306 lnk = _FindLinkIn(la, dst_addr, la->nullAddress, dst_port, alias_port, 1307 link_type, replace_partial_links); 1308 } 1309 } 1310 return (lnk); 1311 } 1312 1313 1314 1315 1316 /* External routines for finding/adding links 1317 1318 -- "external" means outside alias_db.c, but within alias*.c -- 1319 1320 FindIcmpIn(), FindIcmpOut() 1321 FindFragmentIn1(), FindFragmentIn2() 1322 AddFragmentPtrLink(), FindFragmentPtr() 1323 FindProtoIn(), FindProtoOut() 1324 FindUdpTcpIn(), FindUdpTcpOut() 1325 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(), 1326 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId() 1327 FindOriginalAddress(), FindAliasAddress() 1328 1329 (prototypes in alias_local.h) 1330 */ 1331 1332 1333 struct alias_link * 1334 FindIcmpIn(struct libalias *la, struct in_addr dst_addr, 1335 struct in_addr alias_addr, 1336 u_short id_alias, 1337 int create) 1338 { 1339 struct alias_link *lnk; 1340 1341 LIBALIAS_LOCK_ASSERT(la); 1342 lnk = FindLinkIn(la, dst_addr, alias_addr, 1343 NO_DEST_PORT, id_alias, 1344 LINK_ICMP, 0); 1345 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { 1346 struct in_addr target_addr; 1347 1348 target_addr = FindOriginalAddress(la, alias_addr); 1349 lnk = AddLink(la, target_addr, dst_addr, alias_addr, 1350 id_alias, NO_DEST_PORT, id_alias, 1351 LINK_ICMP); 1352 } 1353 return (lnk); 1354 } 1355 1356 1357 struct alias_link * 1358 FindIcmpOut(struct libalias *la, struct in_addr src_addr, 1359 struct in_addr dst_addr, 1360 u_short id, 1361 int create) 1362 { 1363 struct alias_link *lnk; 1364 1365 LIBALIAS_LOCK_ASSERT(la); 1366 lnk = FindLinkOut(la, src_addr, dst_addr, 1367 id, NO_DEST_PORT, 1368 LINK_ICMP, 0); 1369 if (lnk == NULL && create) { 1370 struct in_addr alias_addr; 1371 1372 alias_addr = FindAliasAddress(la, src_addr); 1373 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1374 id, NO_DEST_PORT, GET_ALIAS_ID, 1375 LINK_ICMP); 1376 } 1377 return (lnk); 1378 } 1379 1380 1381 struct alias_link * 1382 FindFragmentIn1(struct libalias *la, struct in_addr dst_addr, 1383 struct in_addr alias_addr, 1384 u_short ip_id) 1385 { 1386 struct alias_link *lnk; 1387 1388 LIBALIAS_LOCK_ASSERT(la); 1389 lnk = FindLinkIn(la, dst_addr, alias_addr, 1390 NO_DEST_PORT, ip_id, 1391 LINK_FRAGMENT_ID, 0); 1392 1393 if (lnk == NULL) { 1394 lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr, 1395 NO_SRC_PORT, NO_DEST_PORT, ip_id, 1396 LINK_FRAGMENT_ID); 1397 } 1398 return (lnk); 1399 } 1400 1401 1402 struct alias_link * 1403 FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if 1404 * one */ 1405 struct in_addr alias_addr, /* is not found. */ 1406 u_short ip_id) 1407 { 1408 1409 LIBALIAS_LOCK_ASSERT(la); 1410 return FindLinkIn(la, dst_addr, alias_addr, 1411 NO_DEST_PORT, ip_id, 1412 LINK_FRAGMENT_ID, 0); 1413 } 1414 1415 1416 struct alias_link * 1417 AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr, 1418 u_short ip_id) 1419 { 1420 1421 LIBALIAS_LOCK_ASSERT(la); 1422 return AddLink(la, la->nullAddress, dst_addr, la->nullAddress, 1423 NO_SRC_PORT, NO_DEST_PORT, ip_id, 1424 LINK_FRAGMENT_PTR); 1425 } 1426 1427 1428 struct alias_link * 1429 FindFragmentPtr(struct libalias *la, struct in_addr dst_addr, 1430 u_short ip_id) 1431 { 1432 1433 LIBALIAS_LOCK_ASSERT(la); 1434 return FindLinkIn(la, dst_addr, la->nullAddress, 1435 NO_DEST_PORT, ip_id, 1436 LINK_FRAGMENT_PTR, 0); 1437 } 1438 1439 1440 struct alias_link * 1441 FindProtoIn(struct libalias *la, struct in_addr dst_addr, 1442 struct in_addr alias_addr, 1443 u_char proto) 1444 { 1445 struct alias_link *lnk; 1446 1447 LIBALIAS_LOCK_ASSERT(la); 1448 lnk = FindLinkIn(la, dst_addr, alias_addr, 1449 NO_DEST_PORT, 0, 1450 proto, 1); 1451 1452 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { 1453 struct in_addr target_addr; 1454 1455 target_addr = FindOriginalAddress(la, alias_addr); 1456 lnk = AddLink(la, target_addr, dst_addr, alias_addr, 1457 NO_SRC_PORT, NO_DEST_PORT, 0, 1458 proto); 1459 } 1460 return (lnk); 1461 } 1462 1463 1464 struct alias_link * 1465 FindProtoOut(struct libalias *la, struct in_addr src_addr, 1466 struct in_addr dst_addr, 1467 u_char proto) 1468 { 1469 struct alias_link *lnk; 1470 1471 LIBALIAS_LOCK_ASSERT(la); 1472 lnk = FindLinkOut(la, src_addr, dst_addr, 1473 NO_SRC_PORT, NO_DEST_PORT, 1474 proto, 1); 1475 1476 if (lnk == NULL) { 1477 struct in_addr alias_addr; 1478 1479 alias_addr = FindAliasAddress(la, src_addr); 1480 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1481 NO_SRC_PORT, NO_DEST_PORT, 0, 1482 proto); 1483 } 1484 return (lnk); 1485 } 1486 1487 1488 struct alias_link * 1489 FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr, 1490 struct in_addr alias_addr, 1491 u_short dst_port, 1492 u_short alias_port, 1493 u_char proto, 1494 int create) 1495 { 1496 int link_type; 1497 struct alias_link *lnk; 1498 1499 LIBALIAS_LOCK_ASSERT(la); 1500 switch (proto) { 1501 case IPPROTO_UDP: 1502 link_type = LINK_UDP; 1503 break; 1504 case IPPROTO_TCP: 1505 link_type = LINK_TCP; 1506 break; 1507 default: 1508 return (NULL); 1509 break; 1510 } 1511 1512 lnk = FindLinkIn(la, dst_addr, alias_addr, 1513 dst_port, alias_port, 1514 link_type, create); 1515 1516 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { 1517 struct in_addr target_addr; 1518 1519 target_addr = FindOriginalAddress(la, alias_addr); 1520 lnk = AddLink(la, target_addr, dst_addr, alias_addr, 1521 alias_port, dst_port, alias_port, 1522 link_type); 1523 } 1524 return (lnk); 1525 } 1526 1527 1528 struct alias_link * 1529 FindUdpTcpOut(struct libalias *la, struct in_addr src_addr, 1530 struct in_addr dst_addr, 1531 u_short src_port, 1532 u_short dst_port, 1533 u_char proto, 1534 int create) 1535 { 1536 int link_type; 1537 struct alias_link *lnk; 1538 1539 LIBALIAS_LOCK_ASSERT(la); 1540 switch (proto) { 1541 case IPPROTO_UDP: 1542 link_type = LINK_UDP; 1543 break; 1544 case IPPROTO_TCP: 1545 link_type = LINK_TCP; 1546 break; 1547 default: 1548 return (NULL); 1549 break; 1550 } 1551 1552 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create); 1553 1554 if (lnk == NULL && create) { 1555 struct in_addr alias_addr; 1556 1557 alias_addr = FindAliasAddress(la, src_addr); 1558 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1559 src_port, dst_port, GET_ALIAS_PORT, 1560 link_type); 1561 } 1562 return (lnk); 1563 } 1564 1565 1566 struct alias_link * 1567 AddPptp(struct libalias *la, struct in_addr src_addr, 1568 struct in_addr dst_addr, 1569 struct in_addr alias_addr, 1570 u_int16_t src_call_id) 1571 { 1572 struct alias_link *lnk; 1573 1574 LIBALIAS_LOCK_ASSERT(la); 1575 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1576 src_call_id, 0, GET_ALIAS_PORT, 1577 LINK_PPTP); 1578 1579 return (lnk); 1580 } 1581 1582 1583 struct alias_link * 1584 FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr, 1585 struct in_addr dst_addr, 1586 u_int16_t src_call_id) 1587 { 1588 u_int i; 1589 struct alias_link *lnk; 1590 1591 LIBALIAS_LOCK_ASSERT(la); 1592 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); 1593 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) 1594 if (lnk->link_type == LINK_PPTP && 1595 lnk->src_addr.s_addr == src_addr.s_addr && 1596 lnk->dst_addr.s_addr == dst_addr.s_addr && 1597 lnk->src_port == src_call_id) 1598 break; 1599 1600 return (lnk); 1601 } 1602 1603 1604 struct alias_link * 1605 FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr, 1606 struct in_addr dst_addr, 1607 u_int16_t dst_call_id) 1608 { 1609 u_int i; 1610 struct alias_link *lnk; 1611 1612 LIBALIAS_LOCK_ASSERT(la); 1613 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); 1614 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) 1615 if (lnk->link_type == LINK_PPTP && 1616 lnk->src_addr.s_addr == src_addr.s_addr && 1617 lnk->dst_addr.s_addr == dst_addr.s_addr && 1618 lnk->dst_port == dst_call_id) 1619 break; 1620 1621 return (lnk); 1622 } 1623 1624 1625 struct alias_link * 1626 FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr, 1627 struct in_addr alias_addr, 1628 u_int16_t dst_call_id) 1629 { 1630 u_int i; 1631 struct alias_link *lnk; 1632 1633 LIBALIAS_LOCK_ASSERT(la); 1634 i = StartPointIn(alias_addr, 0, LINK_PPTP); 1635 LIST_FOREACH(lnk, &la->linkTableIn[i], list_in) 1636 if (lnk->link_type == LINK_PPTP && 1637 lnk->dst_addr.s_addr == dst_addr.s_addr && 1638 lnk->alias_addr.s_addr == alias_addr.s_addr && 1639 lnk->dst_port == dst_call_id) 1640 break; 1641 1642 return (lnk); 1643 } 1644 1645 1646 struct alias_link * 1647 FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr, 1648 struct in_addr alias_addr, 1649 u_int16_t alias_call_id) 1650 { 1651 struct alias_link *lnk; 1652 1653 LIBALIAS_LOCK_ASSERT(la); 1654 lnk = FindLinkIn(la, dst_addr, alias_addr, 1655 0 /* any */ , alias_call_id, 1656 LINK_PPTP, 0); 1657 1658 1659 return (lnk); 1660 } 1661 1662 1663 struct alias_link * 1664 FindRtspOut(struct libalias *la, struct in_addr src_addr, 1665 struct in_addr dst_addr, 1666 u_short src_port, 1667 u_short alias_port, 1668 u_char proto) 1669 { 1670 int link_type; 1671 struct alias_link *lnk; 1672 1673 LIBALIAS_LOCK_ASSERT(la); 1674 switch (proto) { 1675 case IPPROTO_UDP: 1676 link_type = LINK_UDP; 1677 break; 1678 case IPPROTO_TCP: 1679 link_type = LINK_TCP; 1680 break; 1681 default: 1682 return (NULL); 1683 break; 1684 } 1685 1686 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1); 1687 1688 if (lnk == NULL) { 1689 struct in_addr alias_addr; 1690 1691 alias_addr = FindAliasAddress(la, src_addr); 1692 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1693 src_port, 0, alias_port, 1694 link_type); 1695 } 1696 return (lnk); 1697 } 1698 1699 1700 struct in_addr 1701 FindOriginalAddress(struct libalias *la, struct in_addr alias_addr) 1702 { 1703 struct alias_link *lnk; 1704 1705 LIBALIAS_LOCK_ASSERT(la); 1706 lnk = FindLinkIn(la, la->nullAddress, alias_addr, 1707 0, 0, LINK_ADDR, 0); 1708 if (lnk == NULL) { 1709 la->newDefaultLink = 1; 1710 if (la->targetAddress.s_addr == INADDR_ANY) 1711 return (alias_addr); 1712 else if (la->targetAddress.s_addr == INADDR_NONE) 1713 return (la->aliasAddress.s_addr != INADDR_ANY) ? 1714 la->aliasAddress : alias_addr; 1715 else 1716 return (la->targetAddress); 1717 } else { 1718 if (lnk->server != NULL) { /* LSNAT link */ 1719 struct in_addr src_addr; 1720 1721 src_addr = lnk->server->addr; 1722 lnk->server = lnk->server->next; 1723 return (src_addr); 1724 } else if (lnk->src_addr.s_addr == INADDR_ANY) 1725 return (la->aliasAddress.s_addr != INADDR_ANY) ? 1726 la->aliasAddress : alias_addr; 1727 else 1728 return (lnk->src_addr); 1729 } 1730 } 1731 1732 1733 struct in_addr 1734 FindAliasAddress(struct libalias *la, struct in_addr original_addr) 1735 { 1736 struct alias_link *lnk; 1737 1738 LIBALIAS_LOCK_ASSERT(la); 1739 lnk = FindLinkOut(la, original_addr, la->nullAddress, 1740 0, 0, LINK_ADDR, 0); 1741 if (lnk == NULL) { 1742 return (la->aliasAddress.s_addr != INADDR_ANY) ? 1743 la->aliasAddress : original_addr; 1744 } else { 1745 if (lnk->alias_addr.s_addr == INADDR_ANY) 1746 return (la->aliasAddress.s_addr != INADDR_ANY) ? 1747 la->aliasAddress : original_addr; 1748 else 1749 return (lnk->alias_addr); 1750 } 1751 } 1752 1753 1754 /* External routines for getting or changing link data 1755 (external to alias_db.c, but internal to alias*.c) 1756 1757 SetFragmentData(), GetFragmentData() 1758 SetFragmentPtr(), GetFragmentPtr() 1759 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut() 1760 GetOriginalAddress(), GetDestAddress(), GetAliasAddress() 1761 GetOriginalPort(), GetAliasPort() 1762 SetAckModified(), GetAckModified() 1763 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq() 1764 SetProtocolFlags(), GetProtocolFlags() 1765 SetDestCallId() 1766 */ 1767 1768 1769 void 1770 SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr) 1771 { 1772 lnk->data.frag_addr = src_addr; 1773 } 1774 1775 1776 void 1777 GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr) 1778 { 1779 *src_addr = lnk->data.frag_addr; 1780 } 1781 1782 1783 void 1784 SetFragmentPtr(struct alias_link *lnk, char *fptr) 1785 { 1786 lnk->data.frag_ptr = fptr; 1787 } 1788 1789 1790 void 1791 GetFragmentPtr(struct alias_link *lnk, char **fptr) 1792 { 1793 *fptr = lnk->data.frag_ptr; 1794 } 1795 1796 1797 void 1798 SetStateIn(struct alias_link *lnk, int state) 1799 { 1800 /* TCP input state */ 1801 switch (state) { 1802 case ALIAS_TCP_STATE_DISCONNECTED: 1803 if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED) 1804 lnk->expire_time = TCP_EXPIRE_DEAD; 1805 else 1806 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD; 1807 break; 1808 case ALIAS_TCP_STATE_CONNECTED: 1809 if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED) 1810 lnk->expire_time = TCP_EXPIRE_CONNECTED; 1811 break; 1812 default: 1813 #ifdef _KERNEL 1814 panic("libalias:SetStateIn() unknown state"); 1815 #else 1816 abort(); 1817 #endif 1818 } 1819 lnk->data.tcp->state.in = state; 1820 } 1821 1822 1823 void 1824 SetStateOut(struct alias_link *lnk, int state) 1825 { 1826 /* TCP output state */ 1827 switch (state) { 1828 case ALIAS_TCP_STATE_DISCONNECTED: 1829 if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED) 1830 lnk->expire_time = TCP_EXPIRE_DEAD; 1831 else 1832 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD; 1833 break; 1834 case ALIAS_TCP_STATE_CONNECTED: 1835 if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED) 1836 lnk->expire_time = TCP_EXPIRE_CONNECTED; 1837 break; 1838 default: 1839 #ifdef _KERNEL 1840 panic("libalias:SetStateOut() unknown state"); 1841 #else 1842 abort(); 1843 #endif 1844 } 1845 lnk->data.tcp->state.out = state; 1846 } 1847 1848 1849 int 1850 GetStateIn(struct alias_link *lnk) 1851 { 1852 /* TCP input state */ 1853 return (lnk->data.tcp->state.in); 1854 } 1855 1856 1857 int 1858 GetStateOut(struct alias_link *lnk) 1859 { 1860 /* TCP output state */ 1861 return (lnk->data.tcp->state.out); 1862 } 1863 1864 1865 struct in_addr 1866 GetOriginalAddress(struct alias_link *lnk) 1867 { 1868 if (lnk->src_addr.s_addr == INADDR_ANY) 1869 return (lnk->la->aliasAddress); 1870 else 1871 return (lnk->src_addr); 1872 } 1873 1874 1875 struct in_addr 1876 GetDestAddress(struct alias_link *lnk) 1877 { 1878 return (lnk->dst_addr); 1879 } 1880 1881 1882 struct in_addr 1883 GetAliasAddress(struct alias_link *lnk) 1884 { 1885 if (lnk->alias_addr.s_addr == INADDR_ANY) 1886 return (lnk->la->aliasAddress); 1887 else 1888 return (lnk->alias_addr); 1889 } 1890 1891 1892 struct in_addr 1893 GetDefaultAliasAddress(struct libalias *la) 1894 { 1895 1896 LIBALIAS_LOCK_ASSERT(la); 1897 return (la->aliasAddress); 1898 } 1899 1900 1901 void 1902 SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr) 1903 { 1904 1905 LIBALIAS_LOCK_ASSERT(la); 1906 la->aliasAddress = alias_addr; 1907 } 1908 1909 1910 u_short 1911 GetOriginalPort(struct alias_link *lnk) 1912 { 1913 return (lnk->src_port); 1914 } 1915 1916 1917 u_short 1918 GetAliasPort(struct alias_link *lnk) 1919 { 1920 return (lnk->alias_port); 1921 } 1922 1923 #ifndef NO_FW_PUNCH 1924 static u_short 1925 GetDestPort(struct alias_link *lnk) 1926 { 1927 return (lnk->dst_port); 1928 } 1929 1930 #endif 1931 1932 void 1933 SetAckModified(struct alias_link *lnk) 1934 { 1935 /* Indicate that ACK numbers have been modified in a TCP connection */ 1936 lnk->data.tcp->state.ack_modified = 1; 1937 } 1938 1939 1940 struct in_addr 1941 GetProxyAddress(struct alias_link *lnk) 1942 { 1943 return (lnk->proxy_addr); 1944 } 1945 1946 1947 void 1948 SetProxyAddress(struct alias_link *lnk, struct in_addr addr) 1949 { 1950 lnk->proxy_addr = addr; 1951 } 1952 1953 1954 u_short 1955 GetProxyPort(struct alias_link *lnk) 1956 { 1957 return (lnk->proxy_port); 1958 } 1959 1960 1961 void 1962 SetProxyPort(struct alias_link *lnk, u_short port) 1963 { 1964 lnk->proxy_port = port; 1965 } 1966 1967 1968 int 1969 GetAckModified(struct alias_link *lnk) 1970 { 1971 /* See if ACK numbers have been modified */ 1972 return (lnk->data.tcp->state.ack_modified); 1973 } 1974 1975 // XXX ip free 1976 int 1977 GetDeltaAckIn(u_long ack, struct alias_link *lnk) 1978 { 1979 /* 1980 Find out how much the ACK number has been altered for an incoming 1981 TCP packet. To do this, a circular list of ACK numbers where the TCP 1982 packet size was altered is searched. 1983 */ 1984 1985 int i; 1986 int delta, ack_diff_min; 1987 1988 delta = 0; 1989 ack_diff_min = -1; 1990 for (i = 0; i < N_LINK_TCP_DATA; i++) { 1991 struct ack_data_record x; 1992 1993 x = lnk->data.tcp->ack[i]; 1994 if (x.active == 1) { 1995 int ack_diff; 1996 1997 ack_diff = SeqDiff(x.ack_new, ack); 1998 if (ack_diff >= 0) { 1999 if (ack_diff_min >= 0) { 2000 if (ack_diff < ack_diff_min) { 2001 delta = x.delta; 2002 ack_diff_min = ack_diff; 2003 } 2004 } else { 2005 delta = x.delta; 2006 ack_diff_min = ack_diff; 2007 } 2008 } 2009 } 2010 } 2011 return (delta); 2012 } 2013 2014 // XXX ip free 2015 int 2016 GetDeltaSeqOut(u_long seq, struct alias_link *lnk) 2017 { 2018 /* 2019 Find out how much the sequence number has been altered for an outgoing 2020 TCP packet. To do this, a circular list of ACK numbers where the TCP 2021 packet size was altered is searched. 2022 */ 2023 2024 int i; 2025 int delta, seq_diff_min; 2026 2027 delta = 0; 2028 seq_diff_min = -1; 2029 for (i = 0; i < N_LINK_TCP_DATA; i++) { 2030 struct ack_data_record x; 2031 2032 x = lnk->data.tcp->ack[i]; 2033 if (x.active == 1) { 2034 int seq_diff; 2035 2036 seq_diff = SeqDiff(x.ack_old, seq); 2037 if (seq_diff >= 0) { 2038 if (seq_diff_min >= 0) { 2039 if (seq_diff < seq_diff_min) { 2040 delta = x.delta; 2041 seq_diff_min = seq_diff; 2042 } 2043 } else { 2044 delta = x.delta; 2045 seq_diff_min = seq_diff; 2046 } 2047 } 2048 } 2049 } 2050 return (delta); 2051 } 2052 2053 // XXX ip free 2054 void 2055 AddSeq(struct alias_link *lnk, int delta, u_int ip_hl, u_short ip_len, 2056 u_long th_seq, u_int th_off) 2057 { 2058 /* 2059 When a TCP packet has been altered in length, save this 2060 information in a circular list. If enough packets have 2061 been altered, then this list will begin to overwrite itself. 2062 */ 2063 2064 struct ack_data_record x; 2065 int hlen, tlen, dlen; 2066 int i; 2067 2068 hlen = (ip_hl + th_off) << 2; 2069 tlen = ntohs(ip_len); 2070 dlen = tlen - hlen; 2071 2072 x.ack_old = htonl(ntohl(th_seq) + dlen); 2073 x.ack_new = htonl(ntohl(th_seq) + dlen + delta); 2074 x.delta = delta; 2075 x.active = 1; 2076 2077 i = lnk->data.tcp->state.index; 2078 lnk->data.tcp->ack[i] = x; 2079 2080 i++; 2081 if (i == N_LINK_TCP_DATA) 2082 lnk->data.tcp->state.index = 0; 2083 else 2084 lnk->data.tcp->state.index = i; 2085 } 2086 2087 void 2088 SetExpire(struct alias_link *lnk, int expire) 2089 { 2090 if (expire == 0) { 2091 lnk->flags &= ~LINK_PERMANENT; 2092 DeleteLink(lnk); 2093 } else if (expire == -1) { 2094 lnk->flags |= LINK_PERMANENT; 2095 } else if (expire > 0) { 2096 lnk->expire_time = expire; 2097 } else { 2098 #ifdef LIBALIAS_DEBUG 2099 fprintf(stderr, "PacketAlias/SetExpire(): "); 2100 fprintf(stderr, "error in expire parameter\n"); 2101 #endif 2102 } 2103 } 2104 2105 void 2106 ClearCheckNewLink(struct libalias *la) 2107 { 2108 2109 LIBALIAS_LOCK_ASSERT(la); 2110 la->newDefaultLink = 0; 2111 } 2112 2113 void 2114 SetProtocolFlags(struct alias_link *lnk, int pflags) 2115 { 2116 2117 lnk->pflags = pflags;; 2118 } 2119 2120 int 2121 GetProtocolFlags(struct alias_link *lnk) 2122 { 2123 2124 return (lnk->pflags); 2125 } 2126 2127 void 2128 SetDestCallId(struct alias_link *lnk, u_int16_t cid) 2129 { 2130 struct libalias *la = lnk->la; 2131 2132 LIBALIAS_LOCK_ASSERT(la); 2133 la->deleteAllLinks = 1; 2134 ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr, 2135 lnk->src_port, cid, lnk->alias_port, lnk->link_type); 2136 la->deleteAllLinks = 0; 2137 } 2138 2139 2140 /* Miscellaneous Functions 2141 2142 HouseKeeping() 2143 InitPacketAliasLog() 2144 UninitPacketAliasLog() 2145 */ 2146 2147 /* 2148 Whenever an outgoing or incoming packet is handled, HouseKeeping() 2149 is called to find and remove timed-out aliasing links. Logic exists 2150 to sweep through the entire table and linked list structure 2151 every 60 seconds. 2152 2153 (prototype in alias_local.h) 2154 */ 2155 2156 void 2157 HouseKeeping(struct libalias *la) 2158 { 2159 int i, n; 2160 #ifndef _KERNEL 2161 struct timeval tv; 2162 struct timezone tz; 2163 #endif 2164 2165 LIBALIAS_LOCK_ASSERT(la); 2166 /* 2167 * Save system time (seconds) in global variable timeStamp for use 2168 * by other functions. This is done so as not to unnecessarily 2169 * waste timeline by making system calls. 2170 */ 2171 #ifdef _KERNEL 2172 la->timeStamp = time_uptime; 2173 #else 2174 gettimeofday(&tv, &tz); 2175 la->timeStamp = tv.tv_sec; 2176 #endif 2177 2178 /* Compute number of spokes (output table link chains) to cover */ 2179 n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime); 2180 n /= ALIAS_CLEANUP_INTERVAL_SECS; 2181 2182 /* Handle different cases */ 2183 if (n > 0) { 2184 if (n > ALIAS_CLEANUP_MAX_SPOKES) 2185 n = ALIAS_CLEANUP_MAX_SPOKES; 2186 la->lastCleanupTime = la->timeStamp; 2187 for (i = 0; i < n; i++) 2188 IncrementalCleanup(la); 2189 } else if (n < 0) { 2190 #ifdef LIBALIAS_DEBUG 2191 fprintf(stderr, "PacketAlias/HouseKeeping(): "); 2192 fprintf(stderr, "something unexpected in time values\n"); 2193 #endif 2194 la->lastCleanupTime = la->timeStamp; 2195 } 2196 } 2197 2198 /* Init the log file and enable logging */ 2199 static int 2200 InitPacketAliasLog(struct libalias *la) 2201 { 2202 2203 LIBALIAS_LOCK_ASSERT(la); 2204 if (~la->packetAliasMode & PKT_ALIAS_LOG) { 2205 #ifdef _KERNEL 2206 if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE))) 2207 ; 2208 #else 2209 if ((la->logDesc = fopen("/var/log/alias.log", "w"))) 2210 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n"); 2211 #endif 2212 else 2213 return (ENOMEM); /* log initialization failed */ 2214 la->packetAliasMode |= PKT_ALIAS_LOG; 2215 } 2216 2217 return (1); 2218 } 2219 2220 /* Close the log-file and disable logging. */ 2221 static void 2222 UninitPacketAliasLog(struct libalias *la) 2223 { 2224 2225 LIBALIAS_LOCK_ASSERT(la); 2226 if (la->logDesc) { 2227 #ifdef _KERNEL 2228 free(la->logDesc); 2229 #else 2230 fclose(la->logDesc); 2231 #endif 2232 la->logDesc = NULL; 2233 } 2234 la->packetAliasMode &= ~PKT_ALIAS_LOG; 2235 } 2236 2237 /* Outside world interfaces 2238 2239 -- "outside world" means other than alias*.c routines -- 2240 2241 PacketAliasRedirectPort() 2242 PacketAliasAddServer() 2243 PacketAliasRedirectProto() 2244 PacketAliasRedirectAddr() 2245 PacketAliasRedirectDynamic() 2246 PacketAliasRedirectDelete() 2247 PacketAliasSetAddress() 2248 PacketAliasInit() 2249 PacketAliasUninit() 2250 PacketAliasSetMode() 2251 2252 (prototypes in alias.h) 2253 */ 2254 2255 /* Redirection from a specific public addr:port to a 2256 private addr:port */ 2257 struct alias_link * 2258 LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port, 2259 struct in_addr dst_addr, u_short dst_port, 2260 struct in_addr alias_addr, u_short alias_port, 2261 u_char proto) 2262 { 2263 int link_type; 2264 struct alias_link *lnk; 2265 2266 LIBALIAS_LOCK(la); 2267 switch (proto) { 2268 case IPPROTO_UDP: 2269 link_type = LINK_UDP; 2270 break; 2271 case IPPROTO_TCP: 2272 link_type = LINK_TCP; 2273 break; 2274 default: 2275 #ifdef LIBALIAS_DEBUG 2276 fprintf(stderr, "PacketAliasRedirectPort(): "); 2277 fprintf(stderr, "only TCP and UDP protocols allowed\n"); 2278 #endif 2279 lnk = NULL; 2280 goto getout; 2281 } 2282 2283 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 2284 src_port, dst_port, alias_port, 2285 link_type); 2286 2287 if (lnk != NULL) { 2288 lnk->flags |= LINK_PERMANENT; 2289 } 2290 #ifdef LIBALIAS_DEBUG 2291 else { 2292 fprintf(stderr, "PacketAliasRedirectPort(): " 2293 "call to AddLink() failed\n"); 2294 } 2295 #endif 2296 2297 getout: 2298 LIBALIAS_UNLOCK(la); 2299 return (lnk); 2300 } 2301 2302 /* Add server to the pool of servers */ 2303 int 2304 LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port) 2305 { 2306 struct server *server; 2307 int res; 2308 2309 LIBALIAS_LOCK(la); 2310 (void)la; 2311 2312 server = malloc(sizeof(struct server)); 2313 2314 if (server != NULL) { 2315 struct server *head; 2316 2317 server->addr = addr; 2318 server->port = port; 2319 2320 head = lnk->server; 2321 if (head == NULL) 2322 server->next = server; 2323 else { 2324 struct server *s; 2325 2326 for (s = head; s->next != head; s = s->next); 2327 s->next = server; 2328 server->next = head; 2329 } 2330 lnk->server = server; 2331 res = 0; 2332 } else 2333 res = -1; 2334 2335 LIBALIAS_UNLOCK(la); 2336 return (res); 2337 } 2338 2339 /* Redirect packets of a given IP protocol from a specific 2340 public address to a private address */ 2341 struct alias_link * 2342 LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr, 2343 struct in_addr dst_addr, 2344 struct in_addr alias_addr, 2345 u_char proto) 2346 { 2347 struct alias_link *lnk; 2348 2349 LIBALIAS_LOCK(la); 2350 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 2351 NO_SRC_PORT, NO_DEST_PORT, 0, 2352 proto); 2353 2354 if (lnk != NULL) { 2355 lnk->flags |= LINK_PERMANENT; 2356 } 2357 #ifdef LIBALIAS_DEBUG 2358 else { 2359 fprintf(stderr, "PacketAliasRedirectProto(): " 2360 "call to AddLink() failed\n"); 2361 } 2362 #endif 2363 2364 LIBALIAS_UNLOCK(la); 2365 return (lnk); 2366 } 2367 2368 /* Static address translation */ 2369 struct alias_link * 2370 LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr, 2371 struct in_addr alias_addr) 2372 { 2373 struct alias_link *lnk; 2374 2375 LIBALIAS_LOCK(la); 2376 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr, 2377 0, 0, 0, 2378 LINK_ADDR); 2379 2380 if (lnk != NULL) { 2381 lnk->flags |= LINK_PERMANENT; 2382 } 2383 #ifdef LIBALIAS_DEBUG 2384 else { 2385 fprintf(stderr, "PacketAliasRedirectAddr(): " 2386 "call to AddLink() failed\n"); 2387 } 2388 #endif 2389 2390 LIBALIAS_UNLOCK(la); 2391 return (lnk); 2392 } 2393 2394 2395 /* Mark the aliasing link dynamic */ 2396 int 2397 LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk) 2398 { 2399 int res; 2400 2401 LIBALIAS_LOCK(la); 2402 (void)la; 2403 2404 if (lnk->flags & LINK_PARTIALLY_SPECIFIED) 2405 res = -1; 2406 else { 2407 lnk->flags &= ~LINK_PERMANENT; 2408 res = 0; 2409 } 2410 LIBALIAS_UNLOCK(la); 2411 return (res); 2412 } 2413 2414 2415 void 2416 LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk) 2417 { 2418 /* This is a dangerous function to put in the API, 2419 because an invalid pointer can crash the program. */ 2420 2421 LIBALIAS_LOCK(la); 2422 la->deleteAllLinks = 1; 2423 DeleteLink(lnk); 2424 la->deleteAllLinks = 0; 2425 LIBALIAS_UNLOCK(la); 2426 } 2427 2428 2429 void 2430 LibAliasSetAddress(struct libalias *la, struct in_addr addr) 2431 { 2432 2433 LIBALIAS_LOCK(la); 2434 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE 2435 && la->aliasAddress.s_addr != addr.s_addr) 2436 CleanupAliasData(la); 2437 2438 la->aliasAddress = addr; 2439 LIBALIAS_UNLOCK(la); 2440 } 2441 2442 2443 void 2444 LibAliasSetTarget(struct libalias *la, struct in_addr target_addr) 2445 { 2446 2447 LIBALIAS_LOCK(la); 2448 la->targetAddress = target_addr; 2449 LIBALIAS_UNLOCK(la); 2450 } 2451 2452 static void 2453 finishoff(void) 2454 { 2455 2456 while (!LIST_EMPTY(&instancehead)) 2457 LibAliasUninit(LIST_FIRST(&instancehead)); 2458 } 2459 2460 struct libalias * 2461 LibAliasInit(struct libalias *la) 2462 { 2463 int i; 2464 #ifndef _KERNEL 2465 struct timeval tv; 2466 struct timezone tz; 2467 #endif 2468 2469 if (la == NULL) { 2470 la = calloc(sizeof *la, 1); 2471 if (la == NULL) 2472 return (la); 2473 2474 #ifndef _KERNEL /* kernel cleans up on module unload */ 2475 if (LIST_EMPTY(&instancehead)) 2476 atexit(finishoff); 2477 #endif 2478 LIST_INSERT_HEAD(&instancehead, la, instancelist); 2479 2480 #ifdef _KERNEL 2481 la->timeStamp = time_uptime; 2482 la->lastCleanupTime = time_uptime; 2483 #else 2484 gettimeofday(&tv, &tz); 2485 la->timeStamp = tv.tv_sec; 2486 la->lastCleanupTime = tv.tv_sec; 2487 #endif 2488 2489 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) 2490 LIST_INIT(&la->linkTableOut[i]); 2491 for (i = 0; i < LINK_TABLE_IN_SIZE; i++) 2492 LIST_INIT(&la->linkTableIn[i]); 2493 LIBALIAS_LOCK_INIT(la); 2494 LIBALIAS_LOCK(la); 2495 } else { 2496 LIBALIAS_LOCK(la); 2497 la->deleteAllLinks = 1; 2498 CleanupAliasData(la); 2499 la->deleteAllLinks = 0; 2500 } 2501 2502 la->aliasAddress.s_addr = INADDR_ANY; 2503 la->targetAddress.s_addr = INADDR_ANY; 2504 2505 la->icmpLinkCount = 0; 2506 la->udpLinkCount = 0; 2507 la->tcpLinkCount = 0; 2508 la->pptpLinkCount = 0; 2509 la->protoLinkCount = 0; 2510 la->fragmentIdLinkCount = 0; 2511 la->fragmentPtrLinkCount = 0; 2512 la->sockCount = 0; 2513 2514 la->cleanupIndex = 0; 2515 2516 la->packetAliasMode = PKT_ALIAS_SAME_PORTS 2517 #ifndef NO_USE_SOCKETS 2518 | PKT_ALIAS_USE_SOCKETS 2519 #endif 2520 | PKT_ALIAS_RESET_ON_ADDR_CHANGE; 2521 #ifndef NO_FW_PUNCH 2522 la->fireWallFD = -1; 2523 #endif 2524 #ifndef _KERNEL 2525 LibAliasRefreshModules(); 2526 #endif 2527 LIBALIAS_UNLOCK(la); 2528 return (la); 2529 } 2530 2531 void 2532 LibAliasUninit(struct libalias *la) 2533 { 2534 2535 LIBALIAS_LOCK(la); 2536 la->deleteAllLinks = 1; 2537 CleanupAliasData(la); 2538 la->deleteAllLinks = 0; 2539 UninitPacketAliasLog(la); 2540 #ifndef NO_FW_PUNCH 2541 UninitPunchFW(la); 2542 #endif 2543 LIST_REMOVE(la, instancelist); 2544 LIBALIAS_UNLOCK(la); 2545 LIBALIAS_LOCK_DESTROY(la); 2546 free(la); 2547 } 2548 2549 /* Change mode for some operations */ 2550 unsigned int 2551 LibAliasSetMode( 2552 struct libalias *la, 2553 unsigned int flags, /* Which state to bring flags to */ 2554 unsigned int mask /* Mask of which flags to affect (use 0 to 2555 * do a probe for flag values) */ 2556 ) 2557 { 2558 int res = -1; 2559 2560 LIBALIAS_LOCK(la); 2561 /* Enable logging? */ 2562 if (flags & mask & PKT_ALIAS_LOG) { 2563 /* Do the enable */ 2564 if (InitPacketAliasLog(la) == ENOMEM) 2565 goto getout; 2566 } else 2567 /* _Disable_ logging? */ 2568 if (~flags & mask & PKT_ALIAS_LOG) { 2569 UninitPacketAliasLog(la); 2570 } 2571 #ifndef NO_FW_PUNCH 2572 /* Start punching holes in the firewall? */ 2573 if (flags & mask & PKT_ALIAS_PUNCH_FW) { 2574 InitPunchFW(la); 2575 } else 2576 /* Stop punching holes in the firewall? */ 2577 if (~flags & mask & PKT_ALIAS_PUNCH_FW) { 2578 UninitPunchFW(la); 2579 } 2580 #endif 2581 2582 /* Other flags can be set/cleared without special action */ 2583 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask); 2584 res = la->packetAliasMode; 2585 getout: 2586 LIBALIAS_UNLOCK(la); 2587 return (res); 2588 } 2589 2590 2591 int 2592 LibAliasCheckNewLink(struct libalias *la) 2593 { 2594 int res; 2595 2596 LIBALIAS_LOCK(la); 2597 res = la->newDefaultLink; 2598 LIBALIAS_UNLOCK(la); 2599 return (res); 2600 } 2601 2602 2603 #ifndef NO_FW_PUNCH 2604 2605 /***************** 2606 Code to support firewall punching. This shouldn't really be in this 2607 file, but making variables global is evil too. 2608 ****************/ 2609 2610 /* Firewall include files */ 2611 #include <net/if.h> 2612 #include <netinet/ip_fw.h> 2613 #include <string.h> 2614 #include <err.h> 2615 2616 /* 2617 * helper function, updates the pointer to cmd with the length 2618 * of the current command, and also cleans up the first word of 2619 * the new command in case it has been clobbered before. 2620 */ 2621 static ipfw_insn * 2622 next_cmd(ipfw_insn * cmd) 2623 { 2624 cmd += F_LEN(cmd); 2625 bzero(cmd, sizeof(*cmd)); 2626 return (cmd); 2627 } 2628 2629 /* 2630 * A function to fill simple commands of size 1. 2631 * Existing flags are preserved. 2632 */ 2633 static ipfw_insn * 2634 fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size, 2635 int flags, u_int16_t arg) 2636 { 2637 cmd->opcode = opcode; 2638 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK); 2639 cmd->arg1 = arg; 2640 return next_cmd(cmd); 2641 } 2642 2643 static ipfw_insn * 2644 fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr) 2645 { 2646 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1; 2647 2648 cmd->addr.s_addr = addr; 2649 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0); 2650 } 2651 2652 static ipfw_insn * 2653 fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port) 2654 { 2655 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1; 2656 2657 cmd->ports[0] = cmd->ports[1] = port; 2658 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0); 2659 } 2660 2661 static int 2662 fill_rule(void *buf, int bufsize, int rulenum, 2663 enum ipfw_opcodes action, int proto, 2664 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp) 2665 { 2666 struct ip_fw *rule = (struct ip_fw *)buf; 2667 ipfw_insn *cmd = (ipfw_insn *) rule->cmd; 2668 2669 bzero(buf, bufsize); 2670 rule->rulenum = rulenum; 2671 2672 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto); 2673 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr); 2674 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp); 2675 cmd = fill_ip(cmd, O_IP_DST, da.s_addr); 2676 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp); 2677 2678 rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd; 2679 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0); 2680 2681 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd; 2682 2683 return ((char *)cmd - (char *)buf); 2684 } 2685 2686 static void ClearAllFWHoles(struct libalias *la); 2687 2688 2689 #define fw_setfield(la, field, num) \ 2690 do { \ 2691 (field)[(num) - la->fireWallBaseNum] = 1; \ 2692 } /*lint -save -e717 */ while(0)/* lint -restore */ 2693 2694 #define fw_clrfield(la, field, num) \ 2695 do { \ 2696 (field)[(num) - la->fireWallBaseNum] = 0; \ 2697 } /*lint -save -e717 */ while(0)/* lint -restore */ 2698 2699 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum]) 2700 2701 static void 2702 InitPunchFW(struct libalias *la) 2703 { 2704 2705 LIBALIAS_LOCK_ASSERT(la); 2706 la->fireWallField = malloc(la->fireWallNumNums); 2707 if (la->fireWallField) { 2708 memset(la->fireWallField, 0, la->fireWallNumNums); 2709 if (la->fireWallFD < 0) { 2710 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 2711 } 2712 ClearAllFWHoles(la); 2713 la->fireWallActiveNum = la->fireWallBaseNum; 2714 } 2715 } 2716 2717 static void 2718 UninitPunchFW(struct libalias *la) 2719 { 2720 2721 LIBALIAS_LOCK_ASSERT(la); 2722 ClearAllFWHoles(la); 2723 if (la->fireWallFD >= 0) 2724 close(la->fireWallFD); 2725 la->fireWallFD = -1; 2726 if (la->fireWallField) 2727 free(la->fireWallField); 2728 la->fireWallField = NULL; 2729 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW; 2730 } 2731 2732 /* Make a certain link go through the firewall */ 2733 void 2734 PunchFWHole(struct alias_link *lnk) 2735 { 2736 struct libalias *la; 2737 int r; /* Result code */ 2738 struct ip_fw rule; /* On-the-fly built rule */ 2739 int fwhole; /* Where to punch hole */ 2740 2741 LIBALIAS_LOCK_ASSERT(la); 2742 la = lnk->la; 2743 2744 /* Don't do anything unless we are asked to */ 2745 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) || 2746 la->fireWallFD < 0 || 2747 lnk->link_type != LINK_TCP) 2748 return; 2749 2750 memset(&rule, 0, sizeof rule); 2751 2752 /** Build rule **/ 2753 2754 /* Find empty slot */ 2755 for (fwhole = la->fireWallActiveNum; 2756 fwhole < la->fireWallBaseNum + la->fireWallNumNums && 2757 fw_tstfield(la, la->fireWallField, fwhole); 2758 fwhole++); 2759 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) { 2760 for (fwhole = la->fireWallBaseNum; 2761 fwhole < la->fireWallActiveNum && 2762 fw_tstfield(la, la->fireWallField, fwhole); 2763 fwhole++); 2764 if (fwhole == la->fireWallActiveNum) { 2765 /* No rule point empty - we can't punch more holes. */ 2766 la->fireWallActiveNum = la->fireWallBaseNum; 2767 #ifdef LIBALIAS_DEBUG 2768 fprintf(stderr, "libalias: Unable to create firewall hole!\n"); 2769 #endif 2770 return; 2771 } 2772 } 2773 /* Start next search at next position */ 2774 la->fireWallActiveNum = fwhole + 1; 2775 2776 /* 2777 * generate two rules of the form 2778 * 2779 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole 2780 * accept tcp from DAddr DPort to OAddr OPort 2781 */ 2782 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) { 2783 u_int32_t rulebuf[255]; 2784 int i; 2785 2786 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole, 2787 O_ACCEPT, IPPROTO_TCP, 2788 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)), 2789 GetDestAddress(lnk), ntohs(GetDestPort(lnk))); 2790 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i); 2791 if (r) 2792 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)"); 2793 2794 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole, 2795 O_ACCEPT, IPPROTO_TCP, 2796 GetDestAddress(lnk), ntohs(GetDestPort(lnk)), 2797 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk))); 2798 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i); 2799 if (r) 2800 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)"); 2801 } 2802 2803 /* Indicate hole applied */ 2804 lnk->data.tcp->fwhole = fwhole; 2805 fw_setfield(la, la->fireWallField, fwhole); 2806 } 2807 2808 /* Remove a hole in a firewall associated with a particular alias 2809 lnk. Calling this too often is harmless. */ 2810 static void 2811 ClearFWHole(struct alias_link *lnk) 2812 { 2813 struct libalias *la; 2814 2815 LIBALIAS_LOCK_ASSERT(la); 2816 la = lnk->la; 2817 if (lnk->link_type == LINK_TCP) { 2818 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall 2819 * hole? */ 2820 struct ip_fw rule; 2821 2822 if (fwhole < 0) 2823 return; 2824 2825 memset(&rule, 0, sizeof rule); /* useless for ipfw2 */ 2826 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, 2827 &fwhole, sizeof fwhole)); 2828 fw_clrfield(la, la->fireWallField, fwhole); 2829 lnk->data.tcp->fwhole = -1; 2830 } 2831 } 2832 2833 /* Clear out the entire range dedicated to firewall holes. */ 2834 static void 2835 ClearAllFWHoles(struct libalias *la) 2836 { 2837 struct ip_fw rule; /* On-the-fly built rule */ 2838 int i; 2839 2840 LIBALIAS_LOCK_ASSERT(la); 2841 if (la->fireWallFD < 0) 2842 return; 2843 2844 memset(&rule, 0, sizeof rule); 2845 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) { 2846 int r = i; 2847 2848 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r)); 2849 } 2850 /* XXX: third arg correct here ? /phk */ 2851 memset(la->fireWallField, 0, la->fireWallNumNums); 2852 } 2853 2854 #endif 2855 2856 void 2857 LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num) 2858 { 2859 2860 LIBALIAS_LOCK(la); 2861 #ifndef NO_FW_PUNCH 2862 la->fireWallBaseNum = base; 2863 la->fireWallNumNums = num; 2864 #endif 2865 LIBALIAS_UNLOCK(la); 2866 } 2867 2868 void 2869 LibAliasSetSkinnyPort(struct libalias *la, unsigned int port) 2870 { 2871 2872 LIBALIAS_LOCK(la); 2873 la->skinnyPort = port; 2874 LIBALIAS_UNLOCK(la); 2875 } 2876