2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
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.
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
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.
50 Initial version: August, 1996 (cjm)
52 Version 1.4: September 16, 1996 (cjm)
53 Facility for handling incoming links added.
55 Version 1.6: September 18, 1996 (cjm)
56 ICMP data handling simplified.
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.
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)
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)
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)
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)
86 Removed K&R style function headers
87 and general cleanup. (ee)
89 Added packetAliasMode to replace compiler #defines's (ee)
91 Allocates sockets for partially specified
92 ports if ALIAS_USE_SOCKETS defined. (cjm)
94 Version 2.0: March, 1997
95 SetAliasAddress() will now clean up alias links
96 if the aliasing address is changed. (cjm)
98 PacketAliasPermanentLink() function added to support permanent
99 links. (J. Fortes suggested the need for this.)
102 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
104 (192.168.0.2, port 21) <-> alias port 3604, known dest addr
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)
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)
116 SetExpire() function added. (cjm)
118 DeleteLink() no longer frees memory association with a pointer
119 to a fragment (this bug was first recognized by E. Eklund in
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
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.
132 Version 3.2: July, 2000 (salander and satoh)
133 Added FindNewPortGroup to get contiguous range of port values.
135 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
136 link but not actually add one.
138 Added FindRtspOut, which is closely derived from FindUdpTcpOut,
139 except that the alias port (from FindNewPortGroup) is provided
142 See HISTORY file for additional revisions.
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>
155 #include <sys/errno.h>
156 #include <sys/time.h>
160 #include <sys/socket.h>
161 #include <netinet/tcp.h>
164 #include <netinet/libalias/alias.h>
165 #include <netinet/libalias/alias_local.h>
166 #include <netinet/libalias/alias_mod.h>
170 #include "alias_local.h"
171 #include "alias_mod.h"
174 static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
178 Constants (note: constants are also defined
179 near relevant functions or structs)
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)
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
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
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
207 /* When the link isn't yet up */
208 #ifndef TCP_EXPIRE_INITIAL
209 #define TCP_EXPIRE_INITIAL 300
212 /* When the link is up */
213 #ifndef TCP_EXPIRE_CONNECTED
214 #define TCP_EXPIRE_CONNECTED 86400
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. */
222 #define NO_DEST_PORT 1
223 #define NO_SRC_PORT 1
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.
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.
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
254 struct ack_data_record { /* used to save changes to ACK/sequence
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 */
271 #define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes
272 * saved for a modified TCP stream */
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
280 struct server { /* LSNAT server pool (circular list) */
286 struct alias_link { /* Main data structure */
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;
296 struct server *server;
298 int link_type; /* Type of link: TCP, UDP, ICMP,
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)
310 int flags; /* indicates special characteristics */
311 int pflags; /* protocol-specific flags */
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
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 */
325 LIST_ENTRY (alias_link) list_out; /* Linked list of
327 LIST_ENTRY (alias_link) list_in; /* input and output
330 union { /* Auxiliary data */
332 struct in_addr frag_addr;
337 /* Clean up procedure. */
338 static void finishoff(void);
340 /* Kernel module definition. */
342 MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing");
344 MODULE_VERSION(libalias, 1);
347 alias_mod_handler(module_t mod, int type, void *data)
354 handler_chain_init();
358 handler_chain_destroy();
369 static moduledata_t alias_mod = {
370 "alias", alias_mod_handler, NULL
373 DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
376 /* Internal utility routines (used only in alias_db.c)
378 Lookup table starting points:
379 StartPointIn() -- link table initial search point for
381 StartPointOut() -- link table initial search point for
385 SeqDiff() -- difference between two TCP sequences
386 ShowAliasStats() -- send alias statistics to a monitor file
390 /* Local prototypes */
391 static u_int StartPointIn(struct in_addr, u_short, int);
394 StartPointOut(struct in_addr, struct in_addr,
395 u_short, u_short, int);
397 static int SeqDiff(u_long, u_long);
400 /* Firewall control */
401 static void InitPunchFW(struct libalias *);
402 static void UninitPunchFW(struct libalias *);
403 static void ClearFWHole(struct alias_link *);
407 /* Log file control */
408 static void ShowAliasStats(struct libalias *);
409 static int InitPacketAliasLog(struct libalias *);
410 static void UninitPacketAliasLog(struct libalias *);
413 StartPointIn(struct in_addr alias_addr,
419 n = alias_addr.s_addr;
420 if (link_type != LINK_PPTP)
423 return (n % LINK_TABLE_IN_SIZE);
428 StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
429 u_short src_port, u_short dst_port, int link_type)
434 n += dst_addr.s_addr;
435 if (link_type != LINK_PPTP) {
441 return (n % LINK_TABLE_OUT_SIZE);
446 SeqDiff(u_long x, u_long y)
448 /* Return the difference between two TCP sequence numbers */
451 This function is encapsulated in case there are any unusual
452 arithmetic conditions that need to be considered.
455 return (ntohl(y) - ntohl(x));
461 AliasLog(char *str, const char *format, ...)
465 va_start(ap, format);
466 vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
471 AliasLog(FILE *stream, const char *format, ...)
475 va_start(ap, format);
476 vfprintf(stream, format, ap);
483 ShowAliasStats(struct libalias *la)
486 LIBALIAS_LOCK_ASSERT(la);
487 /* Used for debugging */
489 int tot = la->icmpLinkCount + la->udpLinkCount +
490 la->tcpLinkCount + la->pptpLinkCount +
491 la->protoLinkCount + la->fragmentIdLinkCount +
492 la->fragmentPtrLinkCount;
494 AliasLog(la->logDesc,
495 "icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
501 la->fragmentIdLinkCount,
502 la->fragmentPtrLinkCount, tot);
504 AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
509 /* Internal routines for finding, deleting and adding links
512 GetNewPort() -- find and reserve new alias port number
513 GetSocket() -- try to allocate a socket for a given port
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
520 ReLink() - change link
523 FindLinkOut() - find link for outgoing packets
524 FindLinkIn() - find link for incoming packets
527 FindNewPortGroup() - find an available group of ports
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);
535 static void CleanupAliasData(struct libalias *);
537 static void IncrementalCleanup(struct libalias *);
539 static void DeleteLink(struct alias_link *);
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);
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);
550 static struct alias_link *
551 FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
553 static struct alias_link *
554 FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
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
562 #define GET_ALIAS_PORT -1
563 #define GET_ALIAS_ID GET_ALIAS_PORT
565 #define FIND_EVEN_ALIAS_BASE 1
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). */
573 GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
580 LIBALIAS_LOCK_ASSERT(la);
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.
587 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
588 selected port number.
591 if (alias_port_param == GET_ALIAS_PORT) {
593 * The aliasing port is automatically selected by one of
596 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
598 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
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.
605 port_net = lnk->src_port;
606 port_sys = ntohs(port_net);
608 /* First trial and all subsequent are random. */
609 port_sys = arc4random() & ALIAS_PORT_MASK;
610 port_sys += ALIAS_PORT_BASE;
611 port_net = htons(port_sys);
613 } else if (alias_port_param >= 0 && alias_port_param < 0x10000) {
614 lnk->alias_port = (u_short) alias_port_param;
617 #ifdef LIBALIAS_DEBUG
618 fprintf(stderr, "PacketAlias/GetNewPort(): ");
619 fprintf(stderr, "input parameter error\n");
625 /* Port number search */
626 for (i = 0; i < max_trials; i++) {
628 struct alias_link *search_result;
630 search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr,
631 lnk->dst_port, port_net,
634 if (search_result == NULL)
636 else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED)
637 && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
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;
654 lnk->alias_port = port_net;
656 #ifndef NO_USE_SOCKETS
660 port_sys = arc4random() & ALIAS_PORT_MASK;
661 port_sys += ALIAS_PORT_BASE;
662 port_net = htons(port_sys);
665 #ifdef LIBALIAS_DEBUG
666 fprintf(stderr, "PacketAlias/GetnewPort(): ");
667 fprintf(stderr, "could not find free port\n");
673 #ifndef NO_USE_SOCKETS
675 GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
679 struct sockaddr_in sock_addr;
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);
687 #ifdef LIBALIAS_DEBUG
688 fprintf(stderr, "PacketAlias/GetSocket(): ");
689 fprintf(stderr, "incorrect link type\n");
695 #ifdef LIBALIAS_DEBUG
696 fprintf(stderr, "PacketAlias/GetSocket(): ");
697 fprintf(stderr, "socket() error %d\n", *sockfd);
701 sock_addr.sin_family = AF_INET;
702 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
703 sock_addr.sin_port = port_net;
706 (struct sockaddr *)&sock_addr,
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). */
726 FindNewPortGroup(struct libalias *la,
727 struct in_addr dst_addr,
728 struct in_addr alias_addr,
740 LIBALIAS_LOCK_ASSERT(la);
742 * Get link_type from protocol
747 link_type = LINK_UDP;
750 link_type = LINK_TCP;
758 * The aliasing port is automatically selected by one of two
761 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
763 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
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.
769 port_sys = ntohs(src_port);
773 /* First trial and all subsequent are random. */
774 if (align == FIND_EVEN_ALIAS_BASE)
775 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
777 port_sys = arc4random() & ALIAS_PORT_MASK;
779 port_sys += ALIAS_PORT_BASE;
782 /* Port number search */
783 for (i = 0; i < max_trials; i++) {
785 struct alias_link *search_result;
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),
793 /* Found a good range, return base */
795 return (htons(port_sys));
797 /* Find a new base to try */
798 if (align == FIND_EVEN_ALIAS_BASE)
799 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
801 port_sys = arc4random() & ALIAS_PORT_MASK;
803 port_sys += ALIAS_PORT_BASE;
806 #ifdef LIBALIAS_DEBUG
807 fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
808 fprintf(stderr, "could not find free port(s)\n");
815 CleanupAliasData(struct libalias *la)
817 struct alias_link *lnk;
820 LIBALIAS_LOCK_ASSERT(la);
821 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) {
822 lnk = LIST_FIRST(&la->linkTableOut[i]);
823 while (lnk != NULL) {
824 struct alias_link *link_next = LIST_NEXT(lnk, list_out);
830 la->cleanupIndex = 0;
835 IncrementalCleanup(struct libalias *la)
837 struct alias_link *lnk, *lnk_tmp;
839 LIBALIAS_LOCK_ASSERT(la);
840 LIST_FOREACH_SAFE(lnk, &la->linkTableOut[la->cleanupIndex++],
842 if (la->timeStamp - lnk->timestamp > lnk->expire_time)
846 if (la->cleanupIndex == LINK_TABLE_OUT_SIZE)
847 la->cleanupIndex = 0;
851 DeleteLink(struct alias_link *lnk)
853 struct libalias *la = lnk->la;
855 LIBALIAS_LOCK_ASSERT(la);
856 /* Don't do anything if the link is marked permanent */
857 if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT)
861 /* Delete associated firewall hole, if any */
865 /* Free memory allocated for LSNAT server pool */
866 if (lnk->server != NULL) {
867 struct server *head, *curr, *next;
869 head = curr = lnk->server;
873 } while ((curr = next) != head);
875 /* Adjust output table pointers */
876 LIST_REMOVE(lnk, list_out);
878 /* Adjust input table pointers */
879 LIST_REMOVE(lnk, list_in);
880 #ifndef NO_USE_SOCKETS
881 /* Close socket, if one has been allocated */
882 if (lnk->sockfd != -1) {
887 /* Link-type dependent cleanup */
888 switch (lnk->link_type) {
902 case LINK_FRAGMENT_ID:
903 la->fragmentIdLinkCount--;
905 case LINK_FRAGMENT_PTR:
906 la->fragmentPtrLinkCount--;
907 if (lnk->data.frag_ptr != NULL)
908 free(lnk->data.frag_ptr);
913 la->protoLinkCount--;
920 /* Write statistics, if logging enabled */
921 if (la->packetAliasMode & PKT_ALIAS_LOG) {
927 static struct alias_link *
928 AddLink(struct libalias *la, struct in_addr src_addr,
929 struct in_addr dst_addr,
930 struct in_addr alias_addr,
933 int alias_port_param, /* if less than zero, alias */
935 { /* port will be automatically *//* chosen.
937 u_int start_point; /* zero, equal to alias port */
938 struct alias_link *lnk;
940 LIBALIAS_LOCK_ASSERT(la);
941 lnk = malloc(sizeof(struct alias_link));
943 /* Basic initialization */
945 lnk->src_addr = src_addr;
946 lnk->dst_addr = dst_addr;
947 lnk->alias_addr = alias_addr;
948 lnk->proxy_addr.s_addr = INADDR_ANY;
949 lnk->src_port = src_port;
950 lnk->dst_port = dst_port;
953 lnk->link_type = link_type;
954 #ifndef NO_USE_SOCKETS
959 lnk->timestamp = la->timeStamp;
961 /* Expiration time */
964 lnk->expire_time = ICMP_EXPIRE_TIME;
967 lnk->expire_time = UDP_EXPIRE_TIME;
970 lnk->expire_time = TCP_EXPIRE_INITIAL;
973 lnk->flags |= LINK_PERMANENT; /* no timeout. */
975 case LINK_FRAGMENT_ID:
976 lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME;
978 case LINK_FRAGMENT_PTR:
979 lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
984 lnk->expire_time = PROTO_EXPIRE_TIME;
988 /* Determine alias flags */
989 if (dst_addr.s_addr == INADDR_ANY)
990 lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
992 lnk->flags |= LINK_UNKNOWN_DEST_PORT;
994 /* Determine alias port */
995 if (GetNewPort(la, lnk, alias_port_param) != 0) {
999 /* Link-type dependent initialization */
1000 switch (link_type) {
1001 struct tcp_dat *aux_tcp;
1004 la->icmpLinkCount++;
1010 aux_tcp = malloc(sizeof(struct tcp_dat));
1011 if (aux_tcp != NULL) {
1015 aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
1016 aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
1017 aux_tcp->state.index = 0;
1018 aux_tcp->state.ack_modified = 0;
1019 for (i = 0; i < N_LINK_TCP_DATA; i++)
1020 aux_tcp->ack[i].active = 0;
1021 aux_tcp->fwhole = -1;
1022 lnk->data.tcp = aux_tcp;
1024 #ifdef LIBALIAS_DEBUG
1025 fprintf(stderr, "PacketAlias/AddLink: ");
1026 fprintf(stderr, " cannot allocate auxiliary TCP data\n");
1033 la->pptpLinkCount++;
1035 case LINK_FRAGMENT_ID:
1036 la->fragmentIdLinkCount++;
1038 case LINK_FRAGMENT_PTR:
1039 la->fragmentPtrLinkCount++;
1044 la->protoLinkCount++;
1048 /* Set up pointers for output lookup table */
1049 start_point = StartPointOut(src_addr, dst_addr,
1050 src_port, dst_port, link_type);
1051 LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out);
1053 /* Set up pointers for input lookup table */
1054 start_point = StartPointIn(alias_addr, lnk->alias_port, link_type);
1055 LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in);
1057 #ifdef LIBALIAS_DEBUG
1058 fprintf(stderr, "PacketAlias/AddLink(): ");
1059 fprintf(stderr, "malloc() call failed.\n");
1062 if (la->packetAliasMode & PKT_ALIAS_LOG) {
1068 static struct alias_link *
1069 ReLink(struct alias_link *old_lnk,
1070 struct in_addr src_addr,
1071 struct in_addr dst_addr,
1072 struct in_addr alias_addr,
1075 int alias_port_param, /* if less than zero, alias */
1077 { /* port will be automatically *//* chosen.
1078 * If greater than */
1079 struct alias_link *new_lnk; /* zero, equal to alias port */
1080 struct libalias *la = old_lnk->la;
1082 LIBALIAS_LOCK_ASSERT(la);
1083 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1084 src_port, dst_port, alias_port_param,
1087 if (new_lnk != NULL &&
1088 old_lnk->link_type == LINK_TCP &&
1089 old_lnk->data.tcp->fwhole > 0) {
1090 PunchFWHole(new_lnk);
1093 DeleteLink(old_lnk);
1097 static struct alias_link *
1098 _FindLinkOut(struct libalias *la, struct in_addr src_addr,
1099 struct in_addr dst_addr,
1103 int replace_partial_links)
1106 struct alias_link *lnk;
1108 LIBALIAS_LOCK_ASSERT(la);
1109 i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
1110 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) {
1111 if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
1112 lnk->src_addr.s_addr == src_addr.s_addr &&
1113 lnk->src_port == src_port &&
1114 lnk->dst_port == dst_port &&
1115 lnk->link_type == link_type &&
1116 lnk->server == NULL) {
1117 lnk->timestamp = la->timeStamp;
1122 /* Search for partially specified links. */
1123 if (lnk == NULL && replace_partial_links) {
1124 if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
1125 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0,
1128 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port,
1129 dst_port, link_type, 0);
1132 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
1133 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0,
1138 src_addr, dst_addr, lnk->alias_addr,
1139 src_port, dst_port, lnk->alias_port,
1146 static struct alias_link *
1147 FindLinkOut(struct libalias *la, struct in_addr src_addr,
1148 struct in_addr dst_addr,
1152 int replace_partial_links)
1154 struct alias_link *lnk;
1156 LIBALIAS_LOCK_ASSERT(la);
1157 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port,
1158 link_type, replace_partial_links);
1162 * The following allows permanent links to be specified as
1163 * using the default source address (i.e. device interface
1164 * address) without knowing in advance what that address
1167 if (la->aliasAddress.s_addr != INADDR_ANY &&
1168 src_addr.s_addr == la->aliasAddress.s_addr) {
1169 lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port,
1170 link_type, replace_partial_links);
1177 static struct alias_link *
1178 _FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1179 struct in_addr alias_addr,
1183 int replace_partial_links)
1187 struct alias_link *lnk;
1188 struct alias_link *lnk_fully_specified;
1189 struct alias_link *lnk_unknown_all;
1190 struct alias_link *lnk_unknown_dst_addr;
1191 struct alias_link *lnk_unknown_dst_port;
1193 LIBALIAS_LOCK_ASSERT(la);
1194 /* Initialize pointers */
1195 lnk_fully_specified = NULL;
1196 lnk_unknown_all = NULL;
1197 lnk_unknown_dst_addr = NULL;
1198 lnk_unknown_dst_port = NULL;
1200 /* If either the dest addr or port is unknown, the search
1201 loop will have to know about this. */
1204 if (dst_addr.s_addr == INADDR_ANY)
1205 flags_in |= LINK_UNKNOWN_DEST_ADDR;
1207 flags_in |= LINK_UNKNOWN_DEST_PORT;
1210 start_point = StartPointIn(alias_addr, alias_port, link_type);
1211 LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) {
1214 flags = flags_in | lnk->flags;
1215 if (!(flags & LINK_PARTIALLY_SPECIFIED)) {
1216 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1217 && lnk->alias_port == alias_port
1218 && lnk->dst_addr.s_addr == dst_addr.s_addr
1219 && lnk->dst_port == dst_port
1220 && lnk->link_type == link_type) {
1221 lnk_fully_specified = lnk;
1224 } else if ((flags & LINK_UNKNOWN_DEST_ADDR)
1225 && (flags & LINK_UNKNOWN_DEST_PORT)) {
1226 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1227 && lnk->alias_port == alias_port
1228 && lnk->link_type == link_type) {
1229 if (lnk_unknown_all == NULL)
1230 lnk_unknown_all = lnk;
1232 } else if (flags & LINK_UNKNOWN_DEST_ADDR) {
1233 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1234 && lnk->alias_port == alias_port
1235 && lnk->link_type == link_type
1236 && lnk->dst_port == dst_port) {
1237 if (lnk_unknown_dst_addr == NULL)
1238 lnk_unknown_dst_addr = lnk;
1240 } else if (flags & LINK_UNKNOWN_DEST_PORT) {
1241 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1242 && lnk->alias_port == alias_port
1243 && lnk->link_type == link_type
1244 && lnk->dst_addr.s_addr == dst_addr.s_addr) {
1245 if (lnk_unknown_dst_port == NULL)
1246 lnk_unknown_dst_port = lnk;
1253 if (lnk_fully_specified != NULL) {
1254 lnk_fully_specified->timestamp = la->timeStamp;
1255 lnk = lnk_fully_specified;
1256 } else if (lnk_unknown_dst_port != NULL)
1257 lnk = lnk_unknown_dst_port;
1258 else if (lnk_unknown_dst_addr != NULL)
1259 lnk = lnk_unknown_dst_addr;
1260 else if (lnk_unknown_all != NULL)
1261 lnk = lnk_unknown_all;
1265 if (replace_partial_links &&
1266 (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) {
1267 struct in_addr src_addr;
1270 if (lnk->server != NULL) { /* LSNAT link */
1271 src_addr = lnk->server->addr;
1272 src_port = lnk->server->port;
1273 lnk->server = lnk->server->next;
1275 src_addr = lnk->src_addr;
1276 src_port = lnk->src_port;
1280 src_addr, dst_addr, alias_addr,
1281 src_port, dst_port, alias_port,
1287 static struct alias_link *
1288 FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1289 struct in_addr alias_addr,
1293 int replace_partial_links)
1295 struct alias_link *lnk;
1297 LIBALIAS_LOCK_ASSERT(la);
1298 lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port,
1299 link_type, replace_partial_links);
1303 * The following allows permanent links to be specified as
1304 * using the default aliasing address (i.e. device
1305 * interface address) without knowing in advance what that
1308 if (la->aliasAddress.s_addr != INADDR_ANY &&
1309 alias_addr.s_addr == la->aliasAddress.s_addr) {
1310 lnk = _FindLinkIn(la, dst_addr, la->nullAddress, dst_port, alias_port,
1311 link_type, replace_partial_links);
1320 /* External routines for finding/adding links
1322 -- "external" means outside alias_db.c, but within alias*.c --
1324 FindIcmpIn(), FindIcmpOut()
1325 FindFragmentIn1(), FindFragmentIn2()
1326 AddFragmentPtrLink(), FindFragmentPtr()
1327 FindProtoIn(), FindProtoOut()
1328 FindUdpTcpIn(), FindUdpTcpOut()
1329 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1330 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1331 FindOriginalAddress(), FindAliasAddress()
1333 (prototypes in alias_local.h)
1338 FindIcmpIn(struct libalias *la, struct in_addr dst_addr,
1339 struct in_addr alias_addr,
1343 struct alias_link *lnk;
1345 LIBALIAS_LOCK_ASSERT(la);
1346 lnk = FindLinkIn(la, dst_addr, alias_addr,
1347 NO_DEST_PORT, id_alias,
1349 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1350 struct in_addr target_addr;
1352 target_addr = FindOriginalAddress(la, alias_addr);
1353 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1354 id_alias, NO_DEST_PORT, id_alias,
1362 FindIcmpOut(struct libalias *la, struct in_addr src_addr,
1363 struct in_addr dst_addr,
1367 struct alias_link *lnk;
1369 LIBALIAS_LOCK_ASSERT(la);
1370 lnk = FindLinkOut(la, src_addr, dst_addr,
1373 if (lnk == NULL && create) {
1374 struct in_addr alias_addr;
1376 alias_addr = FindAliasAddress(la, src_addr);
1377 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1378 id, NO_DEST_PORT, GET_ALIAS_ID,
1386 FindFragmentIn1(struct libalias *la, struct in_addr dst_addr,
1387 struct in_addr alias_addr,
1390 struct alias_link *lnk;
1392 LIBALIAS_LOCK_ASSERT(la);
1393 lnk = FindLinkIn(la, dst_addr, alias_addr,
1394 NO_DEST_PORT, ip_id,
1395 LINK_FRAGMENT_ID, 0);
1398 lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr,
1399 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1407 FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if
1409 struct in_addr alias_addr, /* is not found. */
1413 LIBALIAS_LOCK_ASSERT(la);
1414 return FindLinkIn(la, dst_addr, alias_addr,
1415 NO_DEST_PORT, ip_id,
1416 LINK_FRAGMENT_ID, 0);
1421 AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr,
1425 LIBALIAS_LOCK_ASSERT(la);
1426 return AddLink(la, la->nullAddress, dst_addr, la->nullAddress,
1427 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1433 FindFragmentPtr(struct libalias *la, struct in_addr dst_addr,
1437 LIBALIAS_LOCK_ASSERT(la);
1438 return FindLinkIn(la, dst_addr, la->nullAddress,
1439 NO_DEST_PORT, ip_id,
1440 LINK_FRAGMENT_PTR, 0);
1445 FindProtoIn(struct libalias *la, struct in_addr dst_addr,
1446 struct in_addr alias_addr,
1449 struct alias_link *lnk;
1451 LIBALIAS_LOCK_ASSERT(la);
1452 lnk = FindLinkIn(la, dst_addr, alias_addr,
1456 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1457 struct in_addr target_addr;
1459 target_addr = FindOriginalAddress(la, alias_addr);
1460 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1461 NO_SRC_PORT, NO_DEST_PORT, 0,
1469 FindProtoOut(struct libalias *la, struct in_addr src_addr,
1470 struct in_addr dst_addr,
1473 struct alias_link *lnk;
1475 LIBALIAS_LOCK_ASSERT(la);
1476 lnk = FindLinkOut(la, src_addr, dst_addr,
1477 NO_SRC_PORT, NO_DEST_PORT,
1481 struct in_addr alias_addr;
1483 alias_addr = FindAliasAddress(la, src_addr);
1484 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1485 NO_SRC_PORT, NO_DEST_PORT, 0,
1493 FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr,
1494 struct in_addr alias_addr,
1501 struct alias_link *lnk;
1503 LIBALIAS_LOCK_ASSERT(la);
1506 link_type = LINK_UDP;
1509 link_type = LINK_TCP;
1516 lnk = FindLinkIn(la, dst_addr, alias_addr,
1517 dst_port, alias_port,
1520 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1521 struct in_addr target_addr;
1523 target_addr = FindOriginalAddress(la, alias_addr);
1524 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1525 alias_port, dst_port, alias_port,
1533 FindUdpTcpOut(struct libalias *la, struct in_addr src_addr,
1534 struct in_addr dst_addr,
1541 struct alias_link *lnk;
1543 LIBALIAS_LOCK_ASSERT(la);
1546 link_type = LINK_UDP;
1549 link_type = LINK_TCP;
1556 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create);
1558 if (lnk == NULL && create) {
1559 struct in_addr alias_addr;
1561 alias_addr = FindAliasAddress(la, src_addr);
1562 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1563 src_port, dst_port, GET_ALIAS_PORT,
1571 AddPptp(struct libalias *la, struct in_addr src_addr,
1572 struct in_addr dst_addr,
1573 struct in_addr alias_addr,
1574 u_int16_t src_call_id)
1576 struct alias_link *lnk;
1578 LIBALIAS_LOCK_ASSERT(la);
1579 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1580 src_call_id, 0, GET_ALIAS_PORT,
1588 FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr,
1589 struct in_addr dst_addr,
1590 u_int16_t src_call_id)
1593 struct alias_link *lnk;
1595 LIBALIAS_LOCK_ASSERT(la);
1596 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1597 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1598 if (lnk->link_type == LINK_PPTP &&
1599 lnk->src_addr.s_addr == src_addr.s_addr &&
1600 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1601 lnk->src_port == src_call_id)
1609 FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr,
1610 struct in_addr dst_addr,
1611 u_int16_t dst_call_id)
1614 struct alias_link *lnk;
1616 LIBALIAS_LOCK_ASSERT(la);
1617 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1618 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1619 if (lnk->link_type == LINK_PPTP &&
1620 lnk->src_addr.s_addr == src_addr.s_addr &&
1621 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1622 lnk->dst_port == dst_call_id)
1630 FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr,
1631 struct in_addr alias_addr,
1632 u_int16_t dst_call_id)
1635 struct alias_link *lnk;
1637 LIBALIAS_LOCK_ASSERT(la);
1638 i = StartPointIn(alias_addr, 0, LINK_PPTP);
1639 LIST_FOREACH(lnk, &la->linkTableIn[i], list_in)
1640 if (lnk->link_type == LINK_PPTP &&
1641 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1642 lnk->alias_addr.s_addr == alias_addr.s_addr &&
1643 lnk->dst_port == dst_call_id)
1651 FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr,
1652 struct in_addr alias_addr,
1653 u_int16_t alias_call_id)
1655 struct alias_link *lnk;
1657 LIBALIAS_LOCK_ASSERT(la);
1658 lnk = FindLinkIn(la, dst_addr, alias_addr,
1659 0 /* any */ , alias_call_id,
1668 FindRtspOut(struct libalias *la, struct in_addr src_addr,
1669 struct in_addr dst_addr,
1675 struct alias_link *lnk;
1677 LIBALIAS_LOCK_ASSERT(la);
1680 link_type = LINK_UDP;
1683 link_type = LINK_TCP;
1690 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1);
1693 struct in_addr alias_addr;
1695 alias_addr = FindAliasAddress(la, src_addr);
1696 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1697 src_port, 0, alias_port,
1705 FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
1707 struct alias_link *lnk;
1709 LIBALIAS_LOCK_ASSERT(la);
1710 lnk = FindLinkIn(la, la->nullAddress, alias_addr,
1711 0, 0, LINK_ADDR, 0);
1713 la->newDefaultLink = 1;
1714 if (la->targetAddress.s_addr == INADDR_ANY)
1715 return (alias_addr);
1716 else if (la->targetAddress.s_addr == INADDR_NONE)
1717 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1718 la->aliasAddress : alias_addr;
1720 return (la->targetAddress);
1722 if (lnk->server != NULL) { /* LSNAT link */
1723 struct in_addr src_addr;
1725 src_addr = lnk->server->addr;
1726 lnk->server = lnk->server->next;
1728 } else if (lnk->src_addr.s_addr == INADDR_ANY)
1729 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1730 la->aliasAddress : alias_addr;
1732 return (lnk->src_addr);
1738 FindAliasAddress(struct libalias *la, struct in_addr original_addr)
1740 struct alias_link *lnk;
1742 LIBALIAS_LOCK_ASSERT(la);
1743 lnk = FindLinkOut(la, original_addr, la->nullAddress,
1744 0, 0, LINK_ADDR, 0);
1746 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1747 la->aliasAddress : original_addr;
1749 if (lnk->alias_addr.s_addr == INADDR_ANY)
1750 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1751 la->aliasAddress : original_addr;
1753 return (lnk->alias_addr);
1758 /* External routines for getting or changing link data
1759 (external to alias_db.c, but internal to alias*.c)
1761 SetFragmentData(), GetFragmentData()
1762 SetFragmentPtr(), GetFragmentPtr()
1763 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1764 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1765 GetOriginalPort(), GetAliasPort()
1766 SetAckModified(), GetAckModified()
1767 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1768 SetProtocolFlags(), GetProtocolFlags()
1774 SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
1776 lnk->data.frag_addr = src_addr;
1781 GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
1783 *src_addr = lnk->data.frag_addr;
1788 SetFragmentPtr(struct alias_link *lnk, char *fptr)
1790 lnk->data.frag_ptr = fptr;
1795 GetFragmentPtr(struct alias_link *lnk, char **fptr)
1797 *fptr = lnk->data.frag_ptr;
1802 SetStateIn(struct alias_link *lnk, int state)
1804 /* TCP input state */
1806 case ALIAS_TCP_STATE_DISCONNECTED:
1807 if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED)
1808 lnk->expire_time = TCP_EXPIRE_DEAD;
1810 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1812 case ALIAS_TCP_STATE_CONNECTED:
1813 if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED)
1814 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1818 panic("libalias:SetStateIn() unknown state");
1823 lnk->data.tcp->state.in = state;
1828 SetStateOut(struct alias_link *lnk, int state)
1830 /* TCP output state */
1832 case ALIAS_TCP_STATE_DISCONNECTED:
1833 if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED)
1834 lnk->expire_time = TCP_EXPIRE_DEAD;
1836 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1838 case ALIAS_TCP_STATE_CONNECTED:
1839 if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED)
1840 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1844 panic("libalias:SetStateOut() unknown state");
1849 lnk->data.tcp->state.out = state;
1854 GetStateIn(struct alias_link *lnk)
1856 /* TCP input state */
1857 return (lnk->data.tcp->state.in);
1862 GetStateOut(struct alias_link *lnk)
1864 /* TCP output state */
1865 return (lnk->data.tcp->state.out);
1870 GetOriginalAddress(struct alias_link *lnk)
1872 if (lnk->src_addr.s_addr == INADDR_ANY)
1873 return (lnk->la->aliasAddress);
1875 return (lnk->src_addr);
1880 GetDestAddress(struct alias_link *lnk)
1882 return (lnk->dst_addr);
1887 GetAliasAddress(struct alias_link *lnk)
1889 if (lnk->alias_addr.s_addr == INADDR_ANY)
1890 return (lnk->la->aliasAddress);
1892 return (lnk->alias_addr);
1897 GetDefaultAliasAddress(struct libalias *la)
1900 LIBALIAS_LOCK_ASSERT(la);
1901 return (la->aliasAddress);
1906 SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
1909 LIBALIAS_LOCK_ASSERT(la);
1910 la->aliasAddress = alias_addr;
1915 GetOriginalPort(struct alias_link *lnk)
1917 return (lnk->src_port);
1922 GetAliasPort(struct alias_link *lnk)
1924 return (lnk->alias_port);
1929 GetDestPort(struct alias_link *lnk)
1931 return (lnk->dst_port);
1937 SetAckModified(struct alias_link *lnk)
1939 /* Indicate that ACK numbers have been modified in a TCP connection */
1940 lnk->data.tcp->state.ack_modified = 1;
1945 GetProxyAddress(struct alias_link *lnk)
1947 return (lnk->proxy_addr);
1952 SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
1954 lnk->proxy_addr = addr;
1959 GetProxyPort(struct alias_link *lnk)
1961 return (lnk->proxy_port);
1966 SetProxyPort(struct alias_link *lnk, u_short port)
1968 lnk->proxy_port = port;
1973 GetAckModified(struct alias_link *lnk)
1975 /* See if ACK numbers have been modified */
1976 return (lnk->data.tcp->state.ack_modified);
1981 GetDeltaAckIn(struct ip *pip, struct alias_link *lnk)
1984 Find out how much the ACK number has been altered for an incoming
1985 TCP packet. To do this, a circular list of ACK numbers where the TCP
1986 packet size was altered is searched.
1991 int delta, ack_diff_min;
1999 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2000 struct ack_data_record x;
2002 x = lnk->data.tcp->ack[i];
2003 if (x.active == 1) {
2006 ack_diff = SeqDiff(x.ack_new, ack);
2007 if (ack_diff >= 0) {
2008 if (ack_diff_min >= 0) {
2009 if (ack_diff < ack_diff_min) {
2011 ack_diff_min = ack_diff;
2015 ack_diff_min = ack_diff;
2025 GetDeltaSeqOut(struct ip *pip, struct alias_link *lnk)
2028 Find out how much the sequence number has been altered for an outgoing
2029 TCP packet. To do this, a circular list of ACK numbers where the TCP
2030 packet size was altered is searched.
2035 int delta, seq_diff_min;
2043 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2044 struct ack_data_record x;
2046 x = lnk->data.tcp->ack[i];
2047 if (x.active == 1) {
2050 seq_diff = SeqDiff(x.ack_old, seq);
2051 if (seq_diff >= 0) {
2052 if (seq_diff_min >= 0) {
2053 if (seq_diff < seq_diff_min) {
2055 seq_diff_min = seq_diff;
2059 seq_diff_min = seq_diff;
2069 AddSeq(struct ip *pip, struct alias_link *lnk, int delta)
2072 When a TCP packet has been altered in length, save this
2073 information in a circular list. If enough packets have
2074 been altered, then this list will begin to overwrite itself.
2078 struct ack_data_record x;
2079 int hlen, tlen, dlen;
2084 hlen = (pip->ip_hl + tc->th_off) << 2;
2085 tlen = ntohs(pip->ip_len);
2088 x.ack_old = htonl(ntohl(tc->th_seq) + dlen);
2089 x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta);
2093 i = lnk->data.tcp->state.index;
2094 lnk->data.tcp->ack[i] = x;
2097 if (i == N_LINK_TCP_DATA)
2098 lnk->data.tcp->state.index = 0;
2100 lnk->data.tcp->state.index = i;
2104 SetExpire(struct alias_link *lnk, int expire)
2107 lnk->flags &= ~LINK_PERMANENT;
2109 } else if (expire == -1) {
2110 lnk->flags |= LINK_PERMANENT;
2111 } else if (expire > 0) {
2112 lnk->expire_time = expire;
2114 #ifdef LIBALIAS_DEBUG
2115 fprintf(stderr, "PacketAlias/SetExpire(): ");
2116 fprintf(stderr, "error in expire parameter\n");
2122 ClearCheckNewLink(struct libalias *la)
2125 LIBALIAS_LOCK_ASSERT(la);
2126 la->newDefaultLink = 0;
2130 SetProtocolFlags(struct alias_link *lnk, int pflags)
2133 lnk->pflags = pflags;;
2137 GetProtocolFlags(struct alias_link *lnk)
2140 return (lnk->pflags);
2144 SetDestCallId(struct alias_link *lnk, u_int16_t cid)
2146 struct libalias *la = lnk->la;
2148 LIBALIAS_LOCK_ASSERT(la);
2149 la->deleteAllLinks = 1;
2150 ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr,
2151 lnk->src_port, cid, lnk->alias_port, lnk->link_type);
2152 la->deleteAllLinks = 0;
2156 /* Miscellaneous Functions
2159 InitPacketAliasLog()
2160 UninitPacketAliasLog()
2164 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2165 is called to find and remove timed-out aliasing links. Logic exists
2166 to sweep through the entire table and linked list structure
2169 (prototype in alias_local.h)
2173 HouseKeeping(struct libalias *la)
2181 LIBALIAS_LOCK_ASSERT(la);
2183 * Save system time (seconds) in global variable timeStamp for use
2184 * by other functions. This is done so as not to unnecessarily
2185 * waste timeline by making system calls.
2188 la->timeStamp = time_uptime;
2190 gettimeofday(&tv, &tz);
2191 la->timeStamp = tv.tv_sec;
2194 /* Compute number of spokes (output table link chains) to cover */
2195 n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime);
2196 n /= ALIAS_CLEANUP_INTERVAL_SECS;
2198 /* Handle different cases */
2200 if (n > ALIAS_CLEANUP_MAX_SPOKES)
2201 n = ALIAS_CLEANUP_MAX_SPOKES;
2202 la->lastCleanupTime = la->timeStamp;
2203 for (i = 0; i < n; i++)
2204 IncrementalCleanup(la);
2206 #ifdef LIBALIAS_DEBUG
2207 fprintf(stderr, "PacketAlias/HouseKeeping(): ");
2208 fprintf(stderr, "something unexpected in time values\n");
2210 la->lastCleanupTime = la->timeStamp;
2214 /* Init the log file and enable logging */
2216 InitPacketAliasLog(struct libalias *la)
2219 LIBALIAS_LOCK_ASSERT(la);
2220 if (~la->packetAliasMode & PKT_ALIAS_LOG) {
2222 if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
2225 if ((la->logDesc = fopen("/var/log/alias.log", "w")))
2226 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2229 return (ENOMEM); /* log initialization failed */
2230 la->packetAliasMode |= PKT_ALIAS_LOG;
2236 /* Close the log-file and disable logging. */
2238 UninitPacketAliasLog(struct libalias *la)
2241 LIBALIAS_LOCK_ASSERT(la);
2246 fclose(la->logDesc);
2250 la->packetAliasMode &= ~PKT_ALIAS_LOG;
2253 /* Outside world interfaces
2255 -- "outside world" means other than alias*.c routines --
2257 PacketAliasRedirectPort()
2258 PacketAliasAddServer()
2259 PacketAliasRedirectProto()
2260 PacketAliasRedirectAddr()
2261 PacketAliasRedirectDynamic()
2262 PacketAliasRedirectDelete()
2263 PacketAliasSetAddress()
2266 PacketAliasSetMode()
2268 (prototypes in alias.h)
2271 /* Redirection from a specific public addr:port to a
2272 private addr:port */
2274 LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port,
2275 struct in_addr dst_addr, u_short dst_port,
2276 struct in_addr alias_addr, u_short alias_port,
2280 struct alias_link *lnk;
2285 link_type = LINK_UDP;
2288 link_type = LINK_TCP;
2291 #ifdef LIBALIAS_DEBUG
2292 fprintf(stderr, "PacketAliasRedirectPort(): ");
2293 fprintf(stderr, "only TCP and UDP protocols allowed\n");
2299 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2300 src_port, dst_port, alias_port,
2304 lnk->flags |= LINK_PERMANENT;
2306 #ifdef LIBALIAS_DEBUG
2308 fprintf(stderr, "PacketAliasRedirectPort(): "
2309 "call to AddLink() failed\n");
2314 LIBALIAS_UNLOCK(la);
2318 /* Add server to the pool of servers */
2320 LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
2322 struct server *server;
2328 server = malloc(sizeof(struct server));
2330 if (server != NULL) {
2331 struct server *head;
2333 server->addr = addr;
2334 server->port = port;
2338 server->next = server;
2342 for (s = head; s->next != head; s = s->next);
2344 server->next = head;
2346 lnk->server = server;
2351 LIBALIAS_UNLOCK(la);
2355 /* Redirect packets of a given IP protocol from a specific
2356 public address to a private address */
2358 LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr,
2359 struct in_addr dst_addr,
2360 struct in_addr alias_addr,
2363 struct alias_link *lnk;
2366 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2367 NO_SRC_PORT, NO_DEST_PORT, 0,
2371 lnk->flags |= LINK_PERMANENT;
2373 #ifdef LIBALIAS_DEBUG
2375 fprintf(stderr, "PacketAliasRedirectProto(): "
2376 "call to AddLink() failed\n");
2380 LIBALIAS_UNLOCK(la);
2384 /* Static address translation */
2386 LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr,
2387 struct in_addr alias_addr)
2389 struct alias_link *lnk;
2392 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
2397 lnk->flags |= LINK_PERMANENT;
2399 #ifdef LIBALIAS_DEBUG
2401 fprintf(stderr, "PacketAliasRedirectAddr(): "
2402 "call to AddLink() failed\n");
2406 LIBALIAS_UNLOCK(la);
2411 /* Mark the aliasing link dynamic */
2413 LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
2420 if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
2423 lnk->flags &= ~LINK_PERMANENT;
2426 LIBALIAS_UNLOCK(la);
2432 LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
2434 /* This is a dangerous function to put in the API,
2435 because an invalid pointer can crash the program. */
2438 la->deleteAllLinks = 1;
2440 la->deleteAllLinks = 0;
2441 LIBALIAS_UNLOCK(la);
2446 LibAliasSetAddress(struct libalias *la, struct in_addr addr)
2450 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2451 && la->aliasAddress.s_addr != addr.s_addr)
2452 CleanupAliasData(la);
2454 la->aliasAddress = addr;
2455 LIBALIAS_UNLOCK(la);
2460 LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2464 la->targetAddress = target_addr;
2465 LIBALIAS_UNLOCK(la);
2472 while (!LIST_EMPTY(&instancehead))
2473 LibAliasUninit(LIST_FIRST(&instancehead));
2477 LibAliasInit(struct libalias *la)
2486 la = calloc(sizeof *la, 1);
2490 #ifndef _KERNEL /* kernel cleans up on module unload */
2491 if (LIST_EMPTY(&instancehead))
2494 LIST_INSERT_HEAD(&instancehead, la, instancelist);
2497 la->timeStamp = time_uptime;
2498 la->lastCleanupTime = time_uptime;
2500 gettimeofday(&tv, &tz);
2501 la->timeStamp = tv.tv_sec;
2502 la->lastCleanupTime = tv.tv_sec;
2505 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
2506 LIST_INIT(&la->linkTableOut[i]);
2507 for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
2508 LIST_INIT(&la->linkTableIn[i]);
2509 LIBALIAS_LOCK_INIT(la);
2513 la->deleteAllLinks = 1;
2514 CleanupAliasData(la);
2515 la->deleteAllLinks = 0;
2518 la->aliasAddress.s_addr = INADDR_ANY;
2519 la->targetAddress.s_addr = INADDR_ANY;
2521 la->icmpLinkCount = 0;
2522 la->udpLinkCount = 0;
2523 la->tcpLinkCount = 0;
2524 la->pptpLinkCount = 0;
2525 la->protoLinkCount = 0;
2526 la->fragmentIdLinkCount = 0;
2527 la->fragmentPtrLinkCount = 0;
2530 la->cleanupIndex = 0;
2532 la->packetAliasMode = PKT_ALIAS_SAME_PORTS
2533 #ifndef NO_USE_SOCKETS
2534 | PKT_ALIAS_USE_SOCKETS
2536 | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2538 la->fireWallFD = -1;
2541 LibAliasRefreshModules();
2543 LIBALIAS_UNLOCK(la);
2548 LibAliasUninit(struct libalias *la)
2552 la->deleteAllLinks = 1;
2553 CleanupAliasData(la);
2554 la->deleteAllLinks = 0;
2555 UninitPacketAliasLog(la);
2559 LIST_REMOVE(la, instancelist);
2560 LIBALIAS_UNLOCK(la);
2561 LIBALIAS_LOCK_DESTROY(la);
2565 /* Change mode for some operations */
2568 struct libalias *la,
2569 unsigned int flags, /* Which state to bring flags to */
2570 unsigned int mask /* Mask of which flags to affect (use 0 to
2571 * do a probe for flag values) */
2577 /* Enable logging? */
2578 if (flags & mask & PKT_ALIAS_LOG) {
2580 if (InitPacketAliasLog(la) == ENOMEM)
2583 /* _Disable_ logging? */
2584 if (~flags & mask & PKT_ALIAS_LOG) {
2585 UninitPacketAliasLog(la);
2588 /* Start punching holes in the firewall? */
2589 if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2592 /* Stop punching holes in the firewall? */
2593 if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2598 /* Other flags can be set/cleared without special action */
2599 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2600 res = la->packetAliasMode;
2602 LIBALIAS_UNLOCK(la);
2608 LibAliasCheckNewLink(struct libalias *la)
2613 res = la->newDefaultLink;
2614 LIBALIAS_UNLOCK(la);
2622 Code to support firewall punching. This shouldn't really be in this
2623 file, but making variables global is evil too.
2626 /* Firewall include files */
2628 #include <netinet/ip_fw.h>
2633 * helper function, updates the pointer to cmd with the length
2634 * of the current command, and also cleans up the first word of
2635 * the new command in case it has been clobbered before.
2638 next_cmd(ipfw_insn * cmd)
2641 bzero(cmd, sizeof(*cmd));
2646 * A function to fill simple commands of size 1.
2647 * Existing flags are preserved.
2650 fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2651 int flags, u_int16_t arg)
2653 cmd->opcode = opcode;
2654 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2656 return next_cmd(cmd);
2660 fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2662 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1;
2664 cmd->addr.s_addr = addr;
2665 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2669 fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2671 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1;
2673 cmd->ports[0] = cmd->ports[1] = port;
2674 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2678 fill_rule(void *buf, int bufsize, int rulenum,
2679 enum ipfw_opcodes action, int proto,
2680 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
2682 struct ip_fw *rule = (struct ip_fw *)buf;
2683 ipfw_insn *cmd = (ipfw_insn *) rule->cmd;
2685 bzero(buf, bufsize);
2686 rule->rulenum = rulenum;
2688 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto);
2689 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr);
2690 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp);
2691 cmd = fill_ip(cmd, O_IP_DST, da.s_addr);
2692 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
2694 rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2695 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
2697 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2699 return ((char *)cmd - (char *)buf);
2702 static void ClearAllFWHoles(struct libalias *la);
2705 #define fw_setfield(la, field, num) \
2707 (field)[(num) - la->fireWallBaseNum] = 1; \
2708 } /*lint -save -e717 */ while(0)/* lint -restore */
2710 #define fw_clrfield(la, field, num) \
2712 (field)[(num) - la->fireWallBaseNum] = 0; \
2713 } /*lint -save -e717 */ while(0)/* lint -restore */
2715 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2718 InitPunchFW(struct libalias *la)
2721 LIBALIAS_LOCK_ASSERT(la);
2722 la->fireWallField = malloc(la->fireWallNumNums);
2723 if (la->fireWallField) {
2724 memset(la->fireWallField, 0, la->fireWallNumNums);
2725 if (la->fireWallFD < 0) {
2726 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2728 ClearAllFWHoles(la);
2729 la->fireWallActiveNum = la->fireWallBaseNum;
2734 UninitPunchFW(struct libalias *la)
2737 LIBALIAS_LOCK_ASSERT(la);
2738 ClearAllFWHoles(la);
2739 if (la->fireWallFD >= 0)
2740 close(la->fireWallFD);
2741 la->fireWallFD = -1;
2742 if (la->fireWallField)
2743 free(la->fireWallField);
2744 la->fireWallField = NULL;
2745 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2748 /* Make a certain link go through the firewall */
2750 PunchFWHole(struct alias_link *lnk)
2752 struct libalias *la;
2753 int r; /* Result code */
2754 struct ip_fw rule; /* On-the-fly built rule */
2755 int fwhole; /* Where to punch hole */
2757 LIBALIAS_LOCK_ASSERT(la);
2760 /* Don't do anything unless we are asked to */
2761 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2762 la->fireWallFD < 0 ||
2763 lnk->link_type != LINK_TCP)
2766 memset(&rule, 0, sizeof rule);
2770 /* Find empty slot */
2771 for (fwhole = la->fireWallActiveNum;
2772 fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2773 fw_tstfield(la, la->fireWallField, fwhole);
2775 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2776 for (fwhole = la->fireWallBaseNum;
2777 fwhole < la->fireWallActiveNum &&
2778 fw_tstfield(la, la->fireWallField, fwhole);
2780 if (fwhole == la->fireWallActiveNum) {
2781 /* No rule point empty - we can't punch more holes. */
2782 la->fireWallActiveNum = la->fireWallBaseNum;
2783 #ifdef LIBALIAS_DEBUG
2784 fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2789 /* Start next search at next position */
2790 la->fireWallActiveNum = fwhole + 1;
2793 * generate two rules of the form
2795 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2796 * accept tcp from DAddr DPort to OAddr OPort
2798 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2799 u_int32_t rulebuf[255];
2802 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2803 O_ACCEPT, IPPROTO_TCP,
2804 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
2805 GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
2806 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2808 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2810 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2811 O_ACCEPT, IPPROTO_TCP,
2812 GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
2813 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
2814 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2816 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2819 /* Indicate hole applied */
2820 lnk->data.tcp->fwhole = fwhole;
2821 fw_setfield(la, la->fireWallField, fwhole);
2824 /* Remove a hole in a firewall associated with a particular alias
2825 lnk. Calling this too often is harmless. */
2827 ClearFWHole(struct alias_link *lnk)
2829 struct libalias *la;
2831 LIBALIAS_LOCK_ASSERT(la);
2833 if (lnk->link_type == LINK_TCP) {
2834 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall
2841 memset(&rule, 0, sizeof rule); /* useless for ipfw2 */
2842 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL,
2843 &fwhole, sizeof fwhole));
2844 fw_clrfield(la, la->fireWallField, fwhole);
2845 lnk->data.tcp->fwhole = -1;
2849 /* Clear out the entire range dedicated to firewall holes. */
2851 ClearAllFWHoles(struct libalias *la)
2853 struct ip_fw rule; /* On-the-fly built rule */
2856 LIBALIAS_LOCK_ASSERT(la);
2857 if (la->fireWallFD < 0)
2860 memset(&rule, 0, sizeof rule);
2861 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2864 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2866 /* XXX: third arg correct here ? /phk */
2867 memset(la->fireWallField, 0, la->fireWallNumNums);
2873 LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2878 la->fireWallBaseNum = base;
2879 la->fireWallNumNums = num;
2881 LIBALIAS_UNLOCK(la);
2885 LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2889 la->skinnyPort = port;
2890 LIBALIAS_UNLOCK(la);