alias_db.c revision 131699
119370Spst/*- 219370Spst * Copyright (c) 2001 Charles Mott <cm@linktel.net> 319370Spst * All rights reserved. 419370Spst * 546283Sdfr * Redistribution and use in source and binary forms, with or without 619370Spst * modification, are permitted provided that the following conditions 719370Spst * are met: 819370Spst * 1. Redistributions of source code must retain the above copyright 919370Spst * notice, this list of conditions and the following disclaimer. 1019370Spst * 2. Redistributions in binary form must reproduce the above copyright 1119370Spst * notice, this list of conditions and the following disclaimer in the 1219370Spst * documentation and/or other materials provided with the distribution. 1319370Spst * 1419370Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1519370Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1619370Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1719370Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1819370Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1919370Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2019370Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2119370Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2219370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2319370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2419370Spst * SUCH DAMAGE. 2519370Spst */ 2619370Spst 2719370Spst#include <sys/cdefs.h> 2819370Spst__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_db.c 131699 2004-07-06 12:13:28Z des $"); 2919370Spst 3019370Spst/* 3119370Spst Alias_db.c encapsulates all data structures used for storing 3219370Spst packet aliasing data. Other parts of the aliasing software 3319370Spst access data through functions provided in this file. 3419370Spst 3519370Spst Data storage is based on the notion of a "link", which is 3619370Spst established for ICMP echo/reply packets, UDP datagrams and 3719370Spst TCP stream connections. A link stores the original source 3819370Spst and destination addresses. For UDP and TCP, it also stores 3919370Spst source and destination port numbers, as well as an alias 4019370Spst port number. Links are also used to store information about 4119370Spst fragments. 4219370Spst 4319370Spst There is a facility for sweeping through and deleting old 4419370Spst links as new packets are sent through. A simple timeout is 4519370Spst used for ICMP and UDP links. TCP links are left alone unless 4619370Spst there is an incomplete connection, in which case the link 4719370Spst can be deleted after a certain amount of time. 4819370Spst 4919370Spst 5019370Spst Initial version: August, 1996 (cjm) 5119370Spst 5219370Spst Version 1.4: September 16, 1996 (cjm) 5319370Spst Facility for handling incoming links added. 5419370Spst 5519370Spst Version 1.6: September 18, 1996 (cjm) 5619370Spst ICMP data handling simplified. 5719370Spst 5819370Spst Version 1.7: January 9, 1997 (cjm) 5919370Spst Fragment handling simplified. 6019370Spst Saves pointers for unresolved fragments. 6119370Spst Permits links for unspecified remote ports 6219370Spst or unspecified remote addresses. 6319370Spst Fixed bug which did not properly zero port 6419370Spst table entries after a link was deleted. 6519370Spst Cleaned up some obsolete comments. 6619370Spst 6719370Spst Version 1.8: January 14, 1997 (cjm) 6819370Spst Fixed data type error in StartPoint(). 6919370Spst (This error did not exist prior to v1.7 7019370Spst and was discovered and fixed by Ari Suutari) 7119370Spst 7219370Spst Version 1.9: February 1, 1997 7319370Spst Optionally, connections initiated from packet aliasing host 7419370Spst machine will will not have their port number aliased unless it 7519370Spst conflicts with an aliasing port already being used. (cjm) 7619370Spst 7719370Spst All options earlier being #ifdef'ed are now available through 7819370Spst a new interface, SetPacketAliasMode(). This allows run time 7919370Spst control (which is now available in PPP+pktAlias through the 8019370Spst 'alias' keyword). (ee) 8119370Spst 8219370Spst Added ability to create an alias port without 8319370Spst either destination address or port specified. 8419370Spst port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee) 8519370Spst 8619370Spst Removed K&R style function headers 8719370Spst and general cleanup. (ee) 8819370Spst 8919370Spst Added packetAliasMode to replace compiler #defines's (ee) 9019370Spst 9119370Spst Allocates sockets for partially specified 9219370Spst ports if ALIAS_USE_SOCKETS defined. (cjm) 9319370Spst 9419370Spst Version 2.0: March, 1997 9519370Spst SetAliasAddress() will now clean up alias links 9619370Spst if the aliasing address is changed. (cjm) 9719370Spst 9819370Spst PacketAliasPermanentLink() function added to support permanent 9919370Spst links. (J. Fortes suggested the need for this.) 10019370Spst Examples: 10119370Spst 10219370Spst (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port 10319370Spst 10419370Spst (192.168.0.2, port 21) <-> alias port 3604, known dest addr 10519370Spst unknown dest port 10619370Spst 10719370Spst These permanent links allow for incoming connections to 10819370Spst machines on the local network. They can be given with a 10919370Spst user-chosen amount of specificity, with increasing specificity 11019370Spst meaning more security. (cjm) 11119370Spst 11219370Spst Quite a bit of rework to the basic engine. The portTable[] 11319370Spst array, which kept track of which ports were in use was replaced 11419370Spst by a table/linked list structure. (cjm) 11519370Spst 11619370Spst SetExpire() function added. (cjm) 11719370Spst 11819370Spst DeleteLink() no longer frees memory association with a pointer 11919370Spst to a fragment (this bug was first recognized by E. Eklund in 12019370Spst v1.9). 12119370Spst 12219370Spst Version 2.1: May, 1997 (cjm) 12319370Spst Packet aliasing engine reworked so that it can handle 12419370Spst multiple external addresses rather than just a single 12519370Spst host address. 12619370Spst 12719370Spst PacketAliasRedirectPort() and PacketAliasRedirectAddr() 12819370Spst added to the API. The first function is a more generalized 12919370Spst version of PacketAliasPermanentLink(). The second function 13019370Spst implements static network address translation. 13119370Spst 13219370Spst Version 3.2: July, 2000 (salander and satoh) 13319370Spst Added FindNewPortGroup to get contiguous range of port values. 13419370Spst 13519370Spst Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing 13619370Spst link but not actually add one. 13719370Spst 13819370Spst Added FindRtspOut, which is closely derived from FindUdpTcpOut, 13919370Spst except that the alias port (from FindNewPortGroup) is provided 14019370Spst as input. 14119370Spst 14219370Spst See HISTORY file for additional revisions. 14319370Spst*/ 14419370Spst 14519370Spst 14619370Spst/* System include files */ 14719370Spst#include <errno.h> 14819370Spst#include <stdlib.h> 14919370Spst#include <stdio.h> 15019370Spst#include <unistd.h> 15119370Spst 15219370Spst#include <sys/queue.h> 15319370Spst#include <sys/socket.h> 15419370Spst#include <sys/time.h> 15519370Spst#include <sys/types.h> 15619370Spst 15719370Spst/* BSD network include files */ 15819370Spst#include <netinet/in_systm.h> 15919370Spst#include <netinet/in.h> 16019370Spst#include <netinet/ip.h> 16119370Spst#include <netinet/tcp.h> 16219370Spst#include <arpa/inet.h> 16319370Spst 16419370Spst#include "alias.h" 16519370Spst#include "alias_local.h" 16619370Spst 16719370Spst 16819370Spststatic LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead); 16919370Spst 17019370Spst 17119370Spst/* 17219370Spst Constants (note: constants are also defined 17319370Spst near relevant functions or structs) 17419370Spst*/ 17519370Spst 17619370Spst/* Parameters used for cleanup of expired links */ 17719370Spst#define ALIAS_CLEANUP_INTERVAL_SECS 60 17819370Spst#define ALIAS_CLEANUP_MAX_SPOKES 30 17919370Spst 18019370Spst/* Timeouts (in seconds) for different link types */ 18119370Spst#define ICMP_EXPIRE_TIME 60 18219370Spst#define UDP_EXPIRE_TIME 60 18319370Spst#define PROTO_EXPIRE_TIME 60 18419370Spst#define FRAGMENT_ID_EXPIRE_TIME 10 18519370Spst#define FRAGMENT_PTR_EXPIRE_TIME 30 18619370Spst 18719370Spst/* TCP link expire time for different cases */ 18819370Spst/* When the link has been used and closed - minimal grace time to 18919370Spst allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */ 19019370Spst#ifndef TCP_EXPIRE_DEAD 19119370Spst#define TCP_EXPIRE_DEAD 10 19219370Spst#endif 19319370Spst 19419370Spst/* When the link has been used and closed on one side - the other side 19519370Spst is allowed to still send data */ 19619370Spst#ifndef TCP_EXPIRE_SINGLEDEAD 19719370Spst#define TCP_EXPIRE_SINGLEDEAD 90 19819370Spst#endif 19919370Spst 20019370Spst/* When the link isn't yet up */ 20119370Spst#ifndef TCP_EXPIRE_INITIAL 20219370Spst#define TCP_EXPIRE_INITIAL 300 20319370Spst#endif 20419370Spst 20519370Spst/* When the link is up */ 20619370Spst#ifndef TCP_EXPIRE_CONNECTED 20719370Spst#define TCP_EXPIRE_CONNECTED 86400 20819370Spst#endif 20919370Spst 21019370Spst 21119370Spst/* Dummy port number codes used for FindLinkIn/Out() and AddLink(). 21219370Spst These constants can be anything except zero, which indicates an 21319370Spst unknown port number. */ 21419370Spst 21519370Spst#define NO_DEST_PORT 1 21619370Spst#define NO_SRC_PORT 1 21719370Spst 21819370Spst 21919370Spst 22019370Spst/* Data Structures 22119370Spst 22219370Spst The fundamental data structure used in this program is 22319370Spst "struct alias_link". Whenever a TCP connection is made, 22419370Spst a UDP datagram is sent out, or an ICMP echo request is made, 22519370Spst a link record is made (if it has not already been created). 22619370Spst The link record is identified by the source address/port 22719370Spst and the destination address/port. In the case of an ICMP 22819370Spst echo request, the source port is treated as being equivalent 22919370Spst with the 16-bit ID number of the ICMP packet. 23019370Spst 23119370Spst The link record also can store some auxiliary data. For 23219370Spst TCP connections that have had sequence and acknowledgment 23319370Spst modifications, data space is available to track these changes. 23419370Spst A state field is used to keep track in changes to the TCP 23519370Spst connection state. ID numbers of fragments can also be 23619370Spst stored in the auxiliary space. Pointers to unresolved 23719370Spst fragments can also be stored. 23819370Spst 23919370Spst The link records support two independent chainings. Lookup 24019370Spst tables for input and out tables hold the initial pointers 24119370Spst the link chains. On input, the lookup table indexes on alias 24219370Spst port and link type. On output, the lookup table indexes on 24319370Spst source address, destination address, source port, destination 24419370Spst port and link type. 24519370Spst*/ 24619370Spst 24719370Spststruct ack_data_record { /* used to save changes to ACK/sequence 24819370Spst * numbers */ 24919370Spst u_long ack_old; 25019370Spst u_long ack_new; 25119370Spst int delta; 25219370Spst int active; 25319370Spst}; 25419370Spst 25519370Spststruct tcp_state { /* Information about TCP connection */ 25619370Spst int in; /* State for outside -> inside */ 25719370Spst int out; /* State for inside -> outside */ 25819370Spst int index; /* Index to ACK data array */ 25919370Spst int ack_modified; /* Indicates whether ACK and 26019370Spst * sequence numbers */ 26119370Spst /* been modified */ 26219370Spst}; 26319370Spst 26419370Spst#define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes 26519370Spst * saved for a modified TCP stream */ 26619370Spststruct tcp_dat { 26719370Spst struct tcp_state state; 26819370Spst struct ack_data_record ack[N_LINK_TCP_DATA]; 26919370Spst int fwhole; /* Which firewall record is used for this 27019370Spst * hole? */ 27119370Spst}; 27219370Spst 27319370Spststruct server { /* LSNAT server pool (circular list) */ 27419370Spst struct in_addr addr; 27519370Spst u_short port; 27619370Spst struct server *next; 27719370Spst}; 27819370Spst 27919370Spststruct alias_link { /* Main data structure */ 28019370Spst struct libalias *la; 28119370Spst struct in_addr src_addr; /* Address and port information */ 28219370Spst struct in_addr dst_addr; 28319370Spst struct in_addr alias_addr; 28419370Spst struct in_addr proxy_addr; 28519370Spst u_short src_port; 28619370Spst u_short dst_port; 28719370Spst u_short alias_port; 28819370Spst u_short proxy_port; 28919370Spst struct server *server; 29019370Spst 29119370Spst int link_type; /* Type of link: TCP, UDP, ICMP, 29219370Spst * proto, frag */ 29319370Spst 29419370Spst/* values for link_type */ 29519370Spst#define LINK_ICMP IPPROTO_ICMP 29619370Spst#define LINK_UDP IPPROTO_UDP 29719370Spst#define LINK_TCP IPPROTO_TCP 29819370Spst#define LINK_FRAGMENT_ID (IPPROTO_MAX + 1) 29919370Spst#define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2) 30019370Spst#define LINK_ADDR (IPPROTO_MAX + 3) 30119370Spst#define LINK_PPTP (IPPROTO_MAX + 4) 30219370Spst 30319370Spst int flags; /* indicates special characteristics */ 30419370Spst int pflags; /* protocol-specific flags */ 30519370Spst 30619370Spst/* flag bits */ 30719370Spst#define LINK_UNKNOWN_DEST_PORT 0x01 30819370Spst#define LINK_UNKNOWN_DEST_ADDR 0x02 30919370Spst#define LINK_PERMANENT 0x04 31019370Spst#define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */ 31119370Spst#define LINK_UNFIREWALLED 0x08 31219370Spst 31319370Spst int timestamp; /* Time link was last accessed */ 31419370Spst int expire_time; /* Expire time for link */ 31519370Spst 31619370Spst int sockfd; /* socket descriptor */ 31719370Spst 31819370Spst LIST_ENTRY (alias_link) list_out; /* Linked list of 31919370Spst * pointers for */ 32019370Spst LIST_ENTRY (alias_link) list_in; /* input and output 32119370Spst * lookup tables */ 32219370Spst 32319370Spst union { /* Auxiliary data */ 32419370Spst char *frag_ptr; 32519370Spst struct in_addr frag_addr; 32619370Spst struct tcp_dat *tcp; 32719370Spst } data; 32819370Spst}; 32919370Spst 33019370Spst/* Internal utility routines (used only in alias_db.c) 33119370Spst 33219370SpstLookup table starting points: 33319370Spst StartPointIn() -- link table initial search point for 33419370Spst incoming packets 33519370Spst StartPointOut() -- link table initial search point for 33619370Spst outgoing packets 33719370Spst 33819370SpstMiscellaneous: 33919370Spst SeqDiff() -- difference between two TCP sequences 34019370Spst ShowAliasStats() -- send alias statistics to a monitor file 34119370Spst*/ 34219370Spst 34319370Spst 34419370Spst/* Local prototypes */ 34519370Spststatic u_int StartPointIn(struct in_addr, u_short, int); 34619370Spst 34719370Spststatic u_int 34819370SpstStartPointOut(struct in_addr, struct in_addr, 34919370Spst u_short, u_short, int); 35019370Spst 35119370Spststatic int SeqDiff(u_long, u_long); 35219370Spst 35319370Spststatic void ShowAliasStats(struct libalias *); 35419370Spst 35519370Spst#ifndef NO_FW_PUNCH 35619370Spst/* Firewall control */ 35719370Spststatic void InitPunchFW(struct libalias *); 35819370Spststatic void UninitPunchFW(struct libalias *); 35919370Spststatic void ClearFWHole(struct alias_link *); 36019370Spst 36119370Spst#endif 36219370Spst 36319370Spst/* Log file control */ 36419370Spststatic void InitPacketAliasLog(struct libalias *); 36519370Spststatic void UninitPacketAliasLog(struct libalias *); 36619370Spst 36719370Spststatic u_int 36819370SpstStartPointIn(struct in_addr alias_addr, 36919370Spst u_short alias_port, 37019370Spst int link_type) 37119370Spst{ 37219370Spst u_int n; 37319370Spst 37419370Spst n = alias_addr.s_addr; 37519370Spst if (link_type != LINK_PPTP) 37619370Spst n += alias_port; 37719370Spst n += link_type; 37819370Spst return (n % LINK_TABLE_IN_SIZE); 37919370Spst} 38019370Spst 38119370Spst 38219370Spststatic u_int 38319370SpstStartPointOut(struct in_addr src_addr, struct in_addr dst_addr, 38419370Spst u_short src_port, u_short dst_port, int link_type) 38519370Spst{ 38619370Spst u_int n; 38719370Spst 38819370Spst n = src_addr.s_addr; 38919370Spst n += dst_addr.s_addr; 39019370Spst if (link_type != LINK_PPTP) { 39119370Spst n += src_port; 39219370Spst n += dst_port; 39319370Spst } 39419370Spst n += link_type; 39519370Spst 39619370Spst return (n % LINK_TABLE_OUT_SIZE); 39719370Spst} 39819370Spst 39919370Spst 40019370Spststatic int 40119370SpstSeqDiff(u_long x, u_long y) 40219370Spst{ 40319370Spst/* Return the difference between two TCP sequence numbers */ 40419370Spst 40519370Spst/* 40619370Spst This function is encapsulated in case there are any unusual 40719370Spst arithmetic conditions that need to be considered. 40819370Spst*/ 40919370Spst 41019370Spst return (ntohl(y) - ntohl(x)); 41119370Spst} 41219370Spst 41319370Spst 41419370Spststatic void 41519370SpstShowAliasStats(struct libalias *la) 41619370Spst{ 41719370Spst/* Used for debugging */ 41819370Spst 41919370Spst if (la->monitorFile) { 42019370Spst fprintf(la->monitorFile, 42119370Spst "icmp=%d, udp=%d, tcp=%d, pptp=%d, proto=%d, frag_id=%d frag_ptr=%d", 42219370Spst la->icmpLinkCount, 42319370Spst la->udpLinkCount, 42419370Spst la->tcpLinkCount, 42519370Spst la->pptpLinkCount, 42619370Spst la->protoLinkCount, 42719370Spst la->fragmentIdLinkCount, 42819370Spst la->fragmentPtrLinkCount); 42919370Spst 43019370Spst fprintf(la->monitorFile, " / tot=%d (sock=%d)\n", 43119370Spst la->icmpLinkCount + la->udpLinkCount 43219370Spst + la->tcpLinkCount 43319370Spst + la->pptpLinkCount 43419370Spst + la->protoLinkCount 43519370Spst + la->fragmentIdLinkCount 43619370Spst + la->fragmentPtrLinkCount, 43719370Spst la->sockCount); 43819370Spst 43919370Spst fflush(la->monitorFile); 44019370Spst } 44119370Spst} 44219370Spst 44319370Spst 44419370Spst 44519370Spst 44619370Spst 44719370Spst/* Internal routines for finding, deleting and adding links 44819370Spst 44919370SpstPort Allocation: 45019370Spst GetNewPort() -- find and reserve new alias port number 45119370Spst GetSocket() -- try to allocate a socket for a given port 45219370Spst 45319370SpstLink creation and deletion: 45419370Spst CleanupAliasData() - remove all link chains from lookup table 45519370Spst IncrementalCleanup() - look for stale links in a single chain 45619370Spst DeleteLink() - remove link 45719370Spst AddLink() - add link 45819370Spst ReLink() - change link 45919370Spst 46019370SpstLink search: 46119370Spst FindLinkOut() - find link for outgoing packets 46219370Spst FindLinkIn() - find link for incoming packets 46319370Spst 46419370SpstPort search: 46519370Spst FindNewPortGroup() - find an available group of ports 46619370Spst*/ 46746283Sdfr 46846283Sdfr/* Local prototypes */ 46919370Spststatic int GetNewPort(struct libalias *, struct alias_link *, int); 47019370Spst 47119370Spststatic u_short GetSocket(struct libalias *, u_short, int *, int); 47219370Spst 47319370Spststatic void CleanupAliasData(struct libalias *); 47419370Spst 47519370Spststatic void IncrementalCleanup(struct libalias *); 47619370Spst 47719370Spststatic void DeleteLink(struct alias_link *); 47819370Spst 47919370Spststatic struct alias_link * 48019370SpstAddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr, 48119370Spst u_short, u_short, int, int); 48219370Spst 483static struct alias_link * 484ReLink(struct alias_link *, 485 struct in_addr, struct in_addr, struct in_addr, 486 u_short, u_short, int, int); 487 488static struct alias_link * 489 FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); 490 491static struct alias_link * 492 FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); 493 494 495#define ALIAS_PORT_BASE 0x08000 496#define ALIAS_PORT_MASK 0x07fff 497#define ALIAS_PORT_MASK_EVEN 0x07ffe 498#define GET_NEW_PORT_MAX_ATTEMPTS 20 499 500#define GET_ALIAS_PORT -1 501#define GET_ALIAS_ID GET_ALIAS_PORT 502 503#define FIND_EVEN_ALIAS_BASE 1 504 505/* GetNewPort() allocates port numbers. Note that if a port number 506 is already in use, that does not mean that it cannot be used by 507 another link concurrently. This is because GetNewPort() looks for 508 unused triplets: (dest addr, dest port, alias port). */ 509 510static int 511GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param) 512{ 513 int i; 514 int max_trials; 515 u_short port_sys; 516 u_short port_net; 517 518/* 519 Description of alias_port_param for GetNewPort(). When 520 this parameter is zero or positive, it precisely specifies 521 the port number. GetNewPort() will return this number 522 without check that it is in use. 523 524 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly 525 selected port number. 526*/ 527 528 if (alias_port_param == GET_ALIAS_PORT) { 529 /* 530 * The aliasing port is automatically selected by one of 531 * two methods below: 532 */ 533 max_trials = GET_NEW_PORT_MAX_ATTEMPTS; 534 535 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) { 536 /* 537 * When the PKT_ALIAS_SAME_PORTS option is chosen, 538 * the first try will be the actual source port. If 539 * this is already in use, the remainder of the 540 * trials will be random. 541 */ 542 port_net = lnk->src_port; 543 port_sys = ntohs(port_net); 544 } else { 545 /* First trial and all subsequent are random. */ 546 port_sys = random() & ALIAS_PORT_MASK; 547 port_sys += ALIAS_PORT_BASE; 548 port_net = htons(port_sys); 549 } 550 } else if (alias_port_param >= 0 && alias_port_param < 0x10000) { 551 lnk->alias_port = (u_short) alias_port_param; 552 return (0); 553 } else { 554#ifdef DEBUG 555 fprintf(stderr, "PacketAlias/GetNewPort(): "); 556 fprintf(stderr, "input parameter error\n"); 557#endif 558 return (-1); 559 } 560 561 562/* Port number search */ 563 for (i = 0; i < max_trials; i++) { 564 int go_ahead; 565 struct alias_link *search_result; 566 567 search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr, 568 lnk->dst_port, port_net, 569 lnk->link_type, 0); 570 571 if (search_result == NULL) 572 go_ahead = 1; 573 else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED) 574 && (search_result->flags & LINK_PARTIALLY_SPECIFIED)) 575 go_ahead = 1; 576 else 577 go_ahead = 0; 578 579 if (go_ahead) { 580 if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS) 581 && (lnk->flags & LINK_PARTIALLY_SPECIFIED) 582 && ((lnk->link_type == LINK_TCP) || 583 (lnk->link_type == LINK_UDP))) { 584 if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) { 585 lnk->alias_port = port_net; 586 return (0); 587 } 588 } else { 589 lnk->alias_port = port_net; 590 return (0); 591 } 592 } 593 port_sys = random() & ALIAS_PORT_MASK; 594 port_sys += ALIAS_PORT_BASE; 595 port_net = htons(port_sys); 596 } 597 598#ifdef DEBUG 599 fprintf(stderr, "PacketAlias/GetnewPort(): "); 600 fprintf(stderr, "could not find free port\n"); 601#endif 602 603 return (-1); 604} 605 606 607static u_short 608GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type) 609{ 610 int err; 611 int sock; 612 struct sockaddr_in sock_addr; 613 614 if (link_type == LINK_TCP) 615 sock = socket(AF_INET, SOCK_STREAM, 0); 616 else if (link_type == LINK_UDP) 617 sock = socket(AF_INET, SOCK_DGRAM, 0); 618 else { 619#ifdef DEBUG 620 fprintf(stderr, "PacketAlias/GetSocket(): "); 621 fprintf(stderr, "incorrect link type\n"); 622#endif 623 return (0); 624 } 625 626 if (sock < 0) { 627#ifdef DEBUG 628 fprintf(stderr, "PacketAlias/GetSocket(): "); 629 fprintf(stderr, "socket() error %d\n", *sockfd); 630#endif 631 return (0); 632 } 633 sock_addr.sin_family = AF_INET; 634 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); 635 sock_addr.sin_port = port_net; 636 637 err = bind(sock, 638 (struct sockaddr *)&sock_addr, 639 sizeof(sock_addr)); 640 if (err == 0) { 641 la->sockCount++; 642 *sockfd = sock; 643 return (1); 644 } else { 645 close(sock); 646 return (0); 647 } 648} 649 650 651/* FindNewPortGroup() returns a base port number for an available 652 range of contiguous port numbers. Note that if a port number 653 is already in use, that does not mean that it cannot be used by 654 another link concurrently. This is because FindNewPortGroup() 655 looks for unused triplets: (dest addr, dest port, alias port). */ 656 657int 658FindNewPortGroup(struct libalias *la, 659 struct in_addr dst_addr, 660 struct in_addr alias_addr, 661 u_short src_port, 662 u_short dst_port, 663 u_short port_count, 664 u_char proto, 665 u_char align) 666{ 667 int i, j; 668 int max_trials; 669 u_short port_sys; 670 int link_type; 671 672 /* 673 * Get link_type from protocol 674 */ 675 676 switch (proto) { 677 case IPPROTO_UDP: 678 link_type = LINK_UDP; 679 break; 680 case IPPROTO_TCP: 681 link_type = LINK_TCP; 682 break; 683 default: 684 return (0); 685 break; 686 } 687 688 /* 689 * The aliasing port is automatically selected by one of two 690 * methods below: 691 */ 692 max_trials = GET_NEW_PORT_MAX_ATTEMPTS; 693 694 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) { 695 /* 696 * When the ALIAS_SAME_PORTS option is chosen, the first 697 * try will be the actual source port. If this is already 698 * in use, the remainder of the trials will be random. 699 */ 700 port_sys = ntohs(src_port); 701 702 } else { 703 704 /* First trial and all subsequent are random. */ 705 if (align == FIND_EVEN_ALIAS_BASE) 706 port_sys = random() & ALIAS_PORT_MASK_EVEN; 707 else 708 port_sys = random() & ALIAS_PORT_MASK; 709 710 port_sys += ALIAS_PORT_BASE; 711 } 712 713/* Port number search */ 714 for (i = 0; i < max_trials; i++) { 715 716 struct alias_link *search_result; 717 718 for (j = 0; j < port_count; j++) 719 if (0 != (search_result = FindLinkIn(la, dst_addr, alias_addr, 720 dst_port, htons(port_sys + j), 721 link_type, 0))) 722 break; 723 724 /* Found a good range, return base */ 725 if (j == port_count) 726 return (htons(port_sys)); 727 728 /* Find a new base to try */ 729 if (align == FIND_EVEN_ALIAS_BASE) 730 port_sys = random() & ALIAS_PORT_MASK_EVEN; 731 else 732 port_sys = random() & ALIAS_PORT_MASK; 733 734 port_sys += ALIAS_PORT_BASE; 735 } 736 737#ifdef DEBUG 738 fprintf(stderr, "PacketAlias/FindNewPortGroup(): "); 739 fprintf(stderr, "could not find free port(s)\n"); 740#endif 741 742 return (0); 743} 744 745static void 746CleanupAliasData(struct libalias *la) 747{ 748 struct alias_link *lnk; 749 int i, icount; 750 751 icount = 0; 752 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) { 753 lnk = LIST_FIRST(&la->linkTableOut[i]); 754 while (lnk != NULL) { 755 struct alias_link *link_next; 756 757 link_next = LIST_NEXT(lnk, list_out); 758 icount++; 759 DeleteLink(lnk); 760 lnk = link_next; 761 } 762 } 763 764 la->cleanupIndex = 0; 765} 766 767 768static void 769IncrementalCleanup(struct libalias *la) 770{ 771 int icount; 772 struct alias_link *lnk; 773 774 icount = 0; 775 lnk = LIST_FIRST(&la->linkTableOut[la->cleanupIndex++]); 776 while (lnk != NULL) { 777 int idelta; 778 struct alias_link *link_next; 779 780 link_next = LIST_NEXT(lnk, list_out); 781 idelta = la->timeStamp - lnk->timestamp; 782 switch (lnk->link_type) { 783 case LINK_TCP: 784 if (idelta > lnk->expire_time) { 785 struct tcp_dat *tcp_aux; 786 787 tcp_aux = lnk->data.tcp; 788 if (tcp_aux->state.in != ALIAS_TCP_STATE_CONNECTED 789 || tcp_aux->state.out != ALIAS_TCP_STATE_CONNECTED) { 790 DeleteLink(lnk); 791 icount++; 792 } 793 } 794 break; 795 default: 796 if (idelta > lnk->expire_time) { 797 DeleteLink(lnk); 798 icount++; 799 } 800 break; 801 } 802 lnk = link_next; 803 } 804 805 if (la->cleanupIndex == LINK_TABLE_OUT_SIZE) 806 la->cleanupIndex = 0; 807} 808 809static void 810DeleteLink(struct alias_link *lnk) 811{ 812 struct libalias *la = lnk->la; 813 814/* Don't do anything if the link is marked permanent */ 815 if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT) 816 return; 817 818#ifndef NO_FW_PUNCH 819/* Delete associated firewall hole, if any */ 820 ClearFWHole(lnk); 821#endif 822 823/* Free memory allocated for LSNAT server pool */ 824 if (lnk->server != NULL) { 825 struct server *head, *curr, *next; 826 827 head = curr = lnk->server; 828 do { 829 next = curr->next; 830 free(curr); 831 } while ((curr = next) != head); 832 } 833/* Adjust output table pointers */ 834 LIST_REMOVE(lnk, list_out); 835 836/* Adjust input table pointers */ 837 LIST_REMOVE(lnk, list_in); 838 839/* Close socket, if one has been allocated */ 840 if (lnk->sockfd != -1) { 841 la->sockCount--; 842 close(lnk->sockfd); 843 } 844/* Link-type dependent cleanup */ 845 switch (lnk->link_type) { 846 case LINK_ICMP: 847 la->icmpLinkCount--; 848 break; 849 case LINK_UDP: 850 la->udpLinkCount--; 851 break; 852 case LINK_TCP: 853 la->tcpLinkCount--; 854 free(lnk->data.tcp); 855 break; 856 case LINK_PPTP: 857 la->pptpLinkCount--; 858 break; 859 case LINK_FRAGMENT_ID: 860 la->fragmentIdLinkCount--; 861 break; 862 case LINK_FRAGMENT_PTR: 863 la->fragmentPtrLinkCount--; 864 if (lnk->data.frag_ptr != NULL) 865 free(lnk->data.frag_ptr); 866 break; 867 case LINK_ADDR: 868 break; 869 default: 870 la->protoLinkCount--; 871 break; 872 } 873 874/* Free memory */ 875 free(lnk); 876 877/* Write statistics, if logging enabled */ 878 if (la->packetAliasMode & PKT_ALIAS_LOG) { 879 ShowAliasStats(la); 880 } 881} 882 883 884static struct alias_link * 885AddLink(struct libalias *la, struct in_addr src_addr, 886 struct in_addr dst_addr, 887 struct in_addr alias_addr, 888 u_short src_port, 889 u_short dst_port, 890 int alias_port_param, /* if less than zero, alias */ 891 int link_type) 892{ /* port will be automatically *//* chosen. 893 * If greater than */ 894 u_int start_point; /* zero, equal to alias port */ 895 struct alias_link *lnk; 896 897 lnk = malloc(sizeof(struct alias_link)); 898 if (lnk != NULL) { 899 /* Basic initialization */ 900 lnk->la = la; 901 lnk->src_addr = src_addr; 902 lnk->dst_addr = dst_addr; 903 lnk->alias_addr = alias_addr; 904 lnk->proxy_addr.s_addr = INADDR_ANY; 905 lnk->src_port = src_port; 906 lnk->dst_port = dst_port; 907 lnk->proxy_port = 0; 908 lnk->server = NULL; 909 lnk->link_type = link_type; 910 lnk->sockfd = -1; 911 lnk->flags = 0; 912 lnk->pflags = 0; 913 lnk->timestamp = la->timeStamp; 914 915 /* Expiration time */ 916 switch (link_type) { 917 case LINK_ICMP: 918 lnk->expire_time = ICMP_EXPIRE_TIME; 919 break; 920 case LINK_UDP: 921 lnk->expire_time = UDP_EXPIRE_TIME; 922 break; 923 case LINK_TCP: 924 lnk->expire_time = TCP_EXPIRE_INITIAL; 925 break; 926 case LINK_PPTP: 927 lnk->flags |= LINK_PERMANENT; /* no timeout. */ 928 break; 929 case LINK_FRAGMENT_ID: 930 lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME; 931 break; 932 case LINK_FRAGMENT_PTR: 933 lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME; 934 break; 935 case LINK_ADDR: 936 break; 937 default: 938 lnk->expire_time = PROTO_EXPIRE_TIME; 939 break; 940 } 941 942 /* Determine alias flags */ 943 if (dst_addr.s_addr == INADDR_ANY) 944 lnk->flags |= LINK_UNKNOWN_DEST_ADDR; 945 if (dst_port == 0) 946 lnk->flags |= LINK_UNKNOWN_DEST_PORT; 947 948 /* Determine alias port */ 949 if (GetNewPort(la, lnk, alias_port_param) != 0) { 950 free(lnk); 951 return (NULL); 952 } 953 /* Link-type dependent initialization */ 954 switch (link_type) { 955 struct tcp_dat *aux_tcp; 956 957 case LINK_ICMP: 958 la->icmpLinkCount++; 959 break; 960 case LINK_UDP: 961 la->udpLinkCount++; 962 break; 963 case LINK_TCP: 964 aux_tcp = malloc(sizeof(struct tcp_dat)); 965 if (aux_tcp != NULL) { 966 int i; 967 968 la->tcpLinkCount++; 969 aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED; 970 aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED; 971 aux_tcp->state.index = 0; 972 aux_tcp->state.ack_modified = 0; 973 for (i = 0; i < N_LINK_TCP_DATA; i++) 974 aux_tcp->ack[i].active = 0; 975 aux_tcp->fwhole = -1; 976 lnk->data.tcp = aux_tcp; 977 } else { 978#ifdef DEBUG 979 fprintf(stderr, "PacketAlias/AddLink: "); 980 fprintf(stderr, " cannot allocate auxiliary TCP data\n"); 981#endif 982 free(lnk); 983 return (NULL); 984 } 985 break; 986 case LINK_PPTP: 987 la->pptpLinkCount++; 988 break; 989 case LINK_FRAGMENT_ID: 990 la->fragmentIdLinkCount++; 991 break; 992 case LINK_FRAGMENT_PTR: 993 la->fragmentPtrLinkCount++; 994 break; 995 case LINK_ADDR: 996 break; 997 default: 998 la->protoLinkCount++; 999 break; 1000 } 1001 1002 /* Set up pointers for output lookup table */ 1003 start_point = StartPointOut(src_addr, dst_addr, 1004 src_port, dst_port, link_type); 1005 LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out); 1006 1007 /* Set up pointers for input lookup table */ 1008 start_point = StartPointIn(alias_addr, lnk->alias_port, link_type); 1009 LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in); 1010 } else { 1011#ifdef DEBUG 1012 fprintf(stderr, "PacketAlias/AddLink(): "); 1013 fprintf(stderr, "malloc() call failed.\n"); 1014#endif 1015 } 1016 1017 if (la->packetAliasMode & PKT_ALIAS_LOG) { 1018 ShowAliasStats(la); 1019 } 1020 return (lnk); 1021} 1022 1023static struct alias_link * 1024ReLink(struct alias_link *old_lnk, 1025 struct in_addr src_addr, 1026 struct in_addr dst_addr, 1027 struct in_addr alias_addr, 1028 u_short src_port, 1029 u_short dst_port, 1030 int alias_port_param, /* if less than zero, alias */ 1031 int link_type) 1032{ /* port will be automatically *//* chosen. 1033 * If greater than */ 1034 struct alias_link *new_lnk; /* zero, equal to alias port */ 1035 struct libalias *la = old_lnk->la; 1036 1037 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1038 src_port, dst_port, alias_port_param, 1039 link_type); 1040#ifndef NO_FW_PUNCH 1041 if (new_lnk != NULL && 1042 old_lnk->link_type == LINK_TCP && 1043 old_lnk->data.tcp->fwhole > 0) { 1044 PunchFWHole(new_lnk); 1045 } 1046#endif 1047 DeleteLink(old_lnk); 1048 return (new_lnk); 1049} 1050 1051static struct alias_link * 1052_FindLinkOut(struct libalias *la, struct in_addr src_addr, 1053 struct in_addr dst_addr, 1054 u_short src_port, 1055 u_short dst_port, 1056 int link_type, 1057 int replace_partial_links) 1058{ 1059 u_int i; 1060 struct alias_link *lnk; 1061 1062 i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type); 1063 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) { 1064 if (lnk->src_addr.s_addr == src_addr.s_addr 1065 && lnk->server == NULL 1066 && lnk->dst_addr.s_addr == dst_addr.s_addr 1067 && lnk->dst_port == dst_port 1068 && lnk->src_port == src_port 1069 && lnk->link_type == link_type) { 1070 lnk->timestamp = la->timeStamp; 1071 break; 1072 } 1073 } 1074 1075/* Search for partially specified links. */ 1076 if (lnk == NULL && replace_partial_links) { 1077 if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) { 1078 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0, 1079 link_type, 0); 1080 if (lnk == NULL) 1081 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 1082 dst_port, link_type, 0); 1083 } 1084 if (lnk == NULL && 1085 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) { 1086 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0, 1087 link_type, 0); 1088 } 1089 if (lnk != NULL) { 1090 lnk = ReLink(lnk, 1091 src_addr, dst_addr, lnk->alias_addr, 1092 src_port, dst_port, lnk->alias_port, 1093 link_type); 1094 } 1095 } 1096 return (lnk); 1097} 1098 1099static struct alias_link * 1100FindLinkOut(struct libalias *la, struct in_addr src_addr, 1101 struct in_addr dst_addr, 1102 u_short src_port, 1103 u_short dst_port, 1104 int link_type, 1105 int replace_partial_links) 1106{ 1107 struct alias_link *lnk; 1108 1109 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, 1110 link_type, replace_partial_links); 1111 1112 if (lnk == NULL) { 1113 /* 1114 * The following allows permanent links to be specified as 1115 * using the default source address (i.e. device interface 1116 * address) without knowing in advance what that address 1117 * is. 1118 */ 1119 if (la->aliasAddress.s_addr != INADDR_ANY && 1120 src_addr.s_addr == la->aliasAddress.s_addr) { 1121 lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port, 1122 link_type, replace_partial_links); 1123 } 1124 } 1125 return (lnk); 1126} 1127 1128 1129static struct alias_link * 1130_FindLinkIn(struct libalias *la, struct in_addr dst_addr, 1131 struct in_addr alias_addr, 1132 u_short dst_port, 1133 u_short alias_port, 1134 int link_type, 1135 int replace_partial_links) 1136{ 1137 int flags_in; 1138 u_int start_point; 1139 struct alias_link *lnk; 1140 struct alias_link *lnk_fully_specified; 1141 struct alias_link *lnk_unknown_all; 1142 struct alias_link *lnk_unknown_dst_addr; 1143 struct alias_link *lnk_unknown_dst_port; 1144 1145/* Initialize pointers */ 1146 lnk_fully_specified = NULL; 1147 lnk_unknown_all = NULL; 1148 lnk_unknown_dst_addr = NULL; 1149 lnk_unknown_dst_port = NULL; 1150 1151/* If either the dest addr or port is unknown, the search 1152 loop will have to know about this. */ 1153 1154 flags_in = 0; 1155 if (dst_addr.s_addr == INADDR_ANY) 1156 flags_in |= LINK_UNKNOWN_DEST_ADDR; 1157 if (dst_port == 0) 1158 flags_in |= LINK_UNKNOWN_DEST_PORT; 1159 1160/* Search loop */ 1161 start_point = StartPointIn(alias_addr, alias_port, link_type); 1162 LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) { 1163 int flags; 1164 1165 flags = flags_in | lnk->flags; 1166 if (!(flags & LINK_PARTIALLY_SPECIFIED)) { 1167 if (lnk->alias_addr.s_addr == alias_addr.s_addr 1168 && lnk->alias_port == alias_port 1169 && lnk->dst_addr.s_addr == dst_addr.s_addr 1170 && lnk->dst_port == dst_port 1171 && lnk->link_type == link_type) { 1172 lnk_fully_specified = lnk; 1173 break; 1174 } 1175 } else if ((flags & LINK_UNKNOWN_DEST_ADDR) 1176 && (flags & LINK_UNKNOWN_DEST_PORT)) { 1177 if (lnk->alias_addr.s_addr == alias_addr.s_addr 1178 && lnk->alias_port == alias_port 1179 && lnk->link_type == link_type) { 1180 if (lnk_unknown_all == NULL) 1181 lnk_unknown_all = lnk; 1182 } 1183 } else if (flags & LINK_UNKNOWN_DEST_ADDR) { 1184 if (lnk->alias_addr.s_addr == alias_addr.s_addr 1185 && lnk->alias_port == alias_port 1186 && lnk->link_type == link_type 1187 && lnk->dst_port == dst_port) { 1188 if (lnk_unknown_dst_addr == NULL) 1189 lnk_unknown_dst_addr = lnk; 1190 } 1191 } else if (flags & LINK_UNKNOWN_DEST_PORT) { 1192 if (lnk->alias_addr.s_addr == alias_addr.s_addr 1193 && lnk->alias_port == alias_port 1194 && lnk->link_type == link_type 1195 && lnk->dst_addr.s_addr == dst_addr.s_addr) { 1196 if (lnk_unknown_dst_port == NULL) 1197 lnk_unknown_dst_port = lnk; 1198 } 1199 } 1200 } 1201 1202 1203 1204 if (lnk_fully_specified != NULL) { 1205 lnk_fully_specified->timestamp = la->timeStamp; 1206 lnk = lnk_fully_specified; 1207 } else if (lnk_unknown_dst_port != NULL) 1208 lnk = lnk_unknown_dst_port; 1209 else if (lnk_unknown_dst_addr != NULL) 1210 lnk = lnk_unknown_dst_addr; 1211 else if (lnk_unknown_all != NULL) 1212 lnk = lnk_unknown_all; 1213 else 1214 return (NULL); 1215 1216 if (replace_partial_links && 1217 (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) { 1218 struct in_addr src_addr; 1219 u_short src_port; 1220 1221 if (lnk->server != NULL) { /* LSNAT link */ 1222 src_addr = lnk->server->addr; 1223 src_port = lnk->server->port; 1224 lnk->server = lnk->server->next; 1225 } else { 1226 src_addr = lnk->src_addr; 1227 src_port = lnk->src_port; 1228 } 1229 1230 lnk = ReLink(lnk, 1231 src_addr, dst_addr, alias_addr, 1232 src_port, dst_port, alias_port, 1233 link_type); 1234 } 1235 return (lnk); 1236} 1237 1238static struct alias_link * 1239FindLinkIn(struct libalias *la, struct in_addr dst_addr, 1240 struct in_addr alias_addr, 1241 u_short dst_port, 1242 u_short alias_port, 1243 int link_type, 1244 int replace_partial_links) 1245{ 1246 struct alias_link *lnk; 1247 1248 lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port, 1249 link_type, replace_partial_links); 1250 1251 if (lnk == NULL) { 1252 /* 1253 * The following allows permanent links to be specified as 1254 * using the default aliasing address (i.e. device 1255 * interface address) without knowing in advance what that 1256 * address is. 1257 */ 1258 if (la->aliasAddress.s_addr != INADDR_ANY && 1259 alias_addr.s_addr == la->aliasAddress.s_addr) { 1260 lnk = _FindLinkIn(la, dst_addr, la->nullAddress, dst_port, alias_port, 1261 link_type, replace_partial_links); 1262 } 1263 } 1264 return (lnk); 1265} 1266 1267 1268 1269 1270/* External routines for finding/adding links 1271 1272-- "external" means outside alias_db.c, but within alias*.c -- 1273 1274 FindIcmpIn(), FindIcmpOut() 1275 FindFragmentIn1(), FindFragmentIn2() 1276 AddFragmentPtrLink(), FindFragmentPtr() 1277 FindProtoIn(), FindProtoOut() 1278 FindUdpTcpIn(), FindUdpTcpOut() 1279 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(), 1280 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId() 1281 FindOriginalAddress(), FindAliasAddress() 1282 1283(prototypes in alias_local.h) 1284*/ 1285 1286 1287struct alias_link * 1288FindIcmpIn(struct libalias *la, struct in_addr dst_addr, 1289 struct in_addr alias_addr, 1290 u_short id_alias, 1291 int create) 1292{ 1293 struct alias_link *lnk; 1294 1295 lnk = FindLinkIn(la, dst_addr, alias_addr, 1296 NO_DEST_PORT, id_alias, 1297 LINK_ICMP, 0); 1298 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { 1299 struct in_addr target_addr; 1300 1301 target_addr = FindOriginalAddress(la, alias_addr); 1302 lnk = AddLink(la, target_addr, dst_addr, alias_addr, 1303 id_alias, NO_DEST_PORT, id_alias, 1304 LINK_ICMP); 1305 } 1306 return (lnk); 1307} 1308 1309 1310struct alias_link * 1311FindIcmpOut(struct libalias *la, struct in_addr src_addr, 1312 struct in_addr dst_addr, 1313 u_short id, 1314 int create) 1315{ 1316 struct alias_link *lnk; 1317 1318 lnk = FindLinkOut(la, src_addr, dst_addr, 1319 id, NO_DEST_PORT, 1320 LINK_ICMP, 0); 1321 if (lnk == NULL && create) { 1322 struct in_addr alias_addr; 1323 1324 alias_addr = FindAliasAddress(la, src_addr); 1325 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1326 id, NO_DEST_PORT, GET_ALIAS_ID, 1327 LINK_ICMP); 1328 } 1329 return (lnk); 1330} 1331 1332 1333struct alias_link * 1334FindFragmentIn1(struct libalias *la, struct in_addr dst_addr, 1335 struct in_addr alias_addr, 1336 u_short ip_id) 1337{ 1338 struct alias_link *lnk; 1339 1340 lnk = FindLinkIn(la, dst_addr, alias_addr, 1341 NO_DEST_PORT, ip_id, 1342 LINK_FRAGMENT_ID, 0); 1343 1344 if (lnk == NULL) { 1345 lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr, 1346 NO_SRC_PORT, NO_DEST_PORT, ip_id, 1347 LINK_FRAGMENT_ID); 1348 } 1349 return (lnk); 1350} 1351 1352 1353struct alias_link * 1354FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if 1355 * one */ 1356 struct in_addr alias_addr, /* is not found. */ 1357 u_short ip_id) 1358{ 1359 return FindLinkIn(la, dst_addr, alias_addr, 1360 NO_DEST_PORT, ip_id, 1361 LINK_FRAGMENT_ID, 0); 1362} 1363 1364 1365struct alias_link * 1366AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr, 1367 u_short ip_id) 1368{ 1369 return AddLink(la, la->nullAddress, dst_addr, la->nullAddress, 1370 NO_SRC_PORT, NO_DEST_PORT, ip_id, 1371 LINK_FRAGMENT_PTR); 1372} 1373 1374 1375struct alias_link * 1376FindFragmentPtr(struct libalias *la, struct in_addr dst_addr, 1377 u_short ip_id) 1378{ 1379 return FindLinkIn(la, dst_addr, la->nullAddress, 1380 NO_DEST_PORT, ip_id, 1381 LINK_FRAGMENT_PTR, 0); 1382} 1383 1384 1385struct alias_link * 1386FindProtoIn(struct libalias *la, struct in_addr dst_addr, 1387 struct in_addr alias_addr, 1388 u_char proto) 1389{ 1390 struct alias_link *lnk; 1391 1392 lnk = FindLinkIn(la, dst_addr, alias_addr, 1393 NO_DEST_PORT, 0, 1394 proto, 1); 1395 1396 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { 1397 struct in_addr target_addr; 1398 1399 target_addr = FindOriginalAddress(la, alias_addr); 1400 lnk = AddLink(la, target_addr, dst_addr, alias_addr, 1401 NO_SRC_PORT, NO_DEST_PORT, 0, 1402 proto); 1403 } 1404 return (lnk); 1405} 1406 1407 1408struct alias_link * 1409FindProtoOut(struct libalias *la, struct in_addr src_addr, 1410 struct in_addr dst_addr, 1411 u_char proto) 1412{ 1413 struct alias_link *lnk; 1414 1415 lnk = FindLinkOut(la, src_addr, dst_addr, 1416 NO_SRC_PORT, NO_DEST_PORT, 1417 proto, 1); 1418 1419 if (lnk == NULL) { 1420 struct in_addr alias_addr; 1421 1422 alias_addr = FindAliasAddress(la, src_addr); 1423 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1424 NO_SRC_PORT, NO_DEST_PORT, 0, 1425 proto); 1426 } 1427 return (lnk); 1428} 1429 1430 1431struct alias_link * 1432FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr, 1433 struct in_addr alias_addr, 1434 u_short dst_port, 1435 u_short alias_port, 1436 u_char proto, 1437 int create) 1438{ 1439 int link_type; 1440 struct alias_link *lnk; 1441 1442 switch (proto) { 1443 case IPPROTO_UDP: 1444 link_type = LINK_UDP; 1445 break; 1446 case IPPROTO_TCP: 1447 link_type = LINK_TCP; 1448 break; 1449 default: 1450 return (NULL); 1451 break; 1452 } 1453 1454 lnk = FindLinkIn(la, dst_addr, alias_addr, 1455 dst_port, alias_port, 1456 link_type, create); 1457 1458 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { 1459 struct in_addr target_addr; 1460 1461 target_addr = FindOriginalAddress(la, alias_addr); 1462 lnk = AddLink(la, target_addr, dst_addr, alias_addr, 1463 alias_port, dst_port, alias_port, 1464 link_type); 1465 } 1466 return (lnk); 1467} 1468 1469 1470struct alias_link * 1471FindUdpTcpOut(struct libalias *la, struct in_addr src_addr, 1472 struct in_addr dst_addr, 1473 u_short src_port, 1474 u_short dst_port, 1475 u_char proto, 1476 int create) 1477{ 1478 int link_type; 1479 struct alias_link *lnk; 1480 1481 switch (proto) { 1482 case IPPROTO_UDP: 1483 link_type = LINK_UDP; 1484 break; 1485 case IPPROTO_TCP: 1486 link_type = LINK_TCP; 1487 break; 1488 default: 1489 return (NULL); 1490 break; 1491 } 1492 1493 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create); 1494 1495 if (lnk == NULL && create) { 1496 struct in_addr alias_addr; 1497 1498 alias_addr = FindAliasAddress(la, src_addr); 1499 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1500 src_port, dst_port, GET_ALIAS_PORT, 1501 link_type); 1502 } 1503 return (lnk); 1504} 1505 1506 1507struct alias_link * 1508AddPptp(struct libalias *la, struct in_addr src_addr, 1509 struct in_addr dst_addr, 1510 struct in_addr alias_addr, 1511 u_int16_t src_call_id) 1512{ 1513 struct alias_link *lnk; 1514 1515 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1516 src_call_id, 0, GET_ALIAS_PORT, 1517 LINK_PPTP); 1518 1519 return (lnk); 1520} 1521 1522 1523struct alias_link * 1524FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr, 1525 struct in_addr dst_addr, 1526 u_int16_t src_call_id) 1527{ 1528 u_int i; 1529 struct alias_link *lnk; 1530 1531 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); 1532 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) 1533 if (lnk->link_type == LINK_PPTP && 1534 lnk->src_addr.s_addr == src_addr.s_addr && 1535 lnk->dst_addr.s_addr == dst_addr.s_addr && 1536 lnk->src_port == src_call_id) 1537 break; 1538 1539 return (lnk); 1540} 1541 1542 1543struct alias_link * 1544FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr, 1545 struct in_addr dst_addr, 1546 u_int16_t dst_call_id) 1547{ 1548 u_int i; 1549 struct alias_link *lnk; 1550 1551 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); 1552 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) 1553 if (lnk->link_type == LINK_PPTP && 1554 lnk->src_addr.s_addr == src_addr.s_addr && 1555 lnk->dst_addr.s_addr == dst_addr.s_addr && 1556 lnk->dst_port == dst_call_id) 1557 break; 1558 1559 return (lnk); 1560} 1561 1562 1563struct alias_link * 1564FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr, 1565 struct in_addr alias_addr, 1566 u_int16_t dst_call_id) 1567{ 1568 u_int i; 1569 struct alias_link *lnk; 1570 1571 i = StartPointIn(alias_addr, 0, LINK_PPTP); 1572 LIST_FOREACH(lnk, &la->linkTableIn[i], list_in) 1573 if (lnk->link_type == LINK_PPTP && 1574 lnk->dst_addr.s_addr == dst_addr.s_addr && 1575 lnk->alias_addr.s_addr == alias_addr.s_addr && 1576 lnk->dst_port == dst_call_id) 1577 break; 1578 1579 return (lnk); 1580} 1581 1582 1583struct alias_link * 1584FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr, 1585 struct in_addr alias_addr, 1586 u_int16_t alias_call_id) 1587{ 1588 struct alias_link *lnk; 1589 1590 lnk = FindLinkIn(la, dst_addr, alias_addr, 1591 0 /* any */ , alias_call_id, 1592 LINK_PPTP, 0); 1593 1594 1595 return (lnk); 1596} 1597 1598 1599struct alias_link * 1600FindRtspOut(struct libalias *la, struct in_addr src_addr, 1601 struct in_addr dst_addr, 1602 u_short src_port, 1603 u_short alias_port, 1604 u_char proto) 1605{ 1606 int link_type; 1607 struct alias_link *lnk; 1608 1609 switch (proto) { 1610 case IPPROTO_UDP: 1611 link_type = LINK_UDP; 1612 break; 1613 case IPPROTO_TCP: 1614 link_type = LINK_TCP; 1615 break; 1616 default: 1617 return (NULL); 1618 break; 1619 } 1620 1621 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1); 1622 1623 if (lnk == NULL) { 1624 struct in_addr alias_addr; 1625 1626 alias_addr = FindAliasAddress(la, src_addr); 1627 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 1628 src_port, 0, alias_port, 1629 link_type); 1630 } 1631 return (lnk); 1632} 1633 1634 1635struct in_addr 1636FindOriginalAddress(struct libalias *la, struct in_addr alias_addr) 1637{ 1638 struct alias_link *lnk; 1639 1640 lnk = FindLinkIn(la, la->nullAddress, alias_addr, 1641 0, 0, LINK_ADDR, 0); 1642 if (lnk == NULL) { 1643 la->newDefaultLink = 1; 1644 if (la->targetAddress.s_addr == INADDR_ANY) 1645 return (alias_addr); 1646 else if (la->targetAddress.s_addr == INADDR_NONE) 1647 return (la->aliasAddress.s_addr != INADDR_ANY) ? 1648 la->aliasAddress : alias_addr; 1649 else 1650 return (la->targetAddress); 1651 } else { 1652 if (lnk->server != NULL) { /* LSNAT link */ 1653 struct in_addr src_addr; 1654 1655 src_addr = lnk->server->addr; 1656 lnk->server = lnk->server->next; 1657 return (src_addr); 1658 } else if (lnk->src_addr.s_addr == INADDR_ANY) 1659 return (la->aliasAddress.s_addr != INADDR_ANY) ? 1660 la->aliasAddress : alias_addr; 1661 else 1662 return (lnk->src_addr); 1663 } 1664} 1665 1666 1667struct in_addr 1668FindAliasAddress(struct libalias *la, struct in_addr original_addr) 1669{ 1670 struct alias_link *lnk; 1671 1672 lnk = FindLinkOut(la, original_addr, la->nullAddress, 1673 0, 0, LINK_ADDR, 0); 1674 if (lnk == NULL) { 1675 return (la->aliasAddress.s_addr != INADDR_ANY) ? 1676 la->aliasAddress : original_addr; 1677 } else { 1678 if (lnk->alias_addr.s_addr == INADDR_ANY) 1679 return (la->aliasAddress.s_addr != INADDR_ANY) ? 1680 la->aliasAddress : original_addr; 1681 else 1682 return (lnk->alias_addr); 1683 } 1684} 1685 1686 1687/* External routines for getting or changing link data 1688 (external to alias_db.c, but internal to alias*.c) 1689 1690 SetFragmentData(), GetFragmentData() 1691 SetFragmentPtr(), GetFragmentPtr() 1692 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut() 1693 GetOriginalAddress(), GetDestAddress(), GetAliasAddress() 1694 GetOriginalPort(), GetAliasPort() 1695 SetAckModified(), GetAckModified() 1696 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq() 1697 SetProtocolFlags(), GetProtocolFlags() 1698 SetDestCallId() 1699*/ 1700 1701 1702void 1703SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr) 1704{ 1705 lnk->data.frag_addr = src_addr; 1706} 1707 1708 1709void 1710GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr) 1711{ 1712 *src_addr = lnk->data.frag_addr; 1713} 1714 1715 1716void 1717SetFragmentPtr(struct alias_link *lnk, char *fptr) 1718{ 1719 lnk->data.frag_ptr = fptr; 1720} 1721 1722 1723void 1724GetFragmentPtr(struct alias_link *lnk, char **fptr) 1725{ 1726 *fptr = lnk->data.frag_ptr; 1727} 1728 1729 1730void 1731SetStateIn(struct alias_link *lnk, int state) 1732{ 1733 /* TCP input state */ 1734 switch (state) { 1735 case ALIAS_TCP_STATE_DISCONNECTED: 1736 if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED) 1737 lnk->expire_time = TCP_EXPIRE_DEAD; 1738 else 1739 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD; 1740 break; 1741 case ALIAS_TCP_STATE_CONNECTED: 1742 if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED) 1743 lnk->expire_time = TCP_EXPIRE_CONNECTED; 1744 break; 1745 default: 1746 abort(); 1747 } 1748 lnk->data.tcp->state.in = state; 1749} 1750 1751 1752void 1753SetStateOut(struct alias_link *lnk, int state) 1754{ 1755 /* TCP output state */ 1756 switch (state) { 1757 case ALIAS_TCP_STATE_DISCONNECTED: 1758 if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED) 1759 lnk->expire_time = TCP_EXPIRE_DEAD; 1760 else 1761 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD; 1762 break; 1763 case ALIAS_TCP_STATE_CONNECTED: 1764 if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED) 1765 lnk->expire_time = TCP_EXPIRE_CONNECTED; 1766 break; 1767 default: 1768 abort(); 1769 } 1770 lnk->data.tcp->state.out = state; 1771} 1772 1773 1774int 1775GetStateIn(struct alias_link *lnk) 1776{ 1777 /* TCP input state */ 1778 return (lnk->data.tcp->state.in); 1779} 1780 1781 1782int 1783GetStateOut(struct alias_link *lnk) 1784{ 1785 /* TCP output state */ 1786 return (lnk->data.tcp->state.out); 1787} 1788 1789 1790struct in_addr 1791GetOriginalAddress(struct alias_link *lnk) 1792{ 1793 if (lnk->src_addr.s_addr == INADDR_ANY) 1794 return (lnk->la->aliasAddress); 1795 else 1796 return (lnk->src_addr); 1797} 1798 1799 1800struct in_addr 1801GetDestAddress(struct alias_link *lnk) 1802{ 1803 return (lnk->dst_addr); 1804} 1805 1806 1807struct in_addr 1808GetAliasAddress(struct alias_link *lnk) 1809{ 1810 if (lnk->alias_addr.s_addr == INADDR_ANY) 1811 return (lnk->la->aliasAddress); 1812 else 1813 return (lnk->alias_addr); 1814} 1815 1816 1817struct in_addr 1818GetDefaultAliasAddress(struct libalias *la) 1819{ 1820 return (la->aliasAddress); 1821} 1822 1823 1824void 1825SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr) 1826{ 1827 la->aliasAddress = alias_addr; 1828} 1829 1830 1831u_short 1832GetOriginalPort(struct alias_link *lnk) 1833{ 1834 return (lnk->src_port); 1835} 1836 1837 1838u_short 1839GetAliasPort(struct alias_link *lnk) 1840{ 1841 return (lnk->alias_port); 1842} 1843 1844#ifndef NO_FW_PUNCH 1845static u_short 1846GetDestPort(struct alias_link *lnk) 1847{ 1848 return (lnk->dst_port); 1849} 1850 1851#endif 1852 1853void 1854SetAckModified(struct alias_link *lnk) 1855{ 1856/* Indicate that ACK numbers have been modified in a TCP connection */ 1857 lnk->data.tcp->state.ack_modified = 1; 1858} 1859 1860 1861struct in_addr 1862GetProxyAddress(struct alias_link *lnk) 1863{ 1864 return (lnk->proxy_addr); 1865} 1866 1867 1868void 1869SetProxyAddress(struct alias_link *lnk, struct in_addr addr) 1870{ 1871 lnk->proxy_addr = addr; 1872} 1873 1874 1875u_short 1876GetProxyPort(struct alias_link *lnk) 1877{ 1878 return (lnk->proxy_port); 1879} 1880 1881 1882void 1883SetProxyPort(struct alias_link *lnk, u_short port) 1884{ 1885 lnk->proxy_port = port; 1886} 1887 1888 1889int 1890GetAckModified(struct alias_link *lnk) 1891{ 1892/* See if ACK numbers have been modified */ 1893 return (lnk->data.tcp->state.ack_modified); 1894} 1895 1896 1897int 1898GetDeltaAckIn(struct ip *pip, struct alias_link *lnk) 1899{ 1900/* 1901Find out how much the ACK number has been altered for an incoming 1902TCP packet. To do this, a circular list of ACK numbers where the TCP 1903packet size was altered is searched. 1904*/ 1905 1906 int i; 1907 struct tcphdr *tc; 1908 int delta, ack_diff_min; 1909 u_long ack; 1910 1911 tc = ip_next(pip); 1912 ack = tc->th_ack; 1913 1914 delta = 0; 1915 ack_diff_min = -1; 1916 for (i = 0; i < N_LINK_TCP_DATA; i++) { 1917 struct ack_data_record x; 1918 1919 x = lnk->data.tcp->ack[i]; 1920 if (x.active == 1) { 1921 int ack_diff; 1922 1923 ack_diff = SeqDiff(x.ack_new, ack); 1924 if (ack_diff >= 0) { 1925 if (ack_diff_min >= 0) { 1926 if (ack_diff < ack_diff_min) { 1927 delta = x.delta; 1928 ack_diff_min = ack_diff; 1929 } 1930 } else { 1931 delta = x.delta; 1932 ack_diff_min = ack_diff; 1933 } 1934 } 1935 } 1936 } 1937 return (delta); 1938} 1939 1940 1941int 1942GetDeltaSeqOut(struct ip *pip, struct alias_link *lnk) 1943{ 1944/* 1945Find out how much the sequence number has been altered for an outgoing 1946TCP packet. To do this, a circular list of ACK numbers where the TCP 1947packet size was altered is searched. 1948*/ 1949 1950 int i; 1951 struct tcphdr *tc; 1952 int delta, seq_diff_min; 1953 u_long seq; 1954 1955 tc = ip_next(pip); 1956 seq = tc->th_seq; 1957 1958 delta = 0; 1959 seq_diff_min = -1; 1960 for (i = 0; i < N_LINK_TCP_DATA; i++) { 1961 struct ack_data_record x; 1962 1963 x = lnk->data.tcp->ack[i]; 1964 if (x.active == 1) { 1965 int seq_diff; 1966 1967 seq_diff = SeqDiff(x.ack_old, seq); 1968 if (seq_diff >= 0) { 1969 if (seq_diff_min >= 0) { 1970 if (seq_diff < seq_diff_min) { 1971 delta = x.delta; 1972 seq_diff_min = seq_diff; 1973 } 1974 } else { 1975 delta = x.delta; 1976 seq_diff_min = seq_diff; 1977 } 1978 } 1979 } 1980 } 1981 return (delta); 1982} 1983 1984 1985void 1986AddSeq(struct ip *pip, struct alias_link *lnk, int delta) 1987{ 1988/* 1989When a TCP packet has been altered in length, save this 1990information in a circular list. If enough packets have 1991been altered, then this list will begin to overwrite itself. 1992*/ 1993 1994 struct tcphdr *tc; 1995 struct ack_data_record x; 1996 int hlen, tlen, dlen; 1997 int i; 1998 1999 tc = ip_next(pip); 2000 2001 hlen = (pip->ip_hl + tc->th_off) << 2; 2002 tlen = ntohs(pip->ip_len); 2003 dlen = tlen - hlen; 2004 2005 x.ack_old = htonl(ntohl(tc->th_seq) + dlen); 2006 x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta); 2007 x.delta = delta; 2008 x.active = 1; 2009 2010 i = lnk->data.tcp->state.index; 2011 lnk->data.tcp->ack[i] = x; 2012 2013 i++; 2014 if (i == N_LINK_TCP_DATA) 2015 lnk->data.tcp->state.index = 0; 2016 else 2017 lnk->data.tcp->state.index = i; 2018} 2019 2020void 2021SetExpire(struct alias_link *lnk, int expire) 2022{ 2023 if (expire == 0) { 2024 lnk->flags &= ~LINK_PERMANENT; 2025 DeleteLink(lnk); 2026 } else if (expire == -1) { 2027 lnk->flags |= LINK_PERMANENT; 2028 } else if (expire > 0) { 2029 lnk->expire_time = expire; 2030 } else { 2031#ifdef DEBUG 2032 fprintf(stderr, "PacketAlias/SetExpire(): "); 2033 fprintf(stderr, "error in expire parameter\n"); 2034#endif 2035 } 2036} 2037 2038void 2039ClearCheckNewLink(struct libalias *la) 2040{ 2041 la->newDefaultLink = 0; 2042} 2043 2044void 2045SetProtocolFlags(struct alias_link *lnk, int pflags) 2046{ 2047 2048 lnk->pflags = pflags;; 2049} 2050 2051int 2052GetProtocolFlags(struct alias_link *lnk) 2053{ 2054 2055 return (lnk->pflags); 2056} 2057 2058void 2059SetDestCallId(struct alias_link *lnk, u_int16_t cid) 2060{ 2061 struct libalias *la = lnk->la; 2062 2063 la->deleteAllLinks = 1; 2064 lnk = ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr, 2065 lnk->src_port, cid, lnk->alias_port, lnk->link_type); 2066 la->deleteAllLinks = 0; 2067} 2068 2069 2070/* Miscellaneous Functions 2071 2072 HouseKeeping() 2073 InitPacketAliasLog() 2074 UninitPacketAliasLog() 2075*/ 2076 2077/* 2078 Whenever an outgoing or incoming packet is handled, HouseKeeping() 2079 is called to find and remove timed-out aliasing links. Logic exists 2080 to sweep through the entire table and linked list structure 2081 every 60 seconds. 2082 2083 (prototype in alias_local.h) 2084*/ 2085 2086void 2087HouseKeeping(struct libalias *la) 2088{ 2089 int i, n, n100; 2090 struct timeval tv; 2091 struct timezone tz; 2092 2093 /* 2094 * Save system time (seconds) in global variable timeStamp for use 2095 * by other functions. This is done so as not to unnecessarily 2096 * waste timeline by making system calls. 2097 */ 2098 gettimeofday(&tv, &tz); 2099 la->timeStamp = tv.tv_sec; 2100 2101 /* Compute number of spokes (output table link chains) to cover */ 2102 n100 = LINK_TABLE_OUT_SIZE * 100 + la->houseKeepingResidual; 2103 n100 *= la->timeStamp - la->lastCleanupTime; 2104 n100 /= ALIAS_CLEANUP_INTERVAL_SECS; 2105 2106 n = n100 / 100; 2107 2108 /* Handle different cases */ 2109 if (n > ALIAS_CLEANUP_MAX_SPOKES) { 2110 n = ALIAS_CLEANUP_MAX_SPOKES; 2111 la->lastCleanupTime = la->timeStamp; 2112 la->houseKeepingResidual = 0; 2113 2114 for (i = 0; i < n; i++) 2115 IncrementalCleanup(la); 2116 } else if (n > 0) { 2117 la->lastCleanupTime = la->timeStamp; 2118 la->houseKeepingResidual = n100 - 100 * n; 2119 2120 for (i = 0; i < n; i++) 2121 IncrementalCleanup(la); 2122 } else if (n < 0) { 2123#ifdef DEBUG 2124 fprintf(stderr, "PacketAlias/HouseKeeping(): "); 2125 fprintf(stderr, "something unexpected in time values\n"); 2126#endif 2127 la->lastCleanupTime = la->timeStamp; 2128 la->houseKeepingResidual = 0; 2129 } 2130} 2131 2132 2133/* Init the log file and enable logging */ 2134static void 2135InitPacketAliasLog(struct libalias *la) 2136{ 2137 if ((~la->packetAliasMode & PKT_ALIAS_LOG) 2138 && (la->monitorFile = fopen("/var/log/alias.log", "w"))) { 2139 la->packetAliasMode |= PKT_ALIAS_LOG; 2140 fprintf(la->monitorFile, 2141 "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n"); 2142 } 2143} 2144 2145 2146/* Close the log-file and disable logging. */ 2147static void 2148UninitPacketAliasLog(struct libalias *la) 2149{ 2150 if (la->monitorFile) { 2151 fclose(la->monitorFile); 2152 la->monitorFile = NULL; 2153 } 2154 la->packetAliasMode &= ~PKT_ALIAS_LOG; 2155} 2156 2157 2158 2159 2160 2161 2162/* Outside world interfaces 2163 2164-- "outside world" means other than alias*.c routines -- 2165 2166 PacketAliasRedirectPort() 2167 PacketAliasAddServer() 2168 PacketAliasRedirectProto() 2169 PacketAliasRedirectAddr() 2170 PacketAliasRedirectDynamic() 2171 PacketAliasRedirectDelete() 2172 PacketAliasSetAddress() 2173 PacketAliasInit() 2174 PacketAliasUninit() 2175 PacketAliasSetMode() 2176 2177(prototypes in alias.h) 2178*/ 2179 2180/* Redirection from a specific public addr:port to a 2181 private addr:port */ 2182struct alias_link * 2183LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port, 2184 struct in_addr dst_addr, u_short dst_port, 2185 struct in_addr alias_addr, u_short alias_port, 2186 u_char proto) 2187{ 2188 int link_type; 2189 struct alias_link *lnk; 2190 2191 switch (proto) { 2192 case IPPROTO_UDP: 2193 link_type = LINK_UDP; 2194 break; 2195 case IPPROTO_TCP: 2196 link_type = LINK_TCP; 2197 break; 2198 default: 2199#ifdef DEBUG 2200 fprintf(stderr, "PacketAliasRedirectPort(): "); 2201 fprintf(stderr, "only TCP and UDP protocols allowed\n"); 2202#endif 2203 return (NULL); 2204 } 2205 2206 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 2207 src_port, dst_port, alias_port, 2208 link_type); 2209 2210 if (lnk != NULL) { 2211 lnk->flags |= LINK_PERMANENT; 2212 } 2213#ifdef DEBUG 2214 else { 2215 fprintf(stderr, "PacketAliasRedirectPort(): " 2216 "call to AddLink() failed\n"); 2217 } 2218#endif 2219 2220 return (lnk); 2221} 2222 2223/* Add server to the pool of servers */ 2224int 2225LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port) 2226{ 2227 struct server *server; 2228 2229 (void)la; 2230 2231 server = malloc(sizeof(struct server)); 2232 2233 if (server != NULL) { 2234 struct server *head; 2235 2236 server->addr = addr; 2237 server->port = port; 2238 2239 head = lnk->server; 2240 if (head == NULL) 2241 server->next = server; 2242 else { 2243 struct server *s; 2244 2245 for (s = head; s->next != head; s = s->next); 2246 s->next = server; 2247 server->next = head; 2248 } 2249 lnk->server = server; 2250 return (0); 2251 } else 2252 return (-1); 2253} 2254 2255/* Redirect packets of a given IP protocol from a specific 2256 public address to a private address */ 2257struct alias_link * 2258LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr, 2259 struct in_addr dst_addr, 2260 struct in_addr alias_addr, 2261 u_char proto) 2262{ 2263 struct alias_link *lnk; 2264 2265 lnk = AddLink(la, src_addr, dst_addr, alias_addr, 2266 NO_SRC_PORT, NO_DEST_PORT, 0, 2267 proto); 2268 2269 if (lnk != NULL) { 2270 lnk->flags |= LINK_PERMANENT; 2271 } 2272#ifdef DEBUG 2273 else { 2274 fprintf(stderr, "PacketAliasRedirectProto(): " 2275 "call to AddLink() failed\n"); 2276 } 2277#endif 2278 2279 return (lnk); 2280} 2281 2282/* Static address translation */ 2283struct alias_link * 2284LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr, 2285 struct in_addr alias_addr) 2286{ 2287 struct alias_link *lnk; 2288 2289 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr, 2290 0, 0, 0, 2291 LINK_ADDR); 2292 2293 if (lnk != NULL) { 2294 lnk->flags |= LINK_PERMANENT; 2295 } 2296#ifdef DEBUG 2297 else { 2298 fprintf(stderr, "PacketAliasRedirectAddr(): " 2299 "call to AddLink() failed\n"); 2300 } 2301#endif 2302 2303 return (lnk); 2304} 2305 2306 2307/* Mark the aliasing link dynamic */ 2308int 2309LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk) 2310{ 2311 2312 (void)la; 2313 2314 if (lnk->flags & LINK_PARTIALLY_SPECIFIED) 2315 return (-1); 2316 else { 2317 lnk->flags &= ~LINK_PERMANENT; 2318 return (0); 2319 } 2320} 2321 2322 2323void 2324LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk) 2325{ 2326/* This is a dangerous function to put in the API, 2327 because an invalid pointer can crash the program. */ 2328 2329 la->deleteAllLinks = 1; 2330 DeleteLink(lnk); 2331 la->deleteAllLinks = 0; 2332} 2333 2334 2335void 2336LibAliasSetAddress(struct libalias *la, struct in_addr addr) 2337{ 2338 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE 2339 && la->aliasAddress.s_addr != addr.s_addr) 2340 CleanupAliasData(la); 2341 2342 la->aliasAddress = addr; 2343} 2344 2345 2346void 2347LibAliasSetTarget(struct libalias *la, struct in_addr target_addr) 2348{ 2349 la->targetAddress = target_addr; 2350} 2351 2352static void 2353finishoff(void) 2354{ 2355 2356 while (!LIST_EMPTY(&instancehead)) 2357 LibAliasUninit(LIST_FIRST(&instancehead)); 2358} 2359 2360struct libalias * 2361LibAliasInit(struct libalias *la) 2362{ 2363 int i; 2364 struct timeval tv; 2365 struct timezone tz; 2366 2367 if (la == NULL) { 2368 la = calloc(sizeof *la, 1); 2369 if (la == NULL) 2370 return (la); 2371 if (LIST_EMPTY(&instancehead)) 2372 atexit(finishoff); 2373 LIST_INSERT_HEAD(&instancehead, la, instancelist); 2374 2375 gettimeofday(&tv, &tz); 2376 la->timeStamp = tv.tv_sec; 2377 la->lastCleanupTime = tv.tv_sec; 2378 la->houseKeepingResidual = 0; 2379 2380 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) 2381 LIST_INIT(&la->linkTableOut[i]); 2382 for (i = 0; i < LINK_TABLE_IN_SIZE; i++) 2383 LIST_INIT(&la->linkTableIn[i]); 2384 2385 } else { 2386 la->deleteAllLinks = 1; 2387 CleanupAliasData(la); 2388 la->deleteAllLinks = 0; 2389 } 2390 2391 la->aliasAddress.s_addr = INADDR_ANY; 2392 la->targetAddress.s_addr = INADDR_ANY; 2393 2394 la->icmpLinkCount = 0; 2395 la->udpLinkCount = 0; 2396 la->tcpLinkCount = 0; 2397 la->pptpLinkCount = 0; 2398 la->protoLinkCount = 0; 2399 la->fragmentIdLinkCount = 0; 2400 la->fragmentPtrLinkCount = 0; 2401 la->sockCount = 0; 2402 2403 la->cleanupIndex = 0; 2404 2405 la->packetAliasMode = PKT_ALIAS_SAME_PORTS 2406 | PKT_ALIAS_USE_SOCKETS 2407 | PKT_ALIAS_RESET_ON_ADDR_CHANGE; 2408#ifndef NO_FW_PUNCH 2409 la->fireWallFD = -1; 2410#endif 2411 return (la); 2412} 2413 2414void 2415LibAliasUninit(struct libalias *la) 2416{ 2417 la->deleteAllLinks = 1; 2418 CleanupAliasData(la); 2419 la->deleteAllLinks = 0; 2420 UninitPacketAliasLog(la); 2421#ifndef NO_FW_PUNCH 2422 UninitPunchFW(la); 2423#endif 2424 LIST_REMOVE(la, instancelist); 2425 free(la); 2426} 2427 2428/* Change mode for some operations */ 2429unsigned int 2430LibAliasSetMode( 2431 struct libalias *la, 2432 unsigned int flags, /* Which state to bring flags to */ 2433 unsigned int mask /* Mask of which flags to affect (use 0 to 2434 * do a probe for flag values) */ 2435) 2436{ 2437/* Enable logging? */ 2438 if (flags & mask & PKT_ALIAS_LOG) { 2439 InitPacketAliasLog(la); /* Do the enable */ 2440 } else 2441/* _Disable_ logging? */ 2442 if (~flags & mask & PKT_ALIAS_LOG) { 2443 UninitPacketAliasLog(la); 2444 } 2445#ifndef NO_FW_PUNCH 2446/* Start punching holes in the firewall? */ 2447 if (flags & mask & PKT_ALIAS_PUNCH_FW) { 2448 InitPunchFW(la); 2449 } else 2450/* Stop punching holes in the firewall? */ 2451 if (~flags & mask & PKT_ALIAS_PUNCH_FW) { 2452 UninitPunchFW(la); 2453 } 2454#endif 2455 2456/* Other flags can be set/cleared without special action */ 2457 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask); 2458 return (la->packetAliasMode); 2459} 2460 2461 2462int 2463LibAliasCheckNewLink(struct libalias *la) 2464{ 2465 return (la->newDefaultLink); 2466} 2467 2468 2469#ifndef NO_FW_PUNCH 2470 2471/***************** 2472 Code to support firewall punching. This shouldn't really be in this 2473 file, but making variables global is evil too. 2474 ****************/ 2475 2476#ifndef IPFW2 2477#define IPFW2 1 /* use new ipfw code */ 2478#endif 2479 2480/* Firewall include files */ 2481#include <net/if.h> 2482#include <netinet/ip_fw.h> 2483#include <string.h> 2484#include <err.h> 2485 2486#if IPFW2 /* support for new firewall code */ 2487/* 2488 * helper function, updates the pointer to cmd with the length 2489 * of the current command, and also cleans up the first word of 2490 * the new command in case it has been clobbered before. 2491 */ 2492static ipfw_insn * 2493next_cmd(ipfw_insn * cmd) 2494{ 2495 cmd += F_LEN(cmd); 2496 bzero(cmd, sizeof(*cmd)); 2497 return (cmd); 2498} 2499 2500/* 2501 * A function to fill simple commands of size 1. 2502 * Existing flags are preserved. 2503 */ 2504static ipfw_insn * 2505fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size, 2506 int flags, u_int16_t arg) 2507{ 2508 cmd->opcode = opcode; 2509 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK); 2510 cmd->arg1 = arg; 2511 return next_cmd(cmd); 2512} 2513 2514static ipfw_insn * 2515fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr) 2516{ 2517 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1; 2518 2519 cmd->addr.s_addr = addr; 2520 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0); 2521} 2522 2523static ipfw_insn * 2524fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port) 2525{ 2526 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1; 2527 2528 cmd->ports[0] = cmd->ports[1] = port; 2529 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0); 2530} 2531 2532static int 2533fill_rule(void *buf, int bufsize, int rulenum, 2534 enum ipfw_opcodes action, int proto, 2535 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp) 2536{ 2537 struct ip_fw *rule = (struct ip_fw *)buf; 2538 ipfw_insn *cmd = (ipfw_insn *) rule->cmd; 2539 2540 bzero(buf, bufsize); 2541 rule->rulenum = rulenum; 2542 2543 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto); 2544 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr); 2545 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp); 2546 cmd = fill_ip(cmd, O_IP_DST, da.s_addr); 2547 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp); 2548 2549 rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd; 2550 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0); 2551 2552 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd; 2553 2554 return ((char *)cmd - (char *)buf); 2555} 2556 2557#endif /* IPFW2 */ 2558 2559static void ClearAllFWHoles(struct libalias *la); 2560 2561 2562#define fw_setfield(la, field, num) \ 2563do { \ 2564 (field)[(num) - la->fireWallBaseNum] = 1; \ 2565} /*lint -save -e717 */ while(0)/* lint -restore */ 2566 2567#define fw_clrfield(la, field, num) \ 2568do { \ 2569 (field)[(num) - la->fireWallBaseNum] = 0; \ 2570} /*lint -save -e717 */ while(0)/* lint -restore */ 2571 2572#define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum]) 2573 2574static void 2575InitPunchFW(struct libalias *la) 2576{ 2577 2578 la->fireWallField = malloc(la->fireWallNumNums); 2579 if (la->fireWallField) { 2580 memset(la->fireWallField, 0, la->fireWallNumNums); 2581 if (la->fireWallFD < 0) { 2582 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 2583 } 2584 ClearAllFWHoles(la); 2585 la->fireWallActiveNum = la->fireWallBaseNum; 2586 } 2587} 2588 2589static void 2590UninitPunchFW(struct libalias *la) 2591{ 2592 ClearAllFWHoles(la); 2593 if (la->fireWallFD >= 0) 2594 close(la->fireWallFD); 2595 la->fireWallFD = -1; 2596 if (la->fireWallField) 2597 free(la->fireWallField); 2598 la->fireWallField = NULL; 2599 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW; 2600} 2601 2602/* Make a certain link go through the firewall */ 2603void 2604PunchFWHole(struct alias_link *lnk) 2605{ 2606 struct libalias *la; 2607 int r; /* Result code */ 2608 struct ip_fw rule; /* On-the-fly built rule */ 2609 int fwhole; /* Where to punch hole */ 2610 2611 la = lnk->la; 2612 2613/* Don't do anything unless we are asked to */ 2614 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) || 2615 la->fireWallFD < 0 || 2616 lnk->link_type != LINK_TCP) 2617 return; 2618 2619 memset(&rule, 0, sizeof rule); 2620 2621/** Build rule **/ 2622 2623 /* Find empty slot */ 2624 for (fwhole = la->fireWallActiveNum; 2625 fwhole < la->fireWallBaseNum + la->fireWallNumNums && 2626 fw_tstfield(la, la->fireWallField, fwhole); 2627 fwhole++); 2628 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) { 2629 for (fwhole = la->fireWallBaseNum; 2630 fwhole < la->fireWallActiveNum && 2631 fw_tstfield(la, la->fireWallField, fwhole); 2632 fwhole++); 2633 if (fwhole == la->fireWallActiveNum) { 2634 /* No rule point empty - we can't punch more holes. */ 2635 la->fireWallActiveNum = la->fireWallBaseNum; 2636#ifdef DEBUG 2637 fprintf(stderr, "libalias: Unable to create firewall hole!\n"); 2638#endif 2639 return; 2640 } 2641 } 2642 /* Start next search at next position */ 2643 la->fireWallActiveNum = fwhole + 1; 2644 2645 /* 2646 * generate two rules of the form 2647 * 2648 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole 2649 * accept tcp from DAddr DPort to OAddr OPort 2650 */ 2651#if IPFW2 2652 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) { 2653 u_int32_t rulebuf[255]; 2654 int i; 2655 2656 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole, 2657 O_ACCEPT, IPPROTO_TCP, 2658 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)), 2659 GetDestAddress(lnk), ntohs(GetDestPort(lnk))); 2660 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i); 2661 if (r) 2662 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)"); 2663 2664 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole, 2665 O_ACCEPT, IPPROTO_TCP, 2666 GetDestAddress(lnk), ntohs(GetDestPort(lnk)), 2667 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk))); 2668 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i); 2669 if (r) 2670 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)"); 2671 } 2672#else /* !IPFW2, old code to generate ipfw rule */ 2673 2674 /* Build generic part of the two rules */ 2675 rule.fw_number = fwhole; 2676 IP_FW_SETNSRCP(&rule, 1); /* Number of source ports. */ 2677 IP_FW_SETNDSTP(&rule, 1); /* Number of destination ports. */ 2678 rule.fw_flg = IP_FW_F_ACCEPT | IP_FW_F_IN | IP_FW_F_OUT; 2679 rule.fw_prot = IPPROTO_TCP; 2680 rule.fw_smsk.s_addr = INADDR_BROADCAST; 2681 rule.fw_dmsk.s_addr = INADDR_BROADCAST; 2682 2683 /* Build and apply specific part of the rules */ 2684 rule.fw_src = GetOriginalAddress(lnk); 2685 rule.fw_dst = GetDestAddress(lnk); 2686 rule.fw_uar.fw_pts[0] = ntohs(GetOriginalPort(lnk)); 2687 rule.fw_uar.fw_pts[1] = ntohs(GetDestPort(lnk)); 2688 2689 /* 2690 * Skip non-bound links - XXX should not be strictly necessary, but 2691 * seems to leave hole if not done. Leak of non-bound links? (Code 2692 * should be left even if the problem is fixed - it is a clear 2693 * optimization) 2694 */ 2695 if (rule.fw_uar.fw_pts[0] != 0 && rule.fw_uar.fw_pts[1] != 0) { 2696 r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); 2697#ifdef DEBUG 2698 if (r) 2699 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)"); 2700#endif 2701 rule.fw_src = GetDestAddress(lnk); 2702 rule.fw_dst = GetOriginalAddress(lnk); 2703 rule.fw_uar.fw_pts[0] = ntohs(GetDestPort(lnk)); 2704 rule.fw_uar.fw_pts[1] = ntohs(GetOriginalPort(lnk)); 2705 r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); 2706#ifdef DEBUG 2707 if (r) 2708 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)"); 2709#endif 2710 } 2711#endif /* !IPFW2 */ 2712/* Indicate hole applied */ 2713 lnk->data.tcp->fwhole = fwhole; 2714 fw_setfield(la, la->fireWallField, fwhole); 2715} 2716 2717/* Remove a hole in a firewall associated with a particular alias 2718 lnk. Calling this too often is harmless. */ 2719static void 2720ClearFWHole(struct alias_link *lnk) 2721{ 2722 2723 struct libalias *la; 2724 2725 la = lnk->la; 2726 if (lnk->link_type == LINK_TCP) { 2727 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall 2728 * hole? */ 2729 struct ip_fw rule; 2730 2731 if (fwhole < 0) 2732 return; 2733 2734 memset(&rule, 0, sizeof rule); /* useless for ipfw2 */ 2735#if IPFW2 2736 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, 2737 &fwhole, sizeof fwhole)); 2738#else /* !IPFW2 */ 2739 rule.fw_number = fwhole; 2740 while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, 2741 &rule, sizeof rule)); 2742#endif /* !IPFW2 */ 2743 fw_clrfield(la, la->fireWallField, fwhole); 2744 lnk->data.tcp->fwhole = -1; 2745 } 2746} 2747 2748/* Clear out the entire range dedicated to firewall holes. */ 2749static void 2750ClearAllFWHoles(struct libalias *la) 2751{ 2752 struct ip_fw rule; /* On-the-fly built rule */ 2753 int i; 2754 2755 if (la->fireWallFD < 0) 2756 return; 2757 2758 memset(&rule, 0, sizeof rule); 2759 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) { 2760#if IPFW2 2761 int r = i; 2762 2763 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r)); 2764#else /* !IPFW2 */ 2765 rule.fw_number = i; 2766 while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule)); 2767#endif /* !IPFW2 */ 2768 } 2769 /* XXX: third arg correct here ? /phk */ 2770 memset(la->fireWallField, 0, la->fireWallNumNums); 2771} 2772 2773#endif 2774 2775void 2776LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num) 2777{ 2778#ifndef NO_FW_PUNCH 2779 la->fireWallBaseNum = base; 2780 la->fireWallNumNums = num; 2781#endif 2782} 2783 2784void 2785LibAliasSetSkinnyPort(struct libalias *la, unsigned int port) 2786{ 2787 la->skinnyPort = port; 2788} 2789