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: src/sys/netinet/libalias/alias_db.c,v 1.71.2.2.2.1 2008/11/25 02:59:29 kensmith Exp $");
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.
145 #include <sys/param.h>
146 #include <sys/kernel.h>
147 #include <sys/module.h>
148 #include <sys/syslog.h>
149 #include <sys/queue.h>
151 #include <sys/socket.h>
152 #include <netinet/tcp.h>
155 #include "alias_local.h"
156 #include "alias_mod.h"
159 static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
163 Constants (note: constants are also defined
164 near relevant functions or structs)
167 /* Parameters used for cleanup of expired links */
168 /* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */
169 #define ALIAS_CLEANUP_INTERVAL_SECS 64
170 #define ALIAS_CLEANUP_MAX_SPOKES (LINK_TABLE_OUT_SIZE/5)
172 /* Timeouts (in seconds) for different link types */
173 #define ICMP_EXPIRE_TIME 60
174 #define UDP_EXPIRE_TIME 60
175 #define PROTO_EXPIRE_TIME 60
176 #define FRAGMENT_ID_EXPIRE_TIME 10
177 #define FRAGMENT_PTR_EXPIRE_TIME 30
179 /* TCP link expire time for different cases */
180 /* When the link has been used and closed - minimal grace time to
181 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
182 #ifndef TCP_EXPIRE_DEAD
183 #define TCP_EXPIRE_DEAD 10
186 /* When the link has been used and closed on one side - the other side
187 is allowed to still send data */
188 #ifndef TCP_EXPIRE_SINGLEDEAD
189 #define TCP_EXPIRE_SINGLEDEAD 90
192 /* When the link isn't yet up */
193 #ifndef TCP_EXPIRE_INITIAL
194 #define TCP_EXPIRE_INITIAL 300
197 /* When the link is up */
198 #ifndef TCP_EXPIRE_CONNECTED
199 #define TCP_EXPIRE_CONNECTED 86400
203 /* Dummy port number codes used for FindLinkIn/Out() and AddLink().
204 These constants can be anything except zero, which indicates an
205 unknown port number. */
207 #define NO_DEST_PORT 1
208 #define NO_SRC_PORT 1
213 The fundamental data structure used in this program is
214 "struct alias_link". Whenever a TCP connection is made,
215 a UDP datagram is sent out, or an ICMP echo request is made,
216 a link record is made (if it has not already been created).
217 The link record is identified by the source address/port
218 and the destination address/port. In the case of an ICMP
219 echo request, the source port is treated as being equivalent
220 with the 16-bit ID number of the ICMP packet.
222 The link record also can store some auxiliary data. For
223 TCP connections that have had sequence and acknowledgment
224 modifications, data space is available to track these changes.
225 A state field is used to keep track in changes to the TCP
226 connection state. ID numbers of fragments can also be
227 stored in the auxiliary space. Pointers to unresolved
228 fragments can also be stored.
230 The link records support two independent chainings. Lookup
231 tables for input and out tables hold the initial pointers
232 the link chains. On input, the lookup table indexes on alias
233 port and link type. On output, the lookup table indexes on
234 source address, destination address, source port, destination
238 struct ack_data_record { /* used to save changes to ACK/sequence
246 struct tcp_state { /* Information about TCP connection */
247 int in; /* State for outside -> inside */
248 int out; /* State for inside -> outside */
249 int index; /* Index to ACK data array */
250 int ack_modified; /* Indicates whether ACK and
251 * sequence numbers */
255 #define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes
256 * saved for a modified TCP stream */
258 struct tcp_state state;
259 struct ack_data_record ack[N_LINK_TCP_DATA];
260 int fwhole; /* Which firewall record is used for this
264 struct server { /* LSNAT server pool (circular list) */
270 struct alias_link { /* Main data structure */
272 struct in_addr src_addr; /* Address and port information */
273 struct in_addr dst_addr;
274 struct in_addr alias_addr;
275 struct in_addr proxy_addr;
280 struct server *server;
282 int link_type; /* Type of link: TCP, UDP, ICMP,
285 /* values for link_type */
286 #define LINK_ICMP IPPROTO_ICMP
287 #define LINK_UDP IPPROTO_UDP
288 #define LINK_TCP IPPROTO_TCP
289 #define LINK_FRAGMENT_ID (IPPROTO_MAX + 1)
290 #define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2)
291 #define LINK_ADDR (IPPROTO_MAX + 3)
292 #define LINK_PPTP (IPPROTO_MAX + 4)
294 int flags; /* indicates special characteristics */
295 int pflags; /* protocol-specific flags */
298 #define LINK_UNKNOWN_DEST_PORT 0x01
299 #define LINK_UNKNOWN_DEST_ADDR 0x02
300 #define LINK_PERMANENT 0x04
301 #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
302 #define LINK_UNFIREWALLED 0x08
304 int timestamp; /* Time link was last accessed */
305 int expire_time; /* Expire time for link */
306 #ifndef NO_USE_SOCKETS
307 int sockfd; /* socket descriptor */
309 LIST_ENTRY (alias_link) list_out; /* Linked list of
311 LIST_ENTRY (alias_link) list_in; /* input and output
314 union { /* Auxiliary data */
316 struct in_addr frag_addr;
321 /* Clean up procedure. */
322 static void finishoff(void);
324 /* Kernel module definition. */
326 MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing");
328 MODULE_VERSION(libalias, 1);
331 alias_mod_handler(module_t mod, int type, void *data)
338 handler_chain_init();
341 handler_chain_destroy();
352 static moduledata_t alias_mod = {
353 "alias", alias_mod_handler, NULL
356 DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
359 /* Internal utility routines (used only in alias_db.c)
361 Lookup table starting points:
362 StartPointIn() -- link table initial search point for
364 StartPointOut() -- link table initial search point for
368 SeqDiff() -- difference between two TCP sequences
369 ShowAliasStats() -- send alias statistics to a monitor file
373 /* Local prototypes */
374 static u_int StartPointIn(struct in_addr, u_short, int);
377 StartPointOut(struct in_addr, struct in_addr,
378 u_short, u_short, int);
380 static int SeqDiff(u_long, u_long);
383 /* Firewall control */
384 static void InitPunchFW(struct libalias *);
385 static void UninitPunchFW(struct libalias *);
386 static void ClearFWHole(struct alias_link *);
390 /* Log file control */
391 static void ShowAliasStats(struct libalias *);
392 static int InitPacketAliasLog(struct libalias *);
393 static void UninitPacketAliasLog(struct libalias *);
396 StartPointIn(struct in_addr alias_addr,
402 n = alias_addr.s_addr;
403 if (link_type != LINK_PPTP)
406 return (n % LINK_TABLE_IN_SIZE);
411 StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
412 u_short src_port, u_short dst_port, int link_type)
417 n += dst_addr.s_addr;
418 if (link_type != LINK_PPTP) {
424 return (n % LINK_TABLE_OUT_SIZE);
429 SeqDiff(u_long x, u_long y)
431 /* Return the difference between two TCP sequence numbers */
434 This function is encapsulated in case there are any unusual
435 arithmetic conditions that need to be considered.
438 return (ntohl(y) - ntohl(x));
444 AliasLog(char *str, const char *format, ...)
448 va_start(ap, format);
449 kvsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
454 AliasLog(FILE *stream, const char *format, ...)
458 va_start(ap, format);
459 vfprintf(stream, format, ap);
466 ShowAliasStats(struct libalias *la)
469 LIBALIAS_LOCK_ASSERT(la);
470 /* Used for debugging */
472 int tot = la->icmpLinkCount + la->udpLinkCount +
473 la->tcpLinkCount + la->pptpLinkCount +
474 la->protoLinkCount + la->fragmentIdLinkCount +
475 la->fragmentPtrLinkCount;
477 AliasLog(la->logDesc,
478 "icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
484 la->fragmentIdLinkCount,
485 la->fragmentPtrLinkCount, tot);
487 AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
492 /* Internal routines for finding, deleting and adding links
495 GetNewPort() -- find and reserve new alias port number
496 GetSocket() -- try to allocate a socket for a given port
498 Link creation and deletion:
499 CleanupAliasData() - remove all link chains from lookup table
500 IncrementalCleanup() - look for stale links in a single chain
501 DeleteLink() - remove link
503 ReLink() - change link
506 FindLinkOut() - find link for outgoing packets
507 FindLinkIn() - find link for incoming packets
510 FindNewPortGroup() - find an available group of ports
513 /* Local prototypes */
514 static int GetNewPort(struct libalias *, struct alias_link *, int);
515 #ifndef NO_USE_SOCKETS
516 static u_short GetSocket(struct libalias *, u_short, int *, int);
518 static void CleanupAliasData(struct libalias *);
520 static void IncrementalCleanup(struct libalias *);
522 static void DeleteLink(struct alias_link *);
524 static struct alias_link *
525 AddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr,
526 u_short, u_short, int, int);
528 static struct alias_link *
529 ReLink(struct alias_link *,
530 struct in_addr, struct in_addr, struct in_addr,
531 u_short, u_short, int, int);
533 static struct alias_link *
534 FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
536 static struct alias_link *
537 FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
540 #define ALIAS_PORT_BASE 0x08000
541 #define ALIAS_PORT_MASK 0x07fff
542 #define ALIAS_PORT_MASK_EVEN 0x07ffe
543 #define GET_NEW_PORT_MAX_ATTEMPTS 20
545 #define GET_ALIAS_PORT -1
546 #define GET_ALIAS_ID GET_ALIAS_PORT
548 #define FIND_EVEN_ALIAS_BASE 1
550 /* GetNewPort() allocates port numbers. Note that if a port number
551 is already in use, that does not mean that it cannot be used by
552 another link concurrently. This is because GetNewPort() looks for
553 unused triplets: (dest addr, dest port, alias port). */
556 GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
563 LIBALIAS_LOCK_ASSERT(la);
565 Description of alias_port_param for GetNewPort(). When
566 this parameter is zero or positive, it precisely specifies
567 the port number. GetNewPort() will return this number
568 without check that it is in use.
570 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
571 selected port number.
574 if (alias_port_param == GET_ALIAS_PORT) {
576 * The aliasing port is automatically selected by one of
579 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
581 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
583 * When the PKT_ALIAS_SAME_PORTS option is chosen,
584 * the first try will be the actual source port. If
585 * this is already in use, the remainder of the
586 * trials will be random.
588 port_net = lnk->src_port;
589 port_sys = ntohs(port_net);
591 /* First trial and all subsequent are random. */
592 port_sys = krandom() & ALIAS_PORT_MASK;
593 port_sys += ALIAS_PORT_BASE;
594 port_net = htons(port_sys);
596 } else if (alias_port_param >= 0 && alias_port_param < 0x10000) {
597 lnk->alias_port = (u_short) alias_port_param;
600 #ifdef LIBALIAS_DEBUG
601 fprintf(stderr, "PacketAlias/GetNewPort(): ");
602 fprintf(stderr, "input parameter error\n");
608 /* Port number search */
609 for (i = 0; i < max_trials; i++) {
611 struct alias_link *search_result;
613 search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr,
614 lnk->dst_port, port_net,
617 if (search_result == NULL)
619 else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED)
620 && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
626 #ifndef NO_USE_SOCKETS
627 if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS)
628 && (lnk->flags & LINK_PARTIALLY_SPECIFIED)
629 && ((lnk->link_type == LINK_TCP) ||
630 (lnk->link_type == LINK_UDP))) {
631 if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) {
632 lnk->alias_port = port_net;
637 lnk->alias_port = port_net;
639 #ifndef NO_USE_SOCKETS
643 port_sys = krandom() & ALIAS_PORT_MASK;
644 port_sys += ALIAS_PORT_BASE;
645 port_net = htons(port_sys);
648 #ifdef LIBALIAS_DEBUG
649 fprintf(stderr, "PacketAlias/GetnewPort(): ");
650 fprintf(stderr, "could not find free port\n");
656 #ifndef NO_USE_SOCKETS
658 GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
662 struct sockaddr_in sock_addr;
664 LIBALIAS_LOCK_ASSERT(la);
665 if (link_type == LINK_TCP)
666 sock = socket(AF_INET, SOCK_STREAM, 0);
667 else if (link_type == LINK_UDP)
668 sock = socket(AF_INET, SOCK_DGRAM, 0);
670 #ifdef LIBALIAS_DEBUG
671 fprintf(stderr, "PacketAlias/GetSocket(): ");
672 fprintf(stderr, "incorrect link type\n");
678 #ifdef LIBALIAS_DEBUG
679 fprintf(stderr, "PacketAlias/GetSocket(): ");
680 fprintf(stderr, "socket() error %d\n", *sockfd);
684 sock_addr.sin_family = AF_INET;
685 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
686 sock_addr.sin_port = port_net;
689 (struct sockaddr *)&sock_addr,
702 /* FindNewPortGroup() returns a base port number for an available
703 range of contiguous port numbers. Note that if a port number
704 is already in use, that does not mean that it cannot be used by
705 another link concurrently. This is because FindNewPortGroup()
706 looks for unused triplets: (dest addr, dest port, alias port). */
709 FindNewPortGroup(struct libalias *la,
710 struct in_addr dst_addr,
711 struct in_addr alias_addr,
723 LIBALIAS_LOCK_ASSERT(la);
725 * Get link_type from protocol
730 link_type = LINK_UDP;
733 link_type = LINK_TCP;
741 * The aliasing port is automatically selected by one of two
744 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
746 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
748 * When the ALIAS_SAME_PORTS option is chosen, the first
749 * try will be the actual source port. If this is already
750 * in use, the remainder of the trials will be random.
752 port_sys = ntohs(src_port);
756 /* First trial and all subsequent are random. */
757 if (align == FIND_EVEN_ALIAS_BASE)
758 port_sys = krandom() & ALIAS_PORT_MASK_EVEN;
760 port_sys = krandom() & ALIAS_PORT_MASK;
762 port_sys += ALIAS_PORT_BASE;
765 /* Port number search */
766 for (i = 0; i < max_trials; i++) {
768 struct alias_link *search_result;
770 for (j = 0; j < port_count; j++)
771 if (0 != (search_result = FindLinkIn(la, dst_addr, alias_addr,
772 dst_port, htons(port_sys + j),
776 /* Found a good range, return base */
778 return (htons(port_sys));
780 /* Find a new base to try */
781 if (align == FIND_EVEN_ALIAS_BASE)
782 port_sys = krandom() & ALIAS_PORT_MASK_EVEN;
784 port_sys = krandom() & ALIAS_PORT_MASK;
786 port_sys += ALIAS_PORT_BASE;
789 #ifdef LIBALIAS_DEBUG
790 fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
791 fprintf(stderr, "could not find free port(s)\n");
798 CleanupAliasData(struct libalias *la)
800 struct alias_link *lnk;
803 LIBALIAS_LOCK_ASSERT(la);
804 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) {
805 lnk = LIST_FIRST(&la->linkTableOut[i]);
806 while (lnk != NULL) {
807 struct alias_link *link_next = LIST_NEXT(lnk, list_out);
813 la->cleanupIndex = 0;
818 IncrementalCleanup(struct libalias *la)
820 struct alias_link *lnk, *lnk_tmp;
822 LIBALIAS_LOCK_ASSERT(la);
824 LIST_FOREACH_MUTABLE(lnk, &la->linkTableOut[la->cleanupIndex++],list_out, lnk_tmp) {
825 if (la->timeStamp - lnk->timestamp > lnk->expire_time)
829 if (la->cleanupIndex == LINK_TABLE_OUT_SIZE)
830 la->cleanupIndex = 0;
834 DeleteLink(struct alias_link *lnk)
836 struct libalias *la = lnk->la;
838 LIBALIAS_LOCK_ASSERT(la);
839 /* Don't do anything if the link is marked permanent */
840 if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT)
844 /* Delete associated firewall hole, if any */
848 /* Free memory allocated for LSNAT server pool */
849 if (lnk->server != NULL) {
850 struct server *head, *curr, *next;
852 head = curr = lnk->server;
856 } while ((curr = next) != head);
858 /* Adjust output table pointers */
859 LIST_REMOVE(lnk, list_out);
861 /* Adjust input table pointers */
862 LIST_REMOVE(lnk, list_in);
863 #ifndef NO_USE_SOCKETS
864 /* Close socket, if one has been allocated */
865 if (lnk->sockfd != -1) {
870 /* Link-type dependent cleanup */
871 switch (lnk->link_type) {
880 kfree(lnk->data.tcp,M_ALIAS);
885 case LINK_FRAGMENT_ID:
886 la->fragmentIdLinkCount--;
888 case LINK_FRAGMENT_PTR:
889 la->fragmentPtrLinkCount--;
890 if (lnk->data.frag_ptr != NULL)
891 kfree(lnk->data.frag_ptr,M_ALIAS);
896 la->protoLinkCount--;
903 /* Write statistics, if logging enabled */
904 if (la->packetAliasMode & PKT_ALIAS_LOG) {
910 static struct alias_link *
911 AddLink(struct libalias *la, struct in_addr src_addr,
912 struct in_addr dst_addr,
913 struct in_addr alias_addr,
916 int alias_port_param, /* if less than zero, alias */
918 { /* port will be automatically *//* chosen.
920 u_int start_point; /* zero, equal to alias port */
921 struct alias_link *lnk;
923 LIBALIAS_LOCK_ASSERT(la);
924 lnk = kmalloc(sizeof(struct alias_link),M_ALIAS, M_WAITOK | M_ZERO);
926 /* Basic initialization */
928 lnk->src_addr = src_addr;
929 lnk->dst_addr = dst_addr;
930 lnk->alias_addr = alias_addr;
931 lnk->proxy_addr.s_addr = INADDR_ANY;
932 lnk->src_port = src_port;
933 lnk->dst_port = dst_port;
936 lnk->link_type = link_type;
937 #ifndef NO_USE_SOCKETS
942 lnk->timestamp = la->timeStamp;
944 /* Expiration time */
947 lnk->expire_time = ICMP_EXPIRE_TIME;
950 lnk->expire_time = UDP_EXPIRE_TIME;
953 lnk->expire_time = TCP_EXPIRE_INITIAL;
956 lnk->flags |= LINK_PERMANENT; /* no timeout. */
958 case LINK_FRAGMENT_ID:
959 lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME;
961 case LINK_FRAGMENT_PTR:
962 lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
967 lnk->expire_time = PROTO_EXPIRE_TIME;
971 /* Determine alias flags */
972 if (dst_addr.s_addr == INADDR_ANY)
973 lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
975 lnk->flags |= LINK_UNKNOWN_DEST_PORT;
977 /* Determine alias port */
978 if (GetNewPort(la, lnk, alias_port_param) != 0) {
982 /* Link-type dependent initialization */
984 struct tcp_dat *aux_tcp;
993 aux_tcp = kmalloc(sizeof(struct tcp_dat),M_ALIAS, M_WAITOK | M_ZERO);
994 if (aux_tcp != NULL) {
998 aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
999 aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
1000 aux_tcp->state.index = 0;
1001 aux_tcp->state.ack_modified = 0;
1002 for (i = 0; i < N_LINK_TCP_DATA; i++)
1003 aux_tcp->ack[i].active = 0;
1004 aux_tcp->fwhole = -1;
1005 lnk->data.tcp = aux_tcp;
1007 #ifdef LIBALIAS_DEBUG
1008 fprintf(stderr, "PacketAlias/AddLink: ");
1009 fprintf(stderr, " cannot allocate auxiliary TCP data\n");
1016 la->pptpLinkCount++;
1018 case LINK_FRAGMENT_ID:
1019 la->fragmentIdLinkCount++;
1021 case LINK_FRAGMENT_PTR:
1022 la->fragmentPtrLinkCount++;
1027 la->protoLinkCount++;
1031 /* Set up pointers for output lookup table */
1032 start_point = StartPointOut(src_addr, dst_addr,
1033 src_port, dst_port, link_type);
1034 LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out);
1036 /* Set up pointers for input lookup table */
1037 start_point = StartPointIn(alias_addr, lnk->alias_port, link_type);
1038 LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in);
1040 #ifdef LIBALIAS_DEBUG
1041 fprintf(stderr, "PacketAlias/AddLink(): ");
1042 fprintf(stderr, "kmalloc() call failed.\n");
1045 if (la->packetAliasMode & PKT_ALIAS_LOG) {
1051 static struct alias_link *
1052 ReLink(struct alias_link *old_lnk,
1053 struct in_addr src_addr,
1054 struct in_addr dst_addr,
1055 struct in_addr alias_addr,
1058 int alias_port_param, /* if less than zero, alias */
1060 { /* port will be automatically *//* chosen.
1061 * If greater than */
1062 struct alias_link *new_lnk; /* zero, equal to alias port */
1063 struct libalias *la = old_lnk->la;
1065 LIBALIAS_LOCK_ASSERT(la);
1066 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1067 src_port, dst_port, alias_port_param,
1070 if (new_lnk != NULL &&
1071 old_lnk->link_type == LINK_TCP &&
1072 old_lnk->data.tcp->fwhole > 0) {
1073 PunchFWHole(new_lnk);
1076 DeleteLink(old_lnk);
1080 static struct alias_link *
1081 _FindLinkOut(struct libalias *la, struct in_addr src_addr,
1082 struct in_addr dst_addr,
1086 int replace_partial_links)
1089 struct alias_link *lnk;
1091 LIBALIAS_LOCK_ASSERT(la);
1092 i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
1093 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) {
1094 if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
1095 lnk->src_addr.s_addr == src_addr.s_addr &&
1096 lnk->src_port == src_port &&
1097 lnk->dst_port == dst_port &&
1098 lnk->link_type == link_type &&
1099 lnk->server == NULL) {
1100 lnk->timestamp = la->timeStamp;
1105 /* Search for partially specified links. */
1106 if (lnk == NULL && replace_partial_links) {
1107 if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
1108 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0,
1111 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port,
1112 dst_port, link_type, 0);
1115 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
1116 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0,
1121 src_addr, dst_addr, lnk->alias_addr,
1122 src_port, dst_port, lnk->alias_port,
1129 static struct alias_link *
1130 FindLinkOut(struct libalias *la, struct in_addr src_addr,
1131 struct in_addr dst_addr,
1135 int replace_partial_links)
1137 struct alias_link *lnk;
1139 LIBALIAS_LOCK_ASSERT(la);
1140 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port,
1141 link_type, replace_partial_links);
1145 * The following allows permanent links to be specified as
1146 * using the default source address (i.e. device interface
1147 * address) without knowing in advance what that address
1150 if (la->aliasAddress.s_addr != INADDR_ANY &&
1151 src_addr.s_addr == la->aliasAddress.s_addr) {
1152 lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port,
1153 link_type, replace_partial_links);
1160 static struct alias_link *
1161 _FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1162 struct in_addr alias_addr,
1166 int replace_partial_links)
1170 struct alias_link *lnk;
1171 struct alias_link *lnk_fully_specified;
1172 struct alias_link *lnk_unknown_all;
1173 struct alias_link *lnk_unknown_dst_addr;
1174 struct alias_link *lnk_unknown_dst_port;
1176 LIBALIAS_LOCK_ASSERT(la);
1177 /* Initialize pointers */
1178 lnk_fully_specified = NULL;
1179 lnk_unknown_all = NULL;
1180 lnk_unknown_dst_addr = NULL;
1181 lnk_unknown_dst_port = NULL;
1183 /* If either the dest addr or port is unknown, the search
1184 loop will have to know about this. */
1187 if (dst_addr.s_addr == INADDR_ANY)
1188 flags_in |= LINK_UNKNOWN_DEST_ADDR;
1190 flags_in |= LINK_UNKNOWN_DEST_PORT;
1193 start_point = StartPointIn(alias_addr, alias_port, link_type);
1194 LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) {
1197 flags = flags_in | lnk->flags;
1198 if (!(flags & LINK_PARTIALLY_SPECIFIED)) {
1199 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1200 && lnk->alias_port == alias_port
1201 && lnk->dst_addr.s_addr == dst_addr.s_addr
1202 && lnk->dst_port == dst_port
1203 && lnk->link_type == link_type) {
1204 lnk_fully_specified = lnk;
1207 } else if ((flags & LINK_UNKNOWN_DEST_ADDR)
1208 && (flags & LINK_UNKNOWN_DEST_PORT)) {
1209 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1210 && lnk->alias_port == alias_port
1211 && lnk->link_type == link_type) {
1212 if (lnk_unknown_all == NULL)
1213 lnk_unknown_all = lnk;
1215 } else if (flags & LINK_UNKNOWN_DEST_ADDR) {
1216 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1217 && lnk->alias_port == alias_port
1218 && lnk->link_type == link_type
1219 && lnk->dst_port == dst_port) {
1220 if (lnk_unknown_dst_addr == NULL)
1221 lnk_unknown_dst_addr = lnk;
1223 } else if (flags & LINK_UNKNOWN_DEST_PORT) {
1224 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1225 && lnk->alias_port == alias_port
1226 && lnk->link_type == link_type
1227 && lnk->dst_addr.s_addr == dst_addr.s_addr) {
1228 if (lnk_unknown_dst_port == NULL)
1229 lnk_unknown_dst_port = lnk;
1236 if (lnk_fully_specified != NULL) {
1237 lnk_fully_specified->timestamp = la->timeStamp;
1238 lnk = lnk_fully_specified;
1239 } else if (lnk_unknown_dst_port != NULL)
1240 lnk = lnk_unknown_dst_port;
1241 else if (lnk_unknown_dst_addr != NULL)
1242 lnk = lnk_unknown_dst_addr;
1243 else if (lnk_unknown_all != NULL)
1244 lnk = lnk_unknown_all;
1248 if (replace_partial_links &&
1249 (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) {
1250 struct in_addr src_addr;
1253 if (lnk->server != NULL) { /* LSNAT link */
1254 src_addr = lnk->server->addr;
1255 src_port = lnk->server->port;
1256 lnk->server = lnk->server->next;
1258 src_addr = lnk->src_addr;
1259 src_port = lnk->src_port;
1263 src_addr, dst_addr, alias_addr,
1264 src_port, dst_port, alias_port,
1270 static struct alias_link *
1271 FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1272 struct in_addr alias_addr,
1276 int replace_partial_links)
1278 struct alias_link *lnk;
1280 LIBALIAS_LOCK_ASSERT(la);
1281 lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port,
1282 link_type, replace_partial_links);
1286 * The following allows permanent links to be specified as
1287 * using the default aliasing address (i.e. device
1288 * interface address) without knowing in advance what that
1291 if (la->aliasAddress.s_addr != INADDR_ANY &&
1292 alias_addr.s_addr == la->aliasAddress.s_addr) {
1293 lnk = _FindLinkIn(la, dst_addr, la->nullAddress, dst_port, alias_port,
1294 link_type, replace_partial_links);
1303 /* External routines for finding/adding links
1305 -- "external" means outside alias_db.c, but within alias*.c --
1307 FindIcmpIn(), FindIcmpOut()
1308 FindFragmentIn1(), FindFragmentIn2()
1309 AddFragmentPtrLink(), FindFragmentPtr()
1310 FindProtoIn(), FindProtoOut()
1311 FindUdpTcpIn(), FindUdpTcpOut()
1312 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1313 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1314 FindOriginalAddress(), FindAliasAddress()
1316 (prototypes in alias_local.h)
1321 FindIcmpIn(struct libalias *la, struct in_addr dst_addr,
1322 struct in_addr alias_addr,
1326 struct alias_link *lnk;
1328 LIBALIAS_LOCK_ASSERT(la);
1329 lnk = FindLinkIn(la, dst_addr, alias_addr,
1330 NO_DEST_PORT, id_alias,
1332 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1333 struct in_addr target_addr;
1335 target_addr = FindOriginalAddress(la, alias_addr);
1336 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1337 id_alias, NO_DEST_PORT, id_alias,
1345 FindIcmpOut(struct libalias *la, struct in_addr src_addr,
1346 struct in_addr dst_addr,
1350 struct alias_link *lnk;
1352 LIBALIAS_LOCK_ASSERT(la);
1353 lnk = FindLinkOut(la, src_addr, dst_addr,
1356 if (lnk == NULL && create) {
1357 struct in_addr alias_addr;
1359 alias_addr = FindAliasAddress(la, src_addr);
1360 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1361 id, NO_DEST_PORT, GET_ALIAS_ID,
1369 FindFragmentIn1(struct libalias *la, struct in_addr dst_addr,
1370 struct in_addr alias_addr,
1373 struct alias_link *lnk;
1375 LIBALIAS_LOCK_ASSERT(la);
1376 lnk = FindLinkIn(la, dst_addr, alias_addr,
1377 NO_DEST_PORT, ip_id,
1378 LINK_FRAGMENT_ID, 0);
1381 lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr,
1382 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1390 FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if
1392 struct in_addr alias_addr, /* is not found. */
1396 LIBALIAS_LOCK_ASSERT(la);
1397 return FindLinkIn(la, dst_addr, alias_addr,
1398 NO_DEST_PORT, ip_id,
1399 LINK_FRAGMENT_ID, 0);
1404 AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr,
1408 LIBALIAS_LOCK_ASSERT(la);
1409 return AddLink(la, la->nullAddress, dst_addr, la->nullAddress,
1410 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1416 FindFragmentPtr(struct libalias *la, struct in_addr dst_addr,
1420 LIBALIAS_LOCK_ASSERT(la);
1421 return FindLinkIn(la, dst_addr, la->nullAddress,
1422 NO_DEST_PORT, ip_id,
1423 LINK_FRAGMENT_PTR, 0);
1428 FindProtoIn(struct libalias *la, struct in_addr dst_addr,
1429 struct in_addr alias_addr,
1432 struct alias_link *lnk;
1434 LIBALIAS_LOCK_ASSERT(la);
1435 lnk = FindLinkIn(la, dst_addr, alias_addr,
1439 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1440 struct in_addr target_addr;
1442 target_addr = FindOriginalAddress(la, alias_addr);
1443 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1444 NO_SRC_PORT, NO_DEST_PORT, 0,
1452 FindProtoOut(struct libalias *la, struct in_addr src_addr,
1453 struct in_addr dst_addr,
1456 struct alias_link *lnk;
1458 LIBALIAS_LOCK_ASSERT(la);
1459 lnk = FindLinkOut(la, src_addr, dst_addr,
1460 NO_SRC_PORT, NO_DEST_PORT,
1464 struct in_addr alias_addr;
1466 alias_addr = FindAliasAddress(la, src_addr);
1467 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1468 NO_SRC_PORT, NO_DEST_PORT, 0,
1476 FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr,
1477 struct in_addr alias_addr,
1484 struct alias_link *lnk;
1486 LIBALIAS_LOCK_ASSERT(la);
1489 link_type = LINK_UDP;
1492 link_type = LINK_TCP;
1499 lnk = FindLinkIn(la, dst_addr, alias_addr,
1500 dst_port, alias_port,
1503 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1504 struct in_addr target_addr;
1506 target_addr = FindOriginalAddress(la, alias_addr);
1507 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1508 alias_port, dst_port, alias_port,
1516 FindUdpTcpOut(struct libalias *la, struct in_addr src_addr,
1517 struct in_addr dst_addr,
1524 struct alias_link *lnk;
1526 LIBALIAS_LOCK_ASSERT(la);
1529 link_type = LINK_UDP;
1532 link_type = LINK_TCP;
1539 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create);
1541 if (lnk == NULL && create) {
1542 struct in_addr alias_addr;
1544 alias_addr = FindAliasAddress(la, src_addr);
1545 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1546 src_port, dst_port, GET_ALIAS_PORT,
1554 AddPptp(struct libalias *la, struct in_addr src_addr,
1555 struct in_addr dst_addr,
1556 struct in_addr alias_addr,
1557 u_int16_t src_call_id)
1559 struct alias_link *lnk;
1561 LIBALIAS_LOCK_ASSERT(la);
1562 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1563 src_call_id, 0, GET_ALIAS_PORT,
1571 FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr,
1572 struct in_addr dst_addr,
1573 u_int16_t src_call_id)
1576 struct alias_link *lnk;
1578 LIBALIAS_LOCK_ASSERT(la);
1579 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1580 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1581 if (lnk->link_type == LINK_PPTP &&
1582 lnk->src_addr.s_addr == src_addr.s_addr &&
1583 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1584 lnk->src_port == src_call_id)
1592 FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr,
1593 struct in_addr dst_addr,
1594 u_int16_t dst_call_id)
1597 struct alias_link *lnk;
1599 LIBALIAS_LOCK_ASSERT(la);
1600 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1601 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1602 if (lnk->link_type == LINK_PPTP &&
1603 lnk->src_addr.s_addr == src_addr.s_addr &&
1604 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1605 lnk->dst_port == dst_call_id)
1613 FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr,
1614 struct in_addr alias_addr,
1615 u_int16_t dst_call_id)
1618 struct alias_link *lnk;
1620 LIBALIAS_LOCK_ASSERT(la);
1621 i = StartPointIn(alias_addr, 0, LINK_PPTP);
1622 LIST_FOREACH(lnk, &la->linkTableIn[i], list_in)
1623 if (lnk->link_type == LINK_PPTP &&
1624 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1625 lnk->alias_addr.s_addr == alias_addr.s_addr &&
1626 lnk->dst_port == dst_call_id)
1634 FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr,
1635 struct in_addr alias_addr,
1636 u_int16_t alias_call_id)
1638 struct alias_link *lnk;
1640 LIBALIAS_LOCK_ASSERT(la);
1641 lnk = FindLinkIn(la, dst_addr, alias_addr,
1642 0 /* any */ , alias_call_id,
1651 FindRtspOut(struct libalias *la, struct in_addr src_addr,
1652 struct in_addr dst_addr,
1658 struct alias_link *lnk;
1660 LIBALIAS_LOCK_ASSERT(la);
1663 link_type = LINK_UDP;
1666 link_type = LINK_TCP;
1673 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1);
1676 struct in_addr alias_addr;
1678 alias_addr = FindAliasAddress(la, src_addr);
1679 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1680 src_port, 0, alias_port,
1688 FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
1690 struct alias_link *lnk;
1692 LIBALIAS_LOCK_ASSERT(la);
1693 lnk = FindLinkIn(la, la->nullAddress, alias_addr,
1694 0, 0, LINK_ADDR, 0);
1696 la->newDefaultLink = 1;
1697 if (la->targetAddress.s_addr == INADDR_ANY)
1698 return (alias_addr);
1699 else if (la->targetAddress.s_addr == INADDR_NONE)
1700 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1701 la->aliasAddress : alias_addr;
1703 return (la->targetAddress);
1705 if (lnk->server != NULL) { /* LSNAT link */
1706 struct in_addr src_addr;
1708 src_addr = lnk->server->addr;
1709 lnk->server = lnk->server->next;
1711 } else if (lnk->src_addr.s_addr == INADDR_ANY)
1712 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1713 la->aliasAddress : alias_addr;
1715 return (lnk->src_addr);
1721 FindAliasAddress(struct libalias *la, struct in_addr original_addr)
1723 struct alias_link *lnk;
1725 LIBALIAS_LOCK_ASSERT(la);
1726 lnk = FindLinkOut(la, original_addr, la->nullAddress,
1727 0, 0, LINK_ADDR, 0);
1729 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1730 la->aliasAddress : original_addr;
1732 if (lnk->alias_addr.s_addr == INADDR_ANY)
1733 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1734 la->aliasAddress : original_addr;
1736 return (lnk->alias_addr);
1741 /* External routines for getting or changing link data
1742 (external to alias_db.c, but internal to alias*.c)
1744 SetFragmentData(), GetFragmentData()
1745 SetFragmentPtr(), GetFragmentPtr()
1746 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1747 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1748 GetOriginalPort(), GetAliasPort()
1749 SetAckModified(), GetAckModified()
1750 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1751 SetProtocolFlags(), GetProtocolFlags()
1757 SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
1759 lnk->data.frag_addr = src_addr;
1764 GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
1766 *src_addr = lnk->data.frag_addr;
1771 SetFragmentPtr(struct alias_link *lnk, char *fptr)
1773 lnk->data.frag_ptr = fptr;
1778 GetFragmentPtr(struct alias_link *lnk, char **fptr)
1780 *fptr = lnk->data.frag_ptr;
1785 SetStateIn(struct alias_link *lnk, int state)
1787 /* TCP input state */
1789 case ALIAS_TCP_STATE_DISCONNECTED:
1790 if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED)
1791 lnk->expire_time = TCP_EXPIRE_DEAD;
1793 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1795 case ALIAS_TCP_STATE_CONNECTED:
1796 if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED)
1797 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1801 panic("libalias:SetStateIn() unknown state");
1806 lnk->data.tcp->state.in = state;
1811 SetStateOut(struct alias_link *lnk, int state)
1813 /* TCP output state */
1815 case ALIAS_TCP_STATE_DISCONNECTED:
1816 if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED)
1817 lnk->expire_time = TCP_EXPIRE_DEAD;
1819 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1821 case ALIAS_TCP_STATE_CONNECTED:
1822 if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED)
1823 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1827 panic("libalias:SetStateOut() unknown state");
1832 lnk->data.tcp->state.out = state;
1837 GetStateIn(struct alias_link *lnk)
1839 /* TCP input state */
1840 return (lnk->data.tcp->state.in);
1845 GetStateOut(struct alias_link *lnk)
1847 /* TCP output state */
1848 return (lnk->data.tcp->state.out);
1853 GetOriginalAddress(struct alias_link *lnk)
1855 if (lnk->src_addr.s_addr == INADDR_ANY)
1856 return (lnk->la->aliasAddress);
1858 return (lnk->src_addr);
1863 GetDestAddress(struct alias_link *lnk)
1865 return (lnk->dst_addr);
1870 GetAliasAddress(struct alias_link *lnk)
1872 if (lnk->alias_addr.s_addr == INADDR_ANY)
1873 return (lnk->la->aliasAddress);
1875 return (lnk->alias_addr);
1880 GetDefaultAliasAddress(struct libalias *la)
1883 LIBALIAS_LOCK_ASSERT(la);
1884 return (la->aliasAddress);
1889 SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
1892 LIBALIAS_LOCK_ASSERT(la);
1893 la->aliasAddress = alias_addr;
1898 GetOriginalPort(struct alias_link *lnk)
1900 return (lnk->src_port);
1905 GetAliasPort(struct alias_link *lnk)
1907 return (lnk->alias_port);
1912 GetDestPort(struct alias_link *lnk)
1914 return (lnk->dst_port);
1920 SetAckModified(struct alias_link *lnk)
1922 /* Indicate that ACK numbers have been modified in a TCP connection */
1923 lnk->data.tcp->state.ack_modified = 1;
1928 GetProxyAddress(struct alias_link *lnk)
1930 return (lnk->proxy_addr);
1935 SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
1937 lnk->proxy_addr = addr;
1942 GetProxyPort(struct alias_link *lnk)
1944 return (lnk->proxy_port);
1949 SetProxyPort(struct alias_link *lnk, u_short port)
1951 lnk->proxy_port = port;
1956 GetAckModified(struct alias_link *lnk)
1958 /* See if ACK numbers have been modified */
1959 return (lnk->data.tcp->state.ack_modified);
1964 GetDeltaAckIn(struct ip *pip, struct alias_link *lnk)
1967 Find out how much the ACK number has been altered for an incoming
1968 TCP packet. To do this, a circular list of ACK numbers where the TCP
1969 packet size was altered is searched.
1974 int delta, ack_diff_min;
1982 for (i = 0; i < N_LINK_TCP_DATA; i++) {
1983 struct ack_data_record x;
1985 x = lnk->data.tcp->ack[i];
1986 if (x.active == 1) {
1989 ack_diff = SeqDiff(x.ack_new, ack);
1990 if (ack_diff >= 0) {
1991 if (ack_diff_min >= 0) {
1992 if (ack_diff < ack_diff_min) {
1994 ack_diff_min = ack_diff;
1998 ack_diff_min = ack_diff;
2008 GetDeltaSeqOut(struct ip *pip, struct alias_link *lnk)
2011 Find out how much the sequence number has been altered for an outgoing
2012 TCP packet. To do this, a circular list of ACK numbers where the TCP
2013 packet size was altered is searched.
2018 int delta, seq_diff_min;
2026 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2027 struct ack_data_record x;
2029 x = lnk->data.tcp->ack[i];
2030 if (x.active == 1) {
2033 seq_diff = SeqDiff(x.ack_old, seq);
2034 if (seq_diff >= 0) {
2035 if (seq_diff_min >= 0) {
2036 if (seq_diff < seq_diff_min) {
2038 seq_diff_min = seq_diff;
2042 seq_diff_min = seq_diff;
2052 AddSeq(struct ip *pip, struct alias_link *lnk, int delta)
2055 When a TCP packet has been altered in length, save this
2056 information in a circular list. If enough packets have
2057 been altered, then this list will begin to overwrite itself.
2061 struct ack_data_record x;
2062 int hlen, tlen, dlen;
2067 hlen = (pip->ip_hl + tc->th_off) << 2;
2068 tlen = ntohs(pip->ip_len);
2071 x.ack_old = htonl(ntohl(tc->th_seq) + dlen);
2072 x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta);
2076 i = lnk->data.tcp->state.index;
2077 lnk->data.tcp->ack[i] = x;
2080 if (i == N_LINK_TCP_DATA)
2081 lnk->data.tcp->state.index = 0;
2083 lnk->data.tcp->state.index = i;
2087 SetExpire(struct alias_link *lnk, int expire)
2090 lnk->flags &= ~LINK_PERMANENT;
2092 } else if (expire == -1) {
2093 lnk->flags |= LINK_PERMANENT;
2094 } else if (expire > 0) {
2095 lnk->expire_time = expire;
2097 #ifdef LIBALIAS_DEBUG
2098 fprintf(stderr, "PacketAlias/SetExpire(): ");
2099 fprintf(stderr, "error in expire parameter\n");
2105 ClearCheckNewLink(struct libalias *la)
2108 LIBALIAS_LOCK_ASSERT(la);
2109 la->newDefaultLink = 0;
2113 SetProtocolFlags(struct alias_link *lnk, int pflags)
2116 lnk->pflags = pflags;;
2120 GetProtocolFlags(struct alias_link *lnk)
2123 return (lnk->pflags);
2127 SetDestCallId(struct alias_link *lnk, u_int16_t cid)
2129 struct libalias *la = lnk->la;
2131 LIBALIAS_LOCK_ASSERT(la);
2132 la->deleteAllLinks = 1;
2133 ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr,
2134 lnk->src_port, cid, lnk->alias_port, lnk->link_type);
2135 la->deleteAllLinks = 0;
2139 /* Miscellaneous Functions
2142 InitPacketAliasLog()
2143 UninitPacketAliasLog()
2147 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2148 is called to find and remove timed-out aliasing links. Logic exists
2149 to sweep through the entire table and linked list structure
2152 (prototype in alias_local.h)
2156 HouseKeeping(struct libalias *la)
2164 LIBALIAS_LOCK_ASSERT(la);
2166 * Save system time (seconds) in global variable timeStamp for use
2167 * by other functions. This is done so as not to unnecessarily
2168 * waste timeline by making system calls.
2171 la->timeStamp = time_uptime;
2173 gettimeofday(&tv, &tz);
2174 la->timeStamp = tv.tv_sec;
2177 /* Compute number of spokes (output table link chains) to cover */
2178 n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime);
2179 n /= ALIAS_CLEANUP_INTERVAL_SECS;
2181 /* Handle different cases */
2183 if (n > ALIAS_CLEANUP_MAX_SPOKES)
2184 n = ALIAS_CLEANUP_MAX_SPOKES;
2185 la->lastCleanupTime = la->timeStamp;
2186 for (i = 0; i < n; i++)
2187 IncrementalCleanup(la);
2189 #ifdef LIBALIAS_DEBUG
2190 fprintf(stderr, "PacketAlias/HouseKeeping(): ");
2191 fprintf(stderr, "something unexpected in time values\n");
2193 la->lastCleanupTime = la->timeStamp;
2197 /* Init the log file and enable logging */
2199 InitPacketAliasLog(struct libalias *la)
2202 LIBALIAS_LOCK_ASSERT(la);
2203 if (~la->packetAliasMode & PKT_ALIAS_LOG) {
2205 if ((la->logDesc = kmalloc(LIBALIAS_BUF_SIZE,M_ALIAS, M_WAITOK | M_ZERO)))
2208 if ((la->logDesc = fopen("/var/log/alias.log", "w")))
2209 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2212 return (ENOMEM); /* log initialization failed */
2213 la->packetAliasMode |= PKT_ALIAS_LOG;
2219 /* Close the log-file and disable logging. */
2221 UninitPacketAliasLog(struct libalias *la)
2224 LIBALIAS_LOCK_ASSERT(la);
2227 kfree(la->logDesc,M_ALIAS);
2229 fclose(la->logDesc);
2233 la->packetAliasMode &= ~PKT_ALIAS_LOG;
2236 /* Outside world interfaces
2238 -- "outside world" means other than alias*.c routines --
2240 PacketAliasRedirectPort()
2241 PacketAliasAddServer()
2242 PacketAliasRedirectProto()
2243 PacketAliasRedirectAddr()
2244 PacketAliasRedirectDynamic()
2245 PacketAliasRedirectDelete()
2246 PacketAliasSetAddress()
2249 PacketAliasSetMode()
2251 (prototypes in alias.h)
2254 /* Redirection from a specific public addr:port to a
2255 private addr:port */
2257 LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port,
2258 struct in_addr dst_addr, u_short dst_port,
2259 struct in_addr alias_addr, u_short alias_port,
2263 struct alias_link *lnk;
2268 link_type = LINK_UDP;
2271 link_type = LINK_TCP;
2274 #ifdef LIBALIAS_DEBUG
2275 fprintf(stderr, "PacketAliasRedirectPort(): ");
2276 fprintf(stderr, "only TCP and UDP protocols allowed\n");
2282 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2283 src_port, dst_port, alias_port,
2287 lnk->flags |= LINK_PERMANENT;
2289 #ifdef LIBALIAS_DEBUG
2291 fprintf(stderr, "PacketAliasRedirectPort(): "
2292 "call to AddLink() failed\n");
2297 LIBALIAS_UNLOCK(la);
2301 /* Add server to the pool of servers */
2303 LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
2305 struct server *server;
2311 server = kmalloc(sizeof(struct server),M_ALIAS, M_WAITOK | M_ZERO);
2313 if (server != NULL) {
2314 struct server *head;
2316 server->addr = addr;
2317 server->port = port;
2321 server->next = server;
2325 for (s = head; s->next != head; s = s->next);
2327 server->next = head;
2329 lnk->server = server;
2334 LIBALIAS_UNLOCK(la);
2338 /* Redirect packets of a given IP protocol from a specific
2339 public address to a private address */
2341 LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr,
2342 struct in_addr dst_addr,
2343 struct in_addr alias_addr,
2346 struct alias_link *lnk;
2349 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2350 NO_SRC_PORT, NO_DEST_PORT, 0,
2354 lnk->flags |= LINK_PERMANENT;
2356 #ifdef LIBALIAS_DEBUG
2358 fprintf(stderr, "PacketAliasRedirectProto(): "
2359 "call to AddLink() failed\n");
2363 LIBALIAS_UNLOCK(la);
2367 /* Static address translation */
2369 LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr,
2370 struct in_addr alias_addr)
2372 struct alias_link *lnk;
2375 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
2380 lnk->flags |= LINK_PERMANENT;
2382 #ifdef LIBALIAS_DEBUG
2384 fprintf(stderr, "PacketAliasRedirectAddr(): "
2385 "call to AddLink() failed\n");
2389 LIBALIAS_UNLOCK(la);
2394 /* Mark the aliasing link dynamic */
2396 LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
2403 if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
2406 lnk->flags &= ~LINK_PERMANENT;
2409 LIBALIAS_UNLOCK(la);
2415 LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
2417 /* This is a dangerous function to put in the API,
2418 because an invalid pointer can crash the program. */
2421 la->deleteAllLinks = 1;
2423 la->deleteAllLinks = 0;
2424 LIBALIAS_UNLOCK(la);
2429 LibAliasSetAddress(struct libalias *la, struct in_addr addr)
2433 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2434 && la->aliasAddress.s_addr != addr.s_addr)
2435 CleanupAliasData(la);
2437 la->aliasAddress = addr;
2438 LIBALIAS_UNLOCK(la);
2443 LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2447 la->targetAddress = target_addr;
2448 LIBALIAS_UNLOCK(la);
2455 while (!LIST_EMPTY(&instancehead))
2456 LibAliasUninit(LIST_FIRST(&instancehead));
2460 LibAliasInit(struct libalias *la)
2469 la = kmalloc(sizeof *la,M_ALIAS, M_WAITOK | M_ZERO);
2473 #ifndef _KERNEL /* kernel cleans up on module unload */
2474 if (LIST_EMPTY(&instancehead))
2477 LIST_INSERT_HEAD(&instancehead, la, instancelist);
2480 la->timeStamp = time_uptime;
2481 la->lastCleanupTime = time_uptime;
2483 gettimeofday(&tv, &tz);
2484 la->timeStamp = tv.tv_sec;
2485 la->lastCleanupTime = tv.tv_sec;
2488 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
2489 LIST_INIT(&la->linkTableOut[i]);
2490 for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
2491 LIST_INIT(&la->linkTableIn[i]);
2492 LIBALIAS_LOCK_INIT(la);
2496 la->deleteAllLinks = 1;
2497 CleanupAliasData(la);
2498 la->deleteAllLinks = 0;
2501 la->aliasAddress.s_addr = INADDR_ANY;
2502 la->targetAddress.s_addr = INADDR_ANY;
2504 la->icmpLinkCount = 0;
2505 la->udpLinkCount = 0;
2506 la->tcpLinkCount = 0;
2507 la->pptpLinkCount = 0;
2508 la->protoLinkCount = 0;
2509 la->fragmentIdLinkCount = 0;
2510 la->fragmentPtrLinkCount = 0;
2513 la->cleanupIndex = 0;
2515 la->packetAliasMode = PKT_ALIAS_SAME_PORTS
2516 #ifndef NO_USE_SOCKETS
2517 | PKT_ALIAS_USE_SOCKETS
2519 | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2521 la->fireWallFD = -1;
2524 LibAliasRefreshModules();
2526 LIBALIAS_UNLOCK(la);
2531 LibAliasUninit(struct libalias *la)
2535 la->deleteAllLinks = 1;
2536 CleanupAliasData(la);
2537 la->deleteAllLinks = 0;
2538 UninitPacketAliasLog(la);
2542 LIST_REMOVE(la, instancelist);
2543 LIBALIAS_UNLOCK(la);
2544 LIBALIAS_LOCK_DESTROY(la);
2548 /* Change mode for some operations */
2551 struct libalias *la,
2552 unsigned int flags, /* Which state to bring flags to */
2553 unsigned int mask /* Mask of which flags to affect (use 0 to
2554 * do a probe for flag values) */
2560 /* Enable logging? */
2561 if (flags & mask & PKT_ALIAS_LOG) {
2563 if (InitPacketAliasLog(la) == ENOMEM)
2566 /* _Disable_ logging? */
2567 if (~flags & mask & PKT_ALIAS_LOG) {
2568 UninitPacketAliasLog(la);
2571 /* Start punching holes in the firewall? */
2572 if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2575 /* Stop punching holes in the firewall? */
2576 if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2581 /* Other flags can be set/cleared without special action */
2582 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2583 res = la->packetAliasMode;
2585 LIBALIAS_UNLOCK(la);
2591 LibAliasCheckNewLink(struct libalias *la)
2596 res = la->newDefaultLink;
2597 LIBALIAS_UNLOCK(la);
2605 Code to support firewall punching. This shouldn't really be in this
2606 file, but making variables global is evil too.
2609 /* Firewall include files */
2611 #include <netinet/ip_fw.h>
2616 * helper function, updates the pointer to cmd with the length
2617 * of the current command, and also cleans up the first word of
2618 * the new command in case it has been clobbered before.
2621 next_cmd(ipfw_insn * cmd)
2624 bzero(cmd, sizeof(*cmd));
2629 * A function to fill simple commands of size 1.
2630 * Existing flags are preserved.
2633 fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2634 int flags, u_int16_t arg)
2636 cmd->opcode = opcode;
2637 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2639 return next_cmd(cmd);
2643 fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2645 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1;
2647 cmd->addr.s_addr = addr;
2648 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2652 fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2654 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1;
2656 cmd->ports[0] = cmd->ports[1] = port;
2657 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2661 fill_rule(void *buf, int bufsize, int rulenum,
2662 enum ipfw_opcodes action, int proto,
2663 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
2665 struct ip_fw *rule = (struct ip_fw *)buf;
2666 ipfw_insn *cmd = (ipfw_insn *) rule->cmd;
2668 bzero(buf, bufsize);
2669 rule->rulenum = rulenum;
2671 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto);
2672 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr);
2673 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp);
2674 cmd = fill_ip(cmd, O_IP_DST, da.s_addr);
2675 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
2677 rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2678 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
2680 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2682 return ((char *)cmd - (char *)buf);
2685 static void ClearAllFWHoles(struct libalias *la);
2688 #define fw_setfield(la, field, num) \
2690 (field)[(num) - la->fireWallBaseNum] = 1; \
2691 } /*lint -save -e717 */ while(0)/* lint -restore */
2693 #define fw_clrfield(la, field, num) \
2695 (field)[(num) - la->fireWallBaseNum] = 0; \
2696 } /*lint -save -e717 */ while(0)/* lint -restore */
2698 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2701 InitPunchFW(struct libalias *la)
2704 LIBALIAS_LOCK_ASSERT(la);
2705 la->fireWallField = kmalloc(la->fireWallNumNums,M_ALIAS, M_WAITOK | M_ZERO);
2706 if (la->fireWallField) {
2707 memset(la->fireWallField, 0, la->fireWallNumNums);
2708 if (la->fireWallFD < 0) {
2709 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2711 ClearAllFWHoles(la);
2712 la->fireWallActiveNum = la->fireWallBaseNum;
2717 UninitPunchFW(struct libalias *la)
2720 LIBALIAS_LOCK_ASSERT(la);
2721 ClearAllFWHoles(la);
2722 if (la->fireWallFD >= 0)
2723 close(la->fireWallFD);
2724 la->fireWallFD = -1;
2725 if (la->fireWallField)
2726 kfree(la->fireWallField,M_ALIAS);
2727 la->fireWallField = NULL;
2728 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2731 /* Make a certain link go through the firewall */
2733 PunchFWHole(struct alias_link *lnk)
2735 struct libalias *la;
2736 int r; /* Result code */
2737 struct ip_fw rule; /* On-the-fly built rule */
2738 int fwhole; /* Where to punch hole */
2740 LIBALIAS_LOCK_ASSERT(la);
2743 /* Don't do anything unless we are asked to */
2744 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2745 la->fireWallFD < 0 ||
2746 lnk->link_type != LINK_TCP)
2749 memset(&rule, 0, sizeof rule);
2753 /* Find empty slot */
2754 for (fwhole = la->fireWallActiveNum;
2755 fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2756 fw_tstfield(la, la->fireWallField, fwhole);
2758 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2759 for (fwhole = la->fireWallBaseNum;
2760 fwhole < la->fireWallActiveNum &&
2761 fw_tstfield(la, la->fireWallField, fwhole);
2763 if (fwhole == la->fireWallActiveNum) {
2764 /* No rule point empty - we can't punch more holes. */
2765 la->fireWallActiveNum = la->fireWallBaseNum;
2766 #ifdef LIBALIAS_DEBUG
2767 fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2772 /* Start next search at next position */
2773 la->fireWallActiveNum = fwhole + 1;
2776 * generate two rules of the form
2778 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2779 * accept tcp from DAddr DPort to OAddr OPort
2781 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2782 u_int32_t rulebuf[255];
2785 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2786 O_ACCEPT, IPPROTO_TCP,
2787 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
2788 GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
2789 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2791 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2793 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2794 O_ACCEPT, IPPROTO_TCP,
2795 GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
2796 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
2797 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2799 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2802 /* Indicate hole applied */
2803 lnk->data.tcp->fwhole = fwhole;
2804 fw_setfield(la, la->fireWallField, fwhole);
2807 /* Remove a hole in a firewall associated with a particular alias
2808 lnk. Calling this too often is harmless. */
2810 ClearFWHole(struct alias_link *lnk)
2812 struct libalias *la;
2814 LIBALIAS_LOCK_ASSERT(la);
2816 if (lnk->link_type == LINK_TCP) {
2817 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall
2824 memset(&rule, 0, sizeof rule); /* useless for ipfw3 */
2825 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL,
2826 &fwhole, sizeof fwhole));
2827 fw_clrfield(la, la->fireWallField, fwhole);
2828 lnk->data.tcp->fwhole = -1;
2832 /* Clear out the entire range dedicated to firewall holes. */
2834 ClearAllFWHoles(struct libalias *la)
2836 struct ip_fw rule; /* On-the-fly built rule */
2839 LIBALIAS_LOCK_ASSERT(la);
2840 if (la->fireWallFD < 0)
2843 memset(&rule, 0, sizeof rule);
2844 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2847 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2849 /* XXX: third arg correct here ? /phk */
2850 memset(la->fireWallField, 0, la->fireWallNumNums);
2856 LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2861 la->fireWallBaseNum = base;
2862 la->fireWallNumNums = num;
2864 LIBALIAS_UNLOCK(la);
2868 LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2872 la->skinnyPort = port;
2873 LIBALIAS_UNLOCK(la);