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 = random() & 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 = random() & 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 = random() & ALIAS_PORT_MASK_EVEN;
777 port_sys = random() & 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 = random() & ALIAS_PORT_MASK_EVEN;
801 port_sys = random() & 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(u_long ack, 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.
1990 int delta, ack_diff_min;
1994 for (i = 0; i < N_LINK_TCP_DATA; i++) {
1995 struct ack_data_record x;
1997 x = lnk->data.tcp->ack[i];
1998 if (x.active == 1) {
2001 ack_diff = SeqDiff(x.ack_new, ack);
2002 if (ack_diff >= 0) {
2003 if (ack_diff_min >= 0) {
2004 if (ack_diff < ack_diff_min) {
2006 ack_diff_min = ack_diff;
2010 ack_diff_min = ack_diff;
2020 GetDeltaSeqOut(u_long seq, struct alias_link *lnk)
2023 Find out how much the sequence number has been altered for an outgoing
2024 TCP packet. To do this, a circular list of ACK numbers where the TCP
2025 packet size was altered is searched.
2029 int delta, seq_diff_min;
2033 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2034 struct ack_data_record x;
2036 x = lnk->data.tcp->ack[i];
2037 if (x.active == 1) {
2040 seq_diff = SeqDiff(x.ack_old, seq);
2041 if (seq_diff >= 0) {
2042 if (seq_diff_min >= 0) {
2043 if (seq_diff < seq_diff_min) {
2045 seq_diff_min = seq_diff;
2049 seq_diff_min = seq_diff;
2059 AddSeq(struct alias_link *lnk, int delta, u_int ip_hl, u_short ip_len,
2060 u_long th_seq, u_int th_off)
2063 When a TCP packet has been altered in length, save this
2064 information in a circular list. If enough packets have
2065 been altered, then this list will begin to overwrite itself.
2068 struct ack_data_record x;
2069 int hlen, tlen, dlen;
2072 hlen = (ip_hl + th_off) << 2;
2073 tlen = ntohs(ip_len);
2076 x.ack_old = htonl(ntohl(th_seq) + dlen);
2077 x.ack_new = htonl(ntohl(th_seq) + dlen + delta);
2081 i = lnk->data.tcp->state.index;
2082 lnk->data.tcp->ack[i] = x;
2085 if (i == N_LINK_TCP_DATA)
2086 lnk->data.tcp->state.index = 0;
2088 lnk->data.tcp->state.index = i;
2092 SetExpire(struct alias_link *lnk, int expire)
2095 lnk->flags &= ~LINK_PERMANENT;
2097 } else if (expire == -1) {
2098 lnk->flags |= LINK_PERMANENT;
2099 } else if (expire > 0) {
2100 lnk->expire_time = expire;
2102 #ifdef LIBALIAS_DEBUG
2103 fprintf(stderr, "PacketAlias/SetExpire(): ");
2104 fprintf(stderr, "error in expire parameter\n");
2110 ClearCheckNewLink(struct libalias *la)
2113 LIBALIAS_LOCK_ASSERT(la);
2114 la->newDefaultLink = 0;
2118 SetProtocolFlags(struct alias_link *lnk, int pflags)
2121 lnk->pflags = pflags;;
2125 GetProtocolFlags(struct alias_link *lnk)
2128 return (lnk->pflags);
2132 SetDestCallId(struct alias_link *lnk, u_int16_t cid)
2134 struct libalias *la = lnk->la;
2136 LIBALIAS_LOCK_ASSERT(la);
2137 la->deleteAllLinks = 1;
2138 ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr,
2139 lnk->src_port, cid, lnk->alias_port, lnk->link_type);
2140 la->deleteAllLinks = 0;
2144 /* Miscellaneous Functions
2147 InitPacketAliasLog()
2148 UninitPacketAliasLog()
2152 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2153 is called to find and remove timed-out aliasing links. Logic exists
2154 to sweep through the entire table and linked list structure
2157 (prototype in alias_local.h)
2161 HouseKeeping(struct libalias *la)
2169 LIBALIAS_LOCK_ASSERT(la);
2171 * Save system time (seconds) in global variable timeStamp for use
2172 * by other functions. This is done so as not to unnecessarily
2173 * waste timeline by making system calls.
2176 la->timeStamp = time_uptime;
2178 gettimeofday(&tv, &tz);
2179 la->timeStamp = tv.tv_sec;
2182 /* Compute number of spokes (output table link chains) to cover */
2183 n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime);
2184 n /= ALIAS_CLEANUP_INTERVAL_SECS;
2186 /* Handle different cases */
2188 if (n > ALIAS_CLEANUP_MAX_SPOKES)
2189 n = ALIAS_CLEANUP_MAX_SPOKES;
2190 la->lastCleanupTime = la->timeStamp;
2191 for (i = 0; i < n; i++)
2192 IncrementalCleanup(la);
2194 #ifdef LIBALIAS_DEBUG
2195 fprintf(stderr, "PacketAlias/HouseKeeping(): ");
2196 fprintf(stderr, "something unexpected in time values\n");
2198 la->lastCleanupTime = la->timeStamp;
2202 /* Init the log file and enable logging */
2204 InitPacketAliasLog(struct libalias *la)
2207 LIBALIAS_LOCK_ASSERT(la);
2208 if (~la->packetAliasMode & PKT_ALIAS_LOG) {
2210 if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
2213 if ((la->logDesc = fopen("/var/log/alias.log", "w")))
2214 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2217 return (ENOMEM); /* log initialization failed */
2218 la->packetAliasMode |= PKT_ALIAS_LOG;
2224 /* Close the log-file and disable logging. */
2226 UninitPacketAliasLog(struct libalias *la)
2229 LIBALIAS_LOCK_ASSERT(la);
2234 fclose(la->logDesc);
2238 la->packetAliasMode &= ~PKT_ALIAS_LOG;
2241 /* Outside world interfaces
2243 -- "outside world" means other than alias*.c routines --
2245 PacketAliasRedirectPort()
2246 PacketAliasAddServer()
2247 PacketAliasRedirectProto()
2248 PacketAliasRedirectAddr()
2249 PacketAliasRedirectDynamic()
2250 PacketAliasRedirectDelete()
2251 PacketAliasSetAddress()
2254 PacketAliasSetMode()
2256 (prototypes in alias.h)
2259 /* Redirection from a specific public addr:port to a
2260 private addr:port */
2262 LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port,
2263 struct in_addr dst_addr, u_short dst_port,
2264 struct in_addr alias_addr, u_short alias_port,
2268 struct alias_link *lnk;
2273 link_type = LINK_UDP;
2276 link_type = LINK_TCP;
2279 #ifdef LIBALIAS_DEBUG
2280 fprintf(stderr, "PacketAliasRedirectPort(): ");
2281 fprintf(stderr, "only TCP and UDP protocols allowed\n");
2287 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2288 src_port, dst_port, alias_port,
2292 lnk->flags |= LINK_PERMANENT;
2294 #ifdef LIBALIAS_DEBUG
2296 fprintf(stderr, "PacketAliasRedirectPort(): "
2297 "call to AddLink() failed\n");
2302 LIBALIAS_UNLOCK(la);
2306 /* Add server to the pool of servers */
2308 LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
2310 struct server *server;
2316 server = malloc(sizeof(struct server));
2318 if (server != NULL) {
2319 struct server *head;
2321 server->addr = addr;
2322 server->port = port;
2326 server->next = server;
2330 for (s = head; s->next != head; s = s->next);
2332 server->next = head;
2334 lnk->server = server;
2339 LIBALIAS_UNLOCK(la);
2343 /* Redirect packets of a given IP protocol from a specific
2344 public address to a private address */
2346 LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr,
2347 struct in_addr dst_addr,
2348 struct in_addr alias_addr,
2351 struct alias_link *lnk;
2354 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2355 NO_SRC_PORT, NO_DEST_PORT, 0,
2359 lnk->flags |= LINK_PERMANENT;
2361 #ifdef LIBALIAS_DEBUG
2363 fprintf(stderr, "PacketAliasRedirectProto(): "
2364 "call to AddLink() failed\n");
2368 LIBALIAS_UNLOCK(la);
2372 /* Static address translation */
2374 LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr,
2375 struct in_addr alias_addr)
2377 struct alias_link *lnk;
2380 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
2385 lnk->flags |= LINK_PERMANENT;
2387 #ifdef LIBALIAS_DEBUG
2389 fprintf(stderr, "PacketAliasRedirectAddr(): "
2390 "call to AddLink() failed\n");
2394 LIBALIAS_UNLOCK(la);
2399 /* Mark the aliasing link dynamic */
2401 LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
2408 if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
2411 lnk->flags &= ~LINK_PERMANENT;
2414 LIBALIAS_UNLOCK(la);
2420 LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
2422 /* This is a dangerous function to put in the API,
2423 because an invalid pointer can crash the program. */
2426 la->deleteAllLinks = 1;
2428 la->deleteAllLinks = 0;
2429 LIBALIAS_UNLOCK(la);
2434 LibAliasSetAddress(struct libalias *la, struct in_addr addr)
2438 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2439 && la->aliasAddress.s_addr != addr.s_addr)
2440 CleanupAliasData(la);
2442 la->aliasAddress = addr;
2443 LIBALIAS_UNLOCK(la);
2448 LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2452 la->targetAddress = target_addr;
2453 LIBALIAS_UNLOCK(la);
2460 while (!LIST_EMPTY(&instancehead))
2461 LibAliasUninit(LIST_FIRST(&instancehead));
2465 LibAliasInit(struct libalias *la)
2474 la = calloc(sizeof *la, 1);
2478 #ifndef _KERNEL /* kernel cleans up on module unload */
2479 if (LIST_EMPTY(&instancehead))
2482 LIST_INSERT_HEAD(&instancehead, la, instancelist);
2485 la->timeStamp = time_uptime;
2486 la->lastCleanupTime = time_uptime;
2488 gettimeofday(&tv, &tz);
2489 la->timeStamp = tv.tv_sec;
2490 la->lastCleanupTime = tv.tv_sec;
2493 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
2494 LIST_INIT(&la->linkTableOut[i]);
2495 for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
2496 LIST_INIT(&la->linkTableIn[i]);
2497 LIBALIAS_LOCK_INIT(la);
2501 la->deleteAllLinks = 1;
2502 CleanupAliasData(la);
2503 la->deleteAllLinks = 0;
2506 la->aliasAddress.s_addr = INADDR_ANY;
2507 la->targetAddress.s_addr = INADDR_ANY;
2509 la->icmpLinkCount = 0;
2510 la->udpLinkCount = 0;
2511 la->tcpLinkCount = 0;
2512 la->pptpLinkCount = 0;
2513 la->protoLinkCount = 0;
2514 la->fragmentIdLinkCount = 0;
2515 la->fragmentPtrLinkCount = 0;
2518 la->cleanupIndex = 0;
2520 la->packetAliasMode = PKT_ALIAS_SAME_PORTS
2521 #ifndef NO_USE_SOCKETS
2522 | PKT_ALIAS_USE_SOCKETS
2524 | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2526 la->fireWallFD = -1;
2529 LibAliasRefreshModules();
2531 LIBALIAS_UNLOCK(la);
2536 LibAliasUninit(struct libalias *la)
2540 la->deleteAllLinks = 1;
2541 CleanupAliasData(la);
2542 la->deleteAllLinks = 0;
2543 UninitPacketAliasLog(la);
2547 LIST_REMOVE(la, instancelist);
2548 LIBALIAS_UNLOCK(la);
2549 LIBALIAS_LOCK_DESTROY(la);
2553 /* Change mode for some operations */
2556 struct libalias *la,
2557 unsigned int flags, /* Which state to bring flags to */
2558 unsigned int mask /* Mask of which flags to affect (use 0 to
2559 * do a probe for flag values) */
2565 /* Enable logging? */
2566 if (flags & mask & PKT_ALIAS_LOG) {
2568 if (InitPacketAliasLog(la) == ENOMEM)
2571 /* _Disable_ logging? */
2572 if (~flags & mask & PKT_ALIAS_LOG) {
2573 UninitPacketAliasLog(la);
2576 /* Start punching holes in the firewall? */
2577 if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2580 /* Stop punching holes in the firewall? */
2581 if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2586 /* Other flags can be set/cleared without special action */
2587 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2588 res = la->packetAliasMode;
2590 LIBALIAS_UNLOCK(la);
2596 LibAliasCheckNewLink(struct libalias *la)
2601 res = la->newDefaultLink;
2602 LIBALIAS_UNLOCK(la);
2610 Code to support firewall punching. This shouldn't really be in this
2611 file, but making variables global is evil too.
2614 /* Firewall include files */
2616 #include <netinet/ip_fw.h>
2621 * helper function, updates the pointer to cmd with the length
2622 * of the current command, and also cleans up the first word of
2623 * the new command in case it has been clobbered before.
2626 next_cmd(ipfw_insn * cmd)
2629 bzero(cmd, sizeof(*cmd));
2634 * A function to fill simple commands of size 1.
2635 * Existing flags are preserved.
2638 fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2639 int flags, u_int16_t arg)
2641 cmd->opcode = opcode;
2642 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2644 return next_cmd(cmd);
2648 fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2650 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1;
2652 cmd->addr.s_addr = addr;
2653 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2657 fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2659 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1;
2661 cmd->ports[0] = cmd->ports[1] = port;
2662 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2666 fill_rule(void *buf, int bufsize, int rulenum,
2667 enum ipfw_opcodes action, int proto,
2668 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
2670 struct ip_fw *rule = (struct ip_fw *)buf;
2671 ipfw_insn *cmd = (ipfw_insn *) rule->cmd;
2673 bzero(buf, bufsize);
2674 rule->rulenum = rulenum;
2676 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto);
2677 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr);
2678 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp);
2679 cmd = fill_ip(cmd, O_IP_DST, da.s_addr);
2680 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
2682 rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2683 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
2685 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2687 return ((char *)cmd - (char *)buf);
2690 static void ClearAllFWHoles(struct libalias *la);
2693 #define fw_setfield(la, field, num) \
2695 (field)[(num) - la->fireWallBaseNum] = 1; \
2696 } /*lint -save -e717 */ while(0)/* lint -restore */
2698 #define fw_clrfield(la, field, num) \
2700 (field)[(num) - la->fireWallBaseNum] = 0; \
2701 } /*lint -save -e717 */ while(0)/* lint -restore */
2703 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2706 InitPunchFW(struct libalias *la)
2709 LIBALIAS_LOCK_ASSERT(la);
2710 la->fireWallField = malloc(la->fireWallNumNums);
2711 if (la->fireWallField) {
2712 memset(la->fireWallField, 0, la->fireWallNumNums);
2713 if (la->fireWallFD < 0) {
2714 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2716 ClearAllFWHoles(la);
2717 la->fireWallActiveNum = la->fireWallBaseNum;
2722 UninitPunchFW(struct libalias *la)
2725 LIBALIAS_LOCK_ASSERT(la);
2726 ClearAllFWHoles(la);
2727 if (la->fireWallFD >= 0)
2728 close(la->fireWallFD);
2729 la->fireWallFD = -1;
2730 if (la->fireWallField)
2731 free(la->fireWallField);
2732 la->fireWallField = NULL;
2733 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2736 /* Make a certain link go through the firewall */
2738 PunchFWHole(struct alias_link *lnk)
2740 struct libalias *la;
2741 int r; /* Result code */
2742 struct ip_fw rule; /* On-the-fly built rule */
2743 int fwhole; /* Where to punch hole */
2745 LIBALIAS_LOCK_ASSERT(la);
2748 /* Don't do anything unless we are asked to */
2749 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2750 la->fireWallFD < 0 ||
2751 lnk->link_type != LINK_TCP)
2754 memset(&rule, 0, sizeof rule);
2758 /* Find empty slot */
2759 for (fwhole = la->fireWallActiveNum;
2760 fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2761 fw_tstfield(la, la->fireWallField, fwhole);
2763 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2764 for (fwhole = la->fireWallBaseNum;
2765 fwhole < la->fireWallActiveNum &&
2766 fw_tstfield(la, la->fireWallField, fwhole);
2768 if (fwhole == la->fireWallActiveNum) {
2769 /* No rule point empty - we can't punch more holes. */
2770 la->fireWallActiveNum = la->fireWallBaseNum;
2771 #ifdef LIBALIAS_DEBUG
2772 fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2777 /* Start next search at next position */
2778 la->fireWallActiveNum = fwhole + 1;
2781 * generate two rules of the form
2783 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2784 * accept tcp from DAddr DPort to OAddr OPort
2786 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2787 u_int32_t rulebuf[255];
2790 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2791 O_ACCEPT, IPPROTO_TCP,
2792 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
2793 GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
2794 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2796 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2798 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2799 O_ACCEPT, IPPROTO_TCP,
2800 GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
2801 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
2802 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2804 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2807 /* Indicate hole applied */
2808 lnk->data.tcp->fwhole = fwhole;
2809 fw_setfield(la, la->fireWallField, fwhole);
2812 /* Remove a hole in a firewall associated with a particular alias
2813 lnk. Calling this too often is harmless. */
2815 ClearFWHole(struct alias_link *lnk)
2817 struct libalias *la;
2819 LIBALIAS_LOCK_ASSERT(la);
2821 if (lnk->link_type == LINK_TCP) {
2822 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall
2829 memset(&rule, 0, sizeof rule); /* useless for ipfw2 */
2830 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL,
2831 &fwhole, sizeof fwhole));
2832 fw_clrfield(la, la->fireWallField, fwhole);
2833 lnk->data.tcp->fwhole = -1;
2837 /* Clear out the entire range dedicated to firewall holes. */
2839 ClearAllFWHoles(struct libalias *la)
2841 struct ip_fw rule; /* On-the-fly built rule */
2844 LIBALIAS_LOCK_ASSERT(la);
2845 if (la->fireWallFD < 0)
2848 memset(&rule, 0, sizeof rule);
2849 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2852 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2854 /* XXX: third arg correct here ? /phk */
2855 memset(la->fireWallField, 0, la->fireWallNumNums);
2861 LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2866 la->fireWallBaseNum = base;
2867 la->fireWallNumNums = num;
2869 LIBALIAS_UNLOCK(la);
2873 LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2877 la->skinnyPort = port;
2878 LIBALIAS_UNLOCK(la);