2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
33 Alias_db.c encapsulates all data structures used for storing
34 packet aliasing data. Other parts of the aliasing software
35 access data through functions provided in this file.
37 Data storage is based on the notion of a "link", which is
38 established for ICMP echo/reply packets, UDP datagrams and
39 TCP stream connections. A link stores the original source
40 and destination addresses. For UDP and TCP, it also stores
41 source and destination port numbers, as well as an alias
42 port number. Links are also used to store information about
45 There is a facility for sweeping through and deleting old
46 links as new packets are sent through. A simple timeout is
47 used for ICMP and UDP links. TCP links are left alone unless
48 there is an incomplete connection, in which case the link
49 can be deleted after a certain amount of time.
51 Initial version: August, 1996 (cjm)
53 Version 1.4: September 16, 1996 (cjm)
54 Facility for handling incoming links added.
56 Version 1.6: September 18, 1996 (cjm)
57 ICMP data handling simplified.
59 Version 1.7: January 9, 1997 (cjm)
60 Fragment handling simplified.
61 Saves pointers for unresolved fragments.
62 Permits links for unspecified remote ports
63 or unspecified remote addresses.
64 Fixed bug which did not properly zero port
65 table entries after a link was deleted.
66 Cleaned up some obsolete comments.
68 Version 1.8: January 14, 1997 (cjm)
69 Fixed data type error in StartPoint().
70 (This error did not exist prior to v1.7
71 and was discovered and fixed by Ari Suutari)
73 Version 1.9: February 1, 1997
74 Optionally, connections initiated from packet aliasing host
75 machine will will not have their port number aliased unless it
76 conflicts with an aliasing port already being used. (cjm)
78 All options earlier being #ifdef'ed are now available through
79 a new interface, SetPacketAliasMode(). This allows run time
80 control (which is now available in PPP+pktAlias through the
81 'alias' keyword). (ee)
83 Added ability to create an alias port without
84 either destination address or port specified.
85 port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
87 Removed K&R style function headers
88 and general cleanup. (ee)
90 Added packetAliasMode to replace compiler #defines's (ee)
92 Allocates sockets for partially specified
93 ports if ALIAS_USE_SOCKETS defined. (cjm)
95 Version 2.0: March, 1997
96 SetAliasAddress() will now clean up alias links
97 if the aliasing address is changed. (cjm)
99 PacketAliasPermanentLink() function added to support permanent
100 links. (J. Fortes suggested the need for this.)
103 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
105 (192.168.0.2, port 21) <-> alias port 3604, known dest addr
108 These permanent links allow for incoming connections to
109 machines on the local network. They can be given with a
110 user-chosen amount of specificity, with increasing specificity
111 meaning more security. (cjm)
113 Quite a bit of rework to the basic engine. The portTable[]
114 array, which kept track of which ports were in use was replaced
115 by a table/linked list structure. (cjm)
117 SetExpire() function added. (cjm)
119 DeleteLink() no longer frees memory association with a pointer
120 to a fragment (this bug was first recognized by E. Eklund in
123 Version 2.1: May, 1997 (cjm)
124 Packet aliasing engine reworked so that it can handle
125 multiple external addresses rather than just a single
128 PacketAliasRedirectPort() and PacketAliasRedirectAddr()
129 added to the API. The first function is a more generalized
130 version of PacketAliasPermanentLink(). The second function
131 implements static network address translation.
133 Version 3.2: July, 2000 (salander and satoh)
134 Added FindNewPortGroup to get contiguous range of port values.
136 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
137 link but not actually add one.
139 Added FindRtspOut, which is closely derived from FindUdpTcpOut,
140 except that the alias port (from FindNewPortGroup) is provided
143 See HISTORY file for additional revisions.
147 #include <machine/stdarg.h>
148 #include <sys/param.h>
149 #include <sys/kernel.h>
150 #include <sys/systm.h>
151 #include <sys/lock.h>
152 #include <sys/module.h>
153 #include <sys/rwlock.h>
154 #include <sys/syslog.h>
159 #include <sys/errno.h>
160 #include <sys/time.h>
164 #include <sys/socket.h>
165 #include <netinet/tcp.h>
168 #include <netinet/libalias/alias.h>
169 #include <netinet/libalias/alias_local.h>
170 #include <netinet/libalias/alias_mod.h>
174 #include "alias_local.h"
175 #include "alias_mod.h"
178 static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
181 Constants (note: constants are also defined
182 near relevant functions or structs)
185 /* Parameters used for cleanup of expired links */
186 /* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */
187 #define ALIAS_CLEANUP_INTERVAL_SECS 64
188 #define ALIAS_CLEANUP_MAX_SPOKES (LINK_TABLE_OUT_SIZE/5)
190 /* Timeouts (in seconds) for different link types */
191 #define ICMP_EXPIRE_TIME 60
192 #define UDP_EXPIRE_TIME 60
193 #define PROTO_EXPIRE_TIME 60
194 #define FRAGMENT_ID_EXPIRE_TIME 10
195 #define FRAGMENT_PTR_EXPIRE_TIME 30
197 /* TCP link expire time for different cases */
198 /* When the link has been used and closed - minimal grace time to
199 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
200 #ifndef TCP_EXPIRE_DEAD
201 #define TCP_EXPIRE_DEAD 10
204 /* When the link has been used and closed on one side - the other side
205 is allowed to still send data */
206 #ifndef TCP_EXPIRE_SINGLEDEAD
207 #define TCP_EXPIRE_SINGLEDEAD 90
210 /* When the link isn't yet up */
211 #ifndef TCP_EXPIRE_INITIAL
212 #define TCP_EXPIRE_INITIAL 300
215 /* When the link is up */
216 #ifndef TCP_EXPIRE_CONNECTED
217 #define TCP_EXPIRE_CONNECTED 86400
220 /* Dummy port number codes used for FindLinkIn/Out() and AddLink().
221 These constants can be anything except zero, which indicates an
222 unknown port number. */
224 #define NO_DEST_PORT 1
225 #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)
361 static moduledata_t alias_mod = {
362 "alias", alias_mod_handler, NULL
365 DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
368 /* Internal utility routines (used only in alias_db.c)
370 Lookup table starting points:
371 StartPointIn() -- link table initial search point for
373 StartPointOut() -- link table initial search point for
377 SeqDiff() -- difference between two TCP sequences
378 ShowAliasStats() -- send alias statistics to a monitor file
381 /* Local prototypes */
382 static u_int StartPointIn(struct in_addr, u_short, int);
385 StartPointOut(struct in_addr, struct in_addr,
386 u_short, u_short, int);
388 static int SeqDiff(u_long, u_long);
391 /* Firewall control */
392 static void InitPunchFW(struct libalias *);
393 static void UninitPunchFW(struct libalias *);
394 static void ClearFWHole(struct alias_link *);
398 /* Log file control */
399 static void ShowAliasStats(struct libalias *);
400 static int InitPacketAliasLog(struct libalias *);
401 static void UninitPacketAliasLog(struct libalias *);
403 void SctpShowAliasStats(struct libalias *la);
406 StartPointIn(struct in_addr alias_addr,
412 n = alias_addr.s_addr;
413 if (link_type != LINK_PPTP)
416 return (n % LINK_TABLE_IN_SIZE);
420 StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
421 u_short src_port, u_short dst_port, int link_type)
426 n += dst_addr.s_addr;
427 if (link_type != LINK_PPTP) {
433 return (n % LINK_TABLE_OUT_SIZE);
437 SeqDiff(u_long x, u_long y)
439 /* Return the difference between two TCP sequence numbers */
442 This function is encapsulated in case there are any unusual
443 arithmetic conditions that need to be considered.
446 return (ntohl(y) - ntohl(x));
452 AliasLog(char *str, const char *format, ...)
456 va_start(ap, format);
457 vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
462 AliasLog(FILE *stream, const char *format, ...)
466 va_start(ap, format);
467 vfprintf(stream, format, ap);
474 ShowAliasStats(struct libalias *la)
477 LIBALIAS_LOCK_ASSERT(la);
478 /* Used for debugging */
480 int tot = la->icmpLinkCount + la->udpLinkCount +
481 (la->sctpLinkCount>>1) + /* sctp counts half associations */
482 la->tcpLinkCount + la->pptpLinkCount +
483 la->protoLinkCount + la->fragmentIdLinkCount +
484 la->fragmentPtrLinkCount;
486 AliasLog(la->logDesc,
487 "icmp=%u, udp=%u, tcp=%u, sctp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
491 la->sctpLinkCount>>1, /* sctp counts half associations */
494 la->fragmentIdLinkCount,
495 la->fragmentPtrLinkCount, tot);
497 AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
502 void SctpShowAliasStats(struct libalias *la)
508 /* Internal routines for finding, deleting and adding links
511 GetNewPort() -- find and reserve new alias port number
512 GetSocket() -- try to allocate a socket for a given port
514 Link creation and deletion:
515 CleanupAliasData() - remove all link chains from lookup table
516 IncrementalCleanup() - look for stale links in a single chain
517 DeleteLink() - remove link
519 ReLink() - change link
522 FindLinkOut() - find link for outgoing packets
523 FindLinkIn() - find link for incoming packets
526 FindNewPortGroup() - find an available group of ports
529 /* Local prototypes */
530 static int GetNewPort(struct libalias *, struct alias_link *, int);
531 #ifndef NO_USE_SOCKETS
532 static u_short GetSocket(struct libalias *, u_short, int *, int);
534 static void CleanupAliasData(struct libalias *);
536 static void IncrementalCleanup(struct libalias *);
538 static void DeleteLink(struct alias_link *);
540 static struct alias_link *
541 ReLink(struct alias_link *,
542 struct in_addr, struct in_addr, struct in_addr,
543 u_short, u_short, int, int);
545 static struct alias_link *
546 FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
548 static struct alias_link *
549 FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
551 #define ALIAS_PORT_BASE 0x08000
552 #define ALIAS_PORT_MASK 0x07fff
553 #define ALIAS_PORT_MASK_EVEN 0x07ffe
554 #define GET_NEW_PORT_MAX_ATTEMPTS 20
556 #define FIND_EVEN_ALIAS_BASE 1
558 /* GetNewPort() allocates port numbers. Note that if a port number
559 is already in use, that does not mean that it cannot be used by
560 another link concurrently. This is because GetNewPort() looks for
561 unused triplets: (dest addr, dest port, alias port). */
564 GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
571 LIBALIAS_LOCK_ASSERT(la);
573 Description of alias_port_param for GetNewPort(). When
574 this parameter is zero or positive, it precisely specifies
575 the port number. GetNewPort() will return this number
576 without check that it is in use.
578 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
579 selected port number.
582 if (alias_port_param == GET_ALIAS_PORT) {
584 * The aliasing port is automatically selected by one of
587 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
589 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
591 * When the PKT_ALIAS_SAME_PORTS option is chosen,
592 * the first try will be the actual source port. If
593 * this is already in use, the remainder of the
594 * trials will be random.
596 port_net = lnk->src_port;
597 port_sys = ntohs(port_net);
599 /* First trial and all subsequent are random. */
600 port_sys = arc4random() & ALIAS_PORT_MASK;
601 port_sys += ALIAS_PORT_BASE;
602 port_net = htons(port_sys);
604 } else if (alias_port_param >= 0 && alias_port_param < 0x10000) {
605 lnk->alias_port = (u_short) alias_port_param;
608 #ifdef LIBALIAS_DEBUG
609 fprintf(stderr, "PacketAlias/GetNewPort(): ");
610 fprintf(stderr, "input parameter error\n");
615 /* Port number search */
616 for (i = 0; i < max_trials; i++) {
618 struct alias_link *search_result;
620 search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr,
621 lnk->dst_port, port_net,
624 if (search_result == NULL)
626 else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED)
627 && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
633 #ifndef NO_USE_SOCKETS
634 if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS)
635 && (lnk->flags & LINK_PARTIALLY_SPECIFIED)
636 && ((lnk->link_type == LINK_TCP) ||
637 (lnk->link_type == LINK_UDP))) {
638 if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) {
639 lnk->alias_port = port_net;
644 lnk->alias_port = port_net;
646 #ifndef NO_USE_SOCKETS
650 port_sys = arc4random() & ALIAS_PORT_MASK;
651 port_sys += ALIAS_PORT_BASE;
652 port_net = htons(port_sys);
655 #ifdef LIBALIAS_DEBUG
656 fprintf(stderr, "PacketAlias/GetNewPort(): ");
657 fprintf(stderr, "could not find free port\n");
663 #ifndef NO_USE_SOCKETS
665 GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
669 struct sockaddr_in sock_addr;
671 LIBALIAS_LOCK_ASSERT(la);
672 if (link_type == LINK_TCP)
673 sock = socket(AF_INET, SOCK_STREAM, 0);
674 else if (link_type == LINK_UDP)
675 sock = socket(AF_INET, SOCK_DGRAM, 0);
677 #ifdef LIBALIAS_DEBUG
678 fprintf(stderr, "PacketAlias/GetSocket(): ");
679 fprintf(stderr, "incorrect link type\n");
685 #ifdef LIBALIAS_DEBUG
686 fprintf(stderr, "PacketAlias/GetSocket(): ");
687 fprintf(stderr, "socket() error %d\n", *sockfd);
691 sock_addr.sin_family = AF_INET;
692 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
693 sock_addr.sin_port = port_net;
696 (struct sockaddr *)&sock_addr,
709 /* FindNewPortGroup() returns a base port number for an available
710 range of contiguous port numbers. Note that if a port number
711 is already in use, that does not mean that it cannot be used by
712 another link concurrently. This is because FindNewPortGroup()
713 looks for unused triplets: (dest addr, dest port, alias port). */
716 FindNewPortGroup(struct libalias *la,
717 struct in_addr dst_addr,
718 struct in_addr alias_addr,
730 LIBALIAS_LOCK_ASSERT(la);
732 * Get link_type from protocol
737 link_type = LINK_UDP;
740 link_type = LINK_TCP;
748 * The aliasing port is automatically selected by one of two
751 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
753 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
755 * When the ALIAS_SAME_PORTS option is chosen, the first
756 * try will be the actual source port. If this is already
757 * in use, the remainder of the trials will be random.
759 port_sys = ntohs(src_port);
762 /* First trial and all subsequent are random. */
763 if (align == FIND_EVEN_ALIAS_BASE)
764 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
766 port_sys = arc4random() & ALIAS_PORT_MASK;
768 port_sys += ALIAS_PORT_BASE;
771 /* Port number search */
772 for (i = 0; i < max_trials; i++) {
773 struct alias_link *search_result;
775 for (j = 0; j < port_count; j++)
776 if ((search_result = FindLinkIn(la, dst_addr,
777 alias_addr, dst_port, htons(port_sys + j),
778 link_type, 0)) != NULL)
781 /* Found a good range, return base */
783 return (htons(port_sys));
785 /* Find a new base to try */
786 if (align == FIND_EVEN_ALIAS_BASE)
787 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
789 port_sys = arc4random() & ALIAS_PORT_MASK;
791 port_sys += ALIAS_PORT_BASE;
794 #ifdef LIBALIAS_DEBUG
795 fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
796 fprintf(stderr, "could not find free port(s)\n");
803 CleanupAliasData(struct libalias *la)
805 struct alias_link *lnk;
808 LIBALIAS_LOCK_ASSERT(la);
809 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) {
810 lnk = LIST_FIRST(&la->linkTableOut[i]);
811 while (lnk != NULL) {
812 struct alias_link *link_next = LIST_NEXT(lnk, list_out);
818 la->cleanupIndex = 0;
822 IncrementalCleanup(struct libalias *la)
824 struct alias_link *lnk, *lnk_tmp;
826 LIBALIAS_LOCK_ASSERT(la);
827 LIST_FOREACH_SAFE(lnk, &la->linkTableOut[la->cleanupIndex++],
829 if (la->timeStamp - lnk->timestamp > lnk->expire_time)
833 if (la->cleanupIndex == LINK_TABLE_OUT_SIZE)
834 la->cleanupIndex = 0;
838 DeleteLink(struct alias_link *lnk)
840 struct libalias *la = lnk->la;
842 LIBALIAS_LOCK_ASSERT(la);
843 /* Don't do anything if the link is marked permanent */
844 if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT)
848 /* Delete associated firewall hole, if any */
852 /* Free memory allocated for LSNAT server pool */
853 if (lnk->server != NULL) {
854 struct server *head, *curr, *next;
856 head = curr = lnk->server;
860 } while ((curr = next) != head);
862 /* Adjust output table pointers */
863 LIST_REMOVE(lnk, list_out);
865 /* Adjust input table pointers */
866 LIST_REMOVE(lnk, list_in);
867 #ifndef NO_USE_SOCKETS
868 /* Close socket, if one has been allocated */
869 if (lnk->sockfd != -1) {
874 /* Link-type dependent cleanup */
875 switch (lnk->link_type) {
889 case LINK_FRAGMENT_ID:
890 la->fragmentIdLinkCount--;
892 case LINK_FRAGMENT_PTR:
893 la->fragmentPtrLinkCount--;
894 if (lnk->data.frag_ptr != NULL)
895 free(lnk->data.frag_ptr);
900 la->protoLinkCount--;
907 /* Write statistics, if logging enabled */
908 if (la->packetAliasMode & PKT_ALIAS_LOG) {
914 AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr,
915 struct in_addr alias_addr, u_short src_port, u_short dst_port,
916 int alias_port_param, int link_type)
919 struct alias_link *lnk;
921 LIBALIAS_LOCK_ASSERT(la);
922 lnk = malloc(sizeof(struct alias_link));
924 /* Basic initialization */
926 lnk->src_addr = src_addr;
927 lnk->dst_addr = dst_addr;
928 lnk->alias_addr = alias_addr;
929 lnk->proxy_addr.s_addr = INADDR_ANY;
930 lnk->src_port = src_port;
931 lnk->dst_port = dst_port;
934 lnk->link_type = link_type;
935 #ifndef NO_USE_SOCKETS
940 lnk->timestamp = la->timeStamp;
942 /* Expiration time */
945 lnk->expire_time = ICMP_EXPIRE_TIME;
948 lnk->expire_time = UDP_EXPIRE_TIME;
951 lnk->expire_time = TCP_EXPIRE_INITIAL;
954 lnk->flags |= LINK_PERMANENT; /* no timeout. */
956 case LINK_FRAGMENT_ID:
957 lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME;
959 case LINK_FRAGMENT_PTR:
960 lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
965 lnk->expire_time = PROTO_EXPIRE_TIME;
969 /* Determine alias flags */
970 if (dst_addr.s_addr == INADDR_ANY)
971 lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
973 lnk->flags |= LINK_UNKNOWN_DEST_PORT;
975 /* Determine alias port */
976 if (GetNewPort(la, lnk, alias_port_param) != 0) {
980 /* Link-type dependent initialization */
982 struct tcp_dat *aux_tcp;
991 aux_tcp = malloc(sizeof(struct tcp_dat));
992 if (aux_tcp != NULL) {
996 aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
997 aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
998 aux_tcp->state.index = 0;
999 aux_tcp->state.ack_modified = 0;
1000 for (i = 0; i < N_LINK_TCP_DATA; i++)
1001 aux_tcp->ack[i].active = 0;
1002 aux_tcp->fwhole = -1;
1003 lnk->data.tcp = aux_tcp;
1005 #ifdef LIBALIAS_DEBUG
1006 fprintf(stderr, "PacketAlias/AddLink: ");
1007 fprintf(stderr, " cannot allocate auxiliary TCP data\n");
1014 la->pptpLinkCount++;
1016 case LINK_FRAGMENT_ID:
1017 la->fragmentIdLinkCount++;
1019 case LINK_FRAGMENT_PTR:
1020 la->fragmentPtrLinkCount++;
1025 la->protoLinkCount++;
1029 /* Set up pointers for output lookup table */
1030 start_point = StartPointOut(src_addr, dst_addr,
1031 src_port, dst_port, link_type);
1032 LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out);
1034 /* Set up pointers for input lookup table */
1035 start_point = StartPointIn(alias_addr, lnk->alias_port, link_type);
1036 LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in);
1038 #ifdef LIBALIAS_DEBUG
1039 fprintf(stderr, "PacketAlias/AddLink(): ");
1040 fprintf(stderr, "malloc() call failed.\n");
1043 if (la->packetAliasMode & PKT_ALIAS_LOG) {
1049 static struct alias_link *
1050 ReLink(struct alias_link *old_lnk,
1051 struct in_addr src_addr,
1052 struct in_addr dst_addr,
1053 struct in_addr alias_addr,
1056 int alias_port_param, /* if less than zero, alias */
1058 { /* port will be automatically *//* chosen.
1059 * If greater than */
1060 struct alias_link *new_lnk; /* zero, equal to alias port */
1061 struct libalias *la = old_lnk->la;
1063 LIBALIAS_LOCK_ASSERT(la);
1064 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1065 src_port, dst_port, alias_port_param,
1068 if (new_lnk != NULL &&
1069 old_lnk->link_type == LINK_TCP &&
1070 old_lnk->data.tcp->fwhole > 0) {
1071 PunchFWHole(new_lnk);
1074 DeleteLink(old_lnk);
1078 static struct alias_link *
1079 _FindLinkOut(struct libalias *la, struct in_addr src_addr,
1080 struct in_addr dst_addr,
1084 int replace_partial_links)
1087 struct alias_link *lnk;
1089 LIBALIAS_LOCK_ASSERT(la);
1090 i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
1091 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) {
1092 if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
1093 lnk->src_addr.s_addr == src_addr.s_addr &&
1094 lnk->src_port == src_port &&
1095 lnk->dst_port == dst_port &&
1096 lnk->link_type == link_type &&
1097 lnk->server == NULL) {
1098 lnk->timestamp = la->timeStamp;
1103 /* Search for partially specified links. */
1104 if (lnk == NULL && replace_partial_links) {
1105 if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
1106 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0,
1109 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port,
1110 dst_port, link_type, 0);
1113 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
1114 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0,
1119 src_addr, dst_addr, lnk->alias_addr,
1120 src_port, dst_port, lnk->alias_port,
1127 static struct alias_link *
1128 FindLinkOut(struct libalias *la, struct in_addr src_addr,
1129 struct in_addr dst_addr,
1133 int replace_partial_links)
1135 struct alias_link *lnk;
1137 LIBALIAS_LOCK_ASSERT(la);
1138 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port,
1139 link_type, replace_partial_links);
1143 * The following allows permanent links to be specified as
1144 * using the default source address (i.e. device interface
1145 * address) without knowing in advance what that address
1148 if (la->aliasAddress.s_addr != INADDR_ANY &&
1149 src_addr.s_addr == la->aliasAddress.s_addr) {
1150 lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port,
1151 link_type, replace_partial_links);
1157 static struct alias_link *
1158 _FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1159 struct in_addr alias_addr,
1163 int replace_partial_links)
1167 struct alias_link *lnk;
1168 struct alias_link *lnk_fully_specified;
1169 struct alias_link *lnk_unknown_all;
1170 struct alias_link *lnk_unknown_dst_addr;
1171 struct alias_link *lnk_unknown_dst_port;
1173 LIBALIAS_LOCK_ASSERT(la);
1174 /* Initialize pointers */
1175 lnk_fully_specified = NULL;
1176 lnk_unknown_all = NULL;
1177 lnk_unknown_dst_addr = NULL;
1178 lnk_unknown_dst_port = NULL;
1180 /* If either the dest addr or port is unknown, the search
1181 loop will have to know about this. */
1184 if (dst_addr.s_addr == INADDR_ANY)
1185 flags_in |= LINK_UNKNOWN_DEST_ADDR;
1187 flags_in |= LINK_UNKNOWN_DEST_PORT;
1190 start_point = StartPointIn(alias_addr, alias_port, link_type);
1191 LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) {
1194 flags = flags_in | lnk->flags;
1195 if (!(flags & LINK_PARTIALLY_SPECIFIED)) {
1196 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1197 && lnk->alias_port == alias_port
1198 && lnk->dst_addr.s_addr == dst_addr.s_addr
1199 && lnk->dst_port == dst_port
1200 && lnk->link_type == link_type) {
1201 lnk_fully_specified = lnk;
1204 } else if ((flags & LINK_UNKNOWN_DEST_ADDR)
1205 && (flags & LINK_UNKNOWN_DEST_PORT)) {
1206 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1207 && lnk->alias_port == alias_port
1208 && lnk->link_type == link_type) {
1209 if (lnk_unknown_all == NULL)
1210 lnk_unknown_all = lnk;
1212 } else if (flags & LINK_UNKNOWN_DEST_ADDR) {
1213 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1214 && lnk->alias_port == alias_port
1215 && lnk->link_type == link_type
1216 && lnk->dst_port == dst_port) {
1217 if (lnk_unknown_dst_addr == NULL)
1218 lnk_unknown_dst_addr = lnk;
1220 } else if (flags & LINK_UNKNOWN_DEST_PORT) {
1221 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1222 && lnk->alias_port == alias_port
1223 && lnk->link_type == link_type
1224 && lnk->dst_addr.s_addr == dst_addr.s_addr) {
1225 if (lnk_unknown_dst_port == NULL)
1226 lnk_unknown_dst_port = lnk;
1231 if (lnk_fully_specified != NULL) {
1232 lnk_fully_specified->timestamp = la->timeStamp;
1233 lnk = lnk_fully_specified;
1234 } else if (lnk_unknown_dst_port != NULL)
1235 lnk = lnk_unknown_dst_port;
1236 else if (lnk_unknown_dst_addr != NULL)
1237 lnk = lnk_unknown_dst_addr;
1238 else if (lnk_unknown_all != NULL)
1239 lnk = lnk_unknown_all;
1243 if (replace_partial_links &&
1244 (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) {
1245 struct in_addr src_addr;
1248 if (lnk->server != NULL) { /* LSNAT link */
1249 src_addr = lnk->server->addr;
1250 src_port = lnk->server->port;
1251 lnk->server = lnk->server->next;
1253 src_addr = lnk->src_addr;
1254 src_port = lnk->src_port;
1257 if (link_type == LINK_SCTP) {
1258 lnk->src_addr = src_addr;
1259 lnk->src_port = 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);
1300 /* External routines for finding/adding links
1302 -- "external" means outside alias_db.c, but within alias*.c --
1304 FindIcmpIn(), FindIcmpOut()
1305 FindFragmentIn1(), FindFragmentIn2()
1306 AddFragmentPtrLink(), FindFragmentPtr()
1307 FindProtoIn(), FindProtoOut()
1308 FindUdpTcpIn(), FindUdpTcpOut()
1309 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1310 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1311 FindOriginalAddress(), FindAliasAddress()
1313 (prototypes in alias_local.h)
1317 FindIcmpIn(struct libalias *la, struct in_addr dst_addr,
1318 struct in_addr alias_addr,
1322 struct alias_link *lnk;
1324 LIBALIAS_LOCK_ASSERT(la);
1325 lnk = FindLinkIn(la, dst_addr, alias_addr,
1326 NO_DEST_PORT, id_alias,
1328 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1329 struct in_addr target_addr;
1331 target_addr = FindOriginalAddress(la, alias_addr);
1332 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1333 id_alias, NO_DEST_PORT, id_alias,
1340 FindIcmpOut(struct libalias *la, struct in_addr src_addr,
1341 struct in_addr dst_addr,
1345 struct alias_link *lnk;
1347 LIBALIAS_LOCK_ASSERT(la);
1348 lnk = FindLinkOut(la, src_addr, dst_addr,
1351 if (lnk == NULL && create) {
1352 struct in_addr alias_addr;
1354 alias_addr = FindAliasAddress(la, src_addr);
1355 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1356 id, NO_DEST_PORT, GET_ALIAS_ID,
1363 FindFragmentIn1(struct libalias *la, struct in_addr dst_addr,
1364 struct in_addr alias_addr,
1367 struct alias_link *lnk;
1369 LIBALIAS_LOCK_ASSERT(la);
1370 lnk = FindLinkIn(la, dst_addr, alias_addr,
1371 NO_DEST_PORT, ip_id,
1372 LINK_FRAGMENT_ID, 0);
1375 lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr,
1376 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1383 FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if
1385 struct in_addr alias_addr, /* is not found. */
1389 LIBALIAS_LOCK_ASSERT(la);
1390 return FindLinkIn(la, dst_addr, alias_addr,
1391 NO_DEST_PORT, ip_id,
1392 LINK_FRAGMENT_ID, 0);
1396 AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr,
1400 LIBALIAS_LOCK_ASSERT(la);
1401 return AddLink(la, la->nullAddress, dst_addr, la->nullAddress,
1402 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1407 FindFragmentPtr(struct libalias *la, struct in_addr dst_addr,
1411 LIBALIAS_LOCK_ASSERT(la);
1412 return FindLinkIn(la, dst_addr, la->nullAddress,
1413 NO_DEST_PORT, ip_id,
1414 LINK_FRAGMENT_PTR, 0);
1418 FindProtoIn(struct libalias *la, struct in_addr dst_addr,
1419 struct in_addr alias_addr,
1422 struct alias_link *lnk;
1424 LIBALIAS_LOCK_ASSERT(la);
1425 lnk = FindLinkIn(la, dst_addr, alias_addr,
1429 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1430 struct in_addr target_addr;
1432 target_addr = FindOriginalAddress(la, alias_addr);
1433 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1434 NO_SRC_PORT, NO_DEST_PORT, 0,
1441 FindProtoOut(struct libalias *la, struct in_addr src_addr,
1442 struct in_addr dst_addr,
1445 struct alias_link *lnk;
1447 LIBALIAS_LOCK_ASSERT(la);
1448 lnk = FindLinkOut(la, src_addr, dst_addr,
1449 NO_SRC_PORT, NO_DEST_PORT,
1453 struct in_addr alias_addr;
1455 alias_addr = FindAliasAddress(la, src_addr);
1456 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1457 NO_SRC_PORT, NO_DEST_PORT, 0,
1464 FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr,
1465 struct in_addr alias_addr,
1472 struct alias_link *lnk;
1474 LIBALIAS_LOCK_ASSERT(la);
1477 link_type = LINK_UDP;
1480 link_type = LINK_TCP;
1487 lnk = FindLinkIn(la, dst_addr, alias_addr,
1488 dst_port, alias_port,
1491 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1492 struct in_addr target_addr;
1494 target_addr = FindOriginalAddress(la, alias_addr);
1495 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1496 alias_port, dst_port, alias_port,
1503 FindUdpTcpOut(struct libalias *la, struct in_addr src_addr,
1504 struct in_addr dst_addr,
1511 struct alias_link *lnk;
1513 LIBALIAS_LOCK_ASSERT(la);
1516 link_type = LINK_UDP;
1519 link_type = LINK_TCP;
1526 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create);
1528 if (lnk == NULL && create) {
1529 struct in_addr alias_addr;
1531 alias_addr = FindAliasAddress(la, src_addr);
1532 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1533 src_port, dst_port, GET_ALIAS_PORT,
1540 AddPptp(struct libalias *la, struct in_addr src_addr,
1541 struct in_addr dst_addr,
1542 struct in_addr alias_addr,
1543 u_int16_t src_call_id)
1545 struct alias_link *lnk;
1547 LIBALIAS_LOCK_ASSERT(la);
1548 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1549 src_call_id, 0, GET_ALIAS_PORT,
1556 FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr,
1557 struct in_addr dst_addr,
1558 u_int16_t src_call_id)
1561 struct alias_link *lnk;
1563 LIBALIAS_LOCK_ASSERT(la);
1564 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1565 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1566 if (lnk->link_type == LINK_PPTP &&
1567 lnk->src_addr.s_addr == src_addr.s_addr &&
1568 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1569 lnk->src_port == src_call_id)
1576 FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr,
1577 struct in_addr dst_addr,
1578 u_int16_t dst_call_id)
1581 struct alias_link *lnk;
1583 LIBALIAS_LOCK_ASSERT(la);
1584 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1585 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1586 if (lnk->link_type == LINK_PPTP &&
1587 lnk->src_addr.s_addr == src_addr.s_addr &&
1588 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1589 lnk->dst_port == dst_call_id)
1596 FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr,
1597 struct in_addr alias_addr,
1598 u_int16_t dst_call_id)
1601 struct alias_link *lnk;
1603 LIBALIAS_LOCK_ASSERT(la);
1604 i = StartPointIn(alias_addr, 0, LINK_PPTP);
1605 LIST_FOREACH(lnk, &la->linkTableIn[i], list_in)
1606 if (lnk->link_type == LINK_PPTP &&
1607 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1608 lnk->alias_addr.s_addr == alias_addr.s_addr &&
1609 lnk->dst_port == dst_call_id)
1616 FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr,
1617 struct in_addr alias_addr,
1618 u_int16_t alias_call_id)
1620 struct alias_link *lnk;
1622 LIBALIAS_LOCK_ASSERT(la);
1623 lnk = FindLinkIn(la, dst_addr, alias_addr,
1624 0 /* any */ , alias_call_id,
1631 FindRtspOut(struct libalias *la, struct in_addr src_addr,
1632 struct in_addr dst_addr,
1638 struct alias_link *lnk;
1640 LIBALIAS_LOCK_ASSERT(la);
1643 link_type = LINK_UDP;
1646 link_type = LINK_TCP;
1653 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1);
1656 struct in_addr alias_addr;
1658 alias_addr = FindAliasAddress(la, src_addr);
1659 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1660 src_port, 0, alias_port,
1667 FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
1669 struct alias_link *lnk;
1671 LIBALIAS_LOCK_ASSERT(la);
1672 lnk = FindLinkIn(la, la->nullAddress, alias_addr,
1673 0, 0, LINK_ADDR, 0);
1675 la->newDefaultLink = 1;
1676 if (la->targetAddress.s_addr == INADDR_ANY)
1677 return (alias_addr);
1678 else if (la->targetAddress.s_addr == INADDR_NONE)
1679 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1680 la->aliasAddress : alias_addr;
1682 return (la->targetAddress);
1684 if (lnk->server != NULL) { /* LSNAT link */
1685 struct in_addr src_addr;
1687 src_addr = lnk->server->addr;
1688 lnk->server = lnk->server->next;
1690 } else if (lnk->src_addr.s_addr == INADDR_ANY)
1691 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1692 la->aliasAddress : alias_addr;
1694 return (lnk->src_addr);
1699 FindAliasAddress(struct libalias *la, struct in_addr original_addr)
1701 struct alias_link *lnk;
1703 LIBALIAS_LOCK_ASSERT(la);
1704 lnk = FindLinkOut(la, original_addr, la->nullAddress,
1705 0, 0, LINK_ADDR, 0);
1707 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1708 la->aliasAddress : original_addr;
1710 if (lnk->alias_addr.s_addr == INADDR_ANY)
1711 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1712 la->aliasAddress : original_addr;
1714 return (lnk->alias_addr);
1718 /* External routines for getting or changing link data
1719 (external to alias_db.c, but internal to alias*.c)
1721 SetFragmentData(), GetFragmentData()
1722 SetFragmentPtr(), GetFragmentPtr()
1723 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1724 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1725 GetOriginalPort(), GetAliasPort()
1726 SetAckModified(), GetAckModified()
1727 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1728 SetProtocolFlags(), GetProtocolFlags()
1733 SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
1735 lnk->data.frag_addr = src_addr;
1739 GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
1741 *src_addr = lnk->data.frag_addr;
1745 SetFragmentPtr(struct alias_link *lnk, char *fptr)
1747 lnk->data.frag_ptr = fptr;
1751 GetFragmentPtr(struct alias_link *lnk, char **fptr)
1753 *fptr = lnk->data.frag_ptr;
1757 SetStateIn(struct alias_link *lnk, int state)
1759 /* TCP input state */
1761 case ALIAS_TCP_STATE_DISCONNECTED:
1762 if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED)
1763 lnk->expire_time = TCP_EXPIRE_DEAD;
1765 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1767 case ALIAS_TCP_STATE_CONNECTED:
1768 if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED)
1769 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1773 panic("libalias:SetStateIn() unknown state");
1778 lnk->data.tcp->state.in = state;
1782 SetStateOut(struct alias_link *lnk, int state)
1784 /* TCP output state */
1786 case ALIAS_TCP_STATE_DISCONNECTED:
1787 if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED)
1788 lnk->expire_time = TCP_EXPIRE_DEAD;
1790 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1792 case ALIAS_TCP_STATE_CONNECTED:
1793 if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED)
1794 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1798 panic("libalias:SetStateOut() unknown state");
1803 lnk->data.tcp->state.out = state;
1807 GetStateIn(struct alias_link *lnk)
1809 /* TCP input state */
1810 return (lnk->data.tcp->state.in);
1814 GetStateOut(struct alias_link *lnk)
1816 /* TCP output state */
1817 return (lnk->data.tcp->state.out);
1821 GetOriginalAddress(struct alias_link *lnk)
1823 if (lnk->src_addr.s_addr == INADDR_ANY)
1824 return (lnk->la->aliasAddress);
1826 return (lnk->src_addr);
1830 GetDestAddress(struct alias_link *lnk)
1832 return (lnk->dst_addr);
1836 GetAliasAddress(struct alias_link *lnk)
1838 if (lnk->alias_addr.s_addr == INADDR_ANY)
1839 return (lnk->la->aliasAddress);
1841 return (lnk->alias_addr);
1845 GetDefaultAliasAddress(struct libalias *la)
1848 LIBALIAS_LOCK_ASSERT(la);
1849 return (la->aliasAddress);
1853 SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
1856 LIBALIAS_LOCK_ASSERT(la);
1857 la->aliasAddress = alias_addr;
1861 GetOriginalPort(struct alias_link *lnk)
1863 return (lnk->src_port);
1867 GetAliasPort(struct alias_link *lnk)
1869 return (lnk->alias_port);
1874 GetDestPort(struct alias_link *lnk)
1876 return (lnk->dst_port);
1882 SetAckModified(struct alias_link *lnk)
1884 /* Indicate that ACK numbers have been modified in a TCP connection */
1885 lnk->data.tcp->state.ack_modified = 1;
1889 GetProxyAddress(struct alias_link *lnk)
1891 return (lnk->proxy_addr);
1895 SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
1897 lnk->proxy_addr = addr;
1901 GetProxyPort(struct alias_link *lnk)
1903 return (lnk->proxy_port);
1907 SetProxyPort(struct alias_link *lnk, u_short port)
1909 lnk->proxy_port = port;
1913 GetAckModified(struct alias_link *lnk)
1915 /* See if ACK numbers have been modified */
1916 return (lnk->data.tcp->state.ack_modified);
1921 GetDeltaAckIn(u_long ack, struct alias_link *lnk)
1924 Find out how much the ACK number has been altered for an incoming
1925 TCP packet. To do this, a circular list of ACK numbers where the TCP
1926 packet size was altered is searched.
1930 int delta, ack_diff_min;
1934 for (i = 0; i < N_LINK_TCP_DATA; i++) {
1935 struct ack_data_record x;
1937 x = lnk->data.tcp->ack[i];
1938 if (x.active == 1) {
1941 ack_diff = SeqDiff(x.ack_new, ack);
1942 if (ack_diff >= 0) {
1943 if (ack_diff_min >= 0) {
1944 if (ack_diff < ack_diff_min) {
1946 ack_diff_min = ack_diff;
1950 ack_diff_min = ack_diff;
1960 GetDeltaSeqOut(u_long seq, struct alias_link *lnk)
1963 Find out how much the sequence number has been altered for an outgoing
1964 TCP packet. To do this, a circular list of ACK numbers where the TCP
1965 packet size was altered is searched.
1969 int delta, seq_diff_min;
1973 for (i = 0; i < N_LINK_TCP_DATA; i++) {
1974 struct ack_data_record x;
1976 x = lnk->data.tcp->ack[i];
1977 if (x.active == 1) {
1980 seq_diff = SeqDiff(x.ack_old, seq);
1981 if (seq_diff >= 0) {
1982 if (seq_diff_min >= 0) {
1983 if (seq_diff < seq_diff_min) {
1985 seq_diff_min = seq_diff;
1989 seq_diff_min = seq_diff;
1999 AddSeq(struct alias_link *lnk, int delta, u_int ip_hl, u_short ip_len,
2000 u_long th_seq, u_int th_off)
2003 When a TCP packet has been altered in length, save this
2004 information in a circular list. If enough packets have
2005 been altered, then this list will begin to overwrite itself.
2008 struct ack_data_record x;
2009 int hlen, tlen, dlen;
2012 hlen = (ip_hl + th_off) << 2;
2013 tlen = ntohs(ip_len);
2016 x.ack_old = htonl(ntohl(th_seq) + dlen);
2017 x.ack_new = htonl(ntohl(th_seq) + dlen + delta);
2021 i = lnk->data.tcp->state.index;
2022 lnk->data.tcp->ack[i] = x;
2025 if (i == N_LINK_TCP_DATA)
2026 lnk->data.tcp->state.index = 0;
2028 lnk->data.tcp->state.index = i;
2032 SetExpire(struct alias_link *lnk, int expire)
2035 lnk->flags &= ~LINK_PERMANENT;
2037 } else if (expire == -1) {
2038 lnk->flags |= LINK_PERMANENT;
2039 } else if (expire > 0) {
2040 lnk->expire_time = expire;
2042 #ifdef LIBALIAS_DEBUG
2043 fprintf(stderr, "PacketAlias/SetExpire(): ");
2044 fprintf(stderr, "error in expire parameter\n");
2050 ClearCheckNewLink(struct libalias *la)
2053 LIBALIAS_LOCK_ASSERT(la);
2054 la->newDefaultLink = 0;
2058 SetProtocolFlags(struct alias_link *lnk, int pflags)
2061 lnk->pflags = pflags;
2065 GetProtocolFlags(struct alias_link *lnk)
2068 return (lnk->pflags);
2072 SetDestCallId(struct alias_link *lnk, u_int16_t cid)
2074 struct libalias *la = lnk->la;
2076 LIBALIAS_LOCK_ASSERT(la);
2077 la->deleteAllLinks = 1;
2078 ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr,
2079 lnk->src_port, cid, lnk->alias_port, lnk->link_type);
2080 la->deleteAllLinks = 0;
2083 /* Miscellaneous Functions
2086 InitPacketAliasLog()
2087 UninitPacketAliasLog()
2091 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2092 is called to find and remove timed-out aliasing links. Logic exists
2093 to sweep through the entire table and linked list structure
2096 (prototype in alias_local.h)
2100 HouseKeeping(struct libalias *la)
2107 LIBALIAS_LOCK_ASSERT(la);
2109 * Save system time (seconds) in global variable timeStamp for use
2110 * by other functions. This is done so as not to unnecessarily
2111 * waste timeline by making system calls.
2114 la->timeStamp = time_uptime;
2116 gettimeofday(&tv, NULL);
2117 la->timeStamp = tv.tv_sec;
2120 /* Compute number of spokes (output table link chains) to cover */
2121 n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime);
2122 n /= ALIAS_CLEANUP_INTERVAL_SECS;
2124 /* Handle different cases */
2126 if (n > ALIAS_CLEANUP_MAX_SPOKES)
2127 n = ALIAS_CLEANUP_MAX_SPOKES;
2128 la->lastCleanupTime = la->timeStamp;
2129 for (i = 0; i < n; i++)
2130 IncrementalCleanup(la);
2132 #ifdef LIBALIAS_DEBUG
2133 fprintf(stderr, "PacketAlias/HouseKeeping(): ");
2134 fprintf(stderr, "something unexpected in time values\n");
2136 la->lastCleanupTime = la->timeStamp;
2140 /* Init the log file and enable logging */
2142 InitPacketAliasLog(struct libalias *la)
2145 LIBALIAS_LOCK_ASSERT(la);
2146 if (~la->packetAliasMode & PKT_ALIAS_LOG) {
2148 if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
2151 if ((la->logDesc = fopen("/var/log/alias.log", "w")))
2152 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2155 return (ENOMEM); /* log initialization failed */
2156 la->packetAliasMode |= PKT_ALIAS_LOG;
2162 /* Close the log-file and disable logging. */
2164 UninitPacketAliasLog(struct libalias *la)
2167 LIBALIAS_LOCK_ASSERT(la);
2172 fclose(la->logDesc);
2176 la->packetAliasMode &= ~PKT_ALIAS_LOG;
2179 /* Outside world interfaces
2181 -- "outside world" means other than alias*.c routines --
2183 PacketAliasRedirectPort()
2184 PacketAliasAddServer()
2185 PacketAliasRedirectProto()
2186 PacketAliasRedirectAddr()
2187 PacketAliasRedirectDynamic()
2188 PacketAliasRedirectDelete()
2189 PacketAliasSetAddress()
2192 PacketAliasSetMode()
2194 (prototypes in alias.h)
2197 /* Redirection from a specific public addr:port to a
2198 private addr:port */
2200 LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port,
2201 struct in_addr dst_addr, u_short dst_port,
2202 struct in_addr alias_addr, u_short alias_port,
2206 struct alias_link *lnk;
2211 link_type = LINK_UDP;
2214 link_type = LINK_TCP;
2217 link_type = LINK_SCTP;
2220 #ifdef LIBALIAS_DEBUG
2221 fprintf(stderr, "PacketAliasRedirectPort(): ");
2222 fprintf(stderr, "only SCTP, TCP and UDP protocols allowed\n");
2228 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2229 src_port, dst_port, alias_port,
2233 lnk->flags |= LINK_PERMANENT;
2235 #ifdef LIBALIAS_DEBUG
2237 fprintf(stderr, "PacketAliasRedirectPort(): "
2238 "call to AddLink() failed\n");
2243 LIBALIAS_UNLOCK(la);
2247 /* Add server to the pool of servers */
2249 LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
2251 struct server *server;
2257 server = malloc(sizeof(struct server));
2259 if (server != NULL) {
2260 struct server *head;
2262 server->addr = addr;
2263 server->port = port;
2267 server->next = server;
2271 for (s = head; s->next != head; s = s->next);
2273 server->next = head;
2275 lnk->server = server;
2280 LIBALIAS_UNLOCK(la);
2284 /* Redirect packets of a given IP protocol from a specific
2285 public address to a private address */
2287 LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr,
2288 struct in_addr dst_addr,
2289 struct in_addr alias_addr,
2292 struct alias_link *lnk;
2295 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2296 NO_SRC_PORT, NO_DEST_PORT, 0,
2300 lnk->flags |= LINK_PERMANENT;
2302 #ifdef LIBALIAS_DEBUG
2304 fprintf(stderr, "PacketAliasRedirectProto(): "
2305 "call to AddLink() failed\n");
2309 LIBALIAS_UNLOCK(la);
2313 /* Static address translation */
2315 LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr,
2316 struct in_addr alias_addr)
2318 struct alias_link *lnk;
2321 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
2326 lnk->flags |= LINK_PERMANENT;
2328 #ifdef LIBALIAS_DEBUG
2330 fprintf(stderr, "PacketAliasRedirectAddr(): "
2331 "call to AddLink() failed\n");
2335 LIBALIAS_UNLOCK(la);
2339 /* Mark the aliasing link dynamic */
2341 LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
2348 if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
2351 lnk->flags &= ~LINK_PERMANENT;
2354 LIBALIAS_UNLOCK(la);
2359 LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
2361 /* This is a dangerous function to put in the API,
2362 because an invalid pointer can crash the program. */
2365 la->deleteAllLinks = 1;
2367 la->deleteAllLinks = 0;
2368 LIBALIAS_UNLOCK(la);
2372 LibAliasSetAddress(struct libalias *la, struct in_addr addr)
2376 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2377 && la->aliasAddress.s_addr != addr.s_addr)
2378 CleanupAliasData(la);
2380 la->aliasAddress = addr;
2381 LIBALIAS_UNLOCK(la);
2385 LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2389 la->targetAddress = target_addr;
2390 LIBALIAS_UNLOCK(la);
2397 while (!LIST_EMPTY(&instancehead))
2398 LibAliasUninit(LIST_FIRST(&instancehead));
2402 LibAliasInit(struct libalias *la)
2411 #undef malloc /* XXX: ugly */
2412 la = malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO);
2414 la = calloc(sizeof *la, 1);
2419 #ifndef _KERNEL /* kernel cleans up on module unload */
2420 if (LIST_EMPTY(&instancehead))
2423 LIST_INSERT_HEAD(&instancehead, la, instancelist);
2426 la->timeStamp = time_uptime;
2427 la->lastCleanupTime = time_uptime;
2429 gettimeofday(&tv, NULL);
2430 la->timeStamp = tv.tv_sec;
2431 la->lastCleanupTime = tv.tv_sec;
2434 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
2435 LIST_INIT(&la->linkTableOut[i]);
2436 for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
2437 LIST_INIT(&la->linkTableIn[i]);
2441 LIBALIAS_LOCK_INIT(la);
2445 la->deleteAllLinks = 1;
2446 CleanupAliasData(la);
2447 la->deleteAllLinks = 0;
2454 la->aliasAddress.s_addr = INADDR_ANY;
2455 la->targetAddress.s_addr = INADDR_ANY;
2457 la->icmpLinkCount = 0;
2458 la->udpLinkCount = 0;
2459 la->tcpLinkCount = 0;
2460 la->sctpLinkCount = 0;
2461 la->pptpLinkCount = 0;
2462 la->protoLinkCount = 0;
2463 la->fragmentIdLinkCount = 0;
2464 la->fragmentPtrLinkCount = 0;
2467 la->cleanupIndex = 0;
2469 la->packetAliasMode = PKT_ALIAS_SAME_PORTS
2470 #ifndef NO_USE_SOCKETS
2471 | PKT_ALIAS_USE_SOCKETS
2473 | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2475 la->fireWallFD = -1;
2478 LibAliasRefreshModules();
2480 LIBALIAS_UNLOCK(la);
2485 LibAliasUninit(struct libalias *la)
2492 la->deleteAllLinks = 1;
2493 CleanupAliasData(la);
2494 la->deleteAllLinks = 0;
2495 UninitPacketAliasLog(la);
2499 LIST_REMOVE(la, instancelist);
2500 LIBALIAS_UNLOCK(la);
2501 LIBALIAS_LOCK_DESTROY(la);
2505 /* Change mode for some operations */
2508 struct libalias *la,
2509 unsigned int flags, /* Which state to bring flags to */
2510 unsigned int mask /* Mask of which flags to affect (use 0 to
2511 * do a probe for flag values) */
2517 /* Enable logging? */
2518 if (flags & mask & PKT_ALIAS_LOG) {
2520 if (InitPacketAliasLog(la) == ENOMEM)
2523 /* _Disable_ logging? */
2524 if (~flags & mask & PKT_ALIAS_LOG) {
2525 UninitPacketAliasLog(la);
2528 /* Start punching holes in the firewall? */
2529 if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2532 /* Stop punching holes in the firewall? */
2533 if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2538 /* Other flags can be set/cleared without special action */
2539 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2540 res = la->packetAliasMode;
2542 LIBALIAS_UNLOCK(la);
2547 LibAliasCheckNewLink(struct libalias *la)
2552 res = la->newDefaultLink;
2553 LIBALIAS_UNLOCK(la);
2560 Code to support firewall punching. This shouldn't really be in this
2561 file, but making variables global is evil too.
2564 /* Firewall include files */
2566 #include <netinet/ip_fw.h>
2571 * helper function, updates the pointer to cmd with the length
2572 * of the current command, and also cleans up the first word of
2573 * the new command in case it has been clobbered before.
2576 next_cmd(ipfw_insn * cmd)
2579 bzero(cmd, sizeof(*cmd));
2584 * A function to fill simple commands of size 1.
2585 * Existing flags are preserved.
2588 fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2589 int flags, u_int16_t arg)
2591 cmd->opcode = opcode;
2592 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2594 return next_cmd(cmd);
2598 fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2600 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1;
2602 cmd->addr.s_addr = addr;
2603 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2607 fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2609 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1;
2611 cmd->ports[0] = cmd->ports[1] = port;
2612 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2616 fill_rule(void *buf, int bufsize, int rulenum,
2617 enum ipfw_opcodes action, int proto,
2618 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
2620 struct ip_fw *rule = (struct ip_fw *)buf;
2621 ipfw_insn *cmd = (ipfw_insn *) rule->cmd;
2623 bzero(buf, bufsize);
2624 rule->rulenum = rulenum;
2626 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto);
2627 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr);
2628 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp);
2629 cmd = fill_ip(cmd, O_IP_DST, da.s_addr);
2630 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
2632 rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2633 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
2635 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2637 return ((char *)cmd - (char *)buf);
2640 static void ClearAllFWHoles(struct libalias *la);
2642 #define fw_setfield(la, field, num) \
2644 (field)[(num) - la->fireWallBaseNum] = 1; \
2645 } /*lint -save -e717 */ while(0)/* lint -restore */
2647 #define fw_clrfield(la, field, num) \
2649 (field)[(num) - la->fireWallBaseNum] = 0; \
2650 } /*lint -save -e717 */ while(0)/* lint -restore */
2652 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2655 InitPunchFW(struct libalias *la)
2658 la->fireWallField = malloc(la->fireWallNumNums);
2659 if (la->fireWallField) {
2660 memset(la->fireWallField, 0, la->fireWallNumNums);
2661 if (la->fireWallFD < 0) {
2662 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2664 ClearAllFWHoles(la);
2665 la->fireWallActiveNum = la->fireWallBaseNum;
2670 UninitPunchFW(struct libalias *la)
2673 ClearAllFWHoles(la);
2674 if (la->fireWallFD >= 0)
2675 close(la->fireWallFD);
2676 la->fireWallFD = -1;
2677 if (la->fireWallField)
2678 free(la->fireWallField);
2679 la->fireWallField = NULL;
2680 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2683 /* Make a certain link go through the firewall */
2685 PunchFWHole(struct alias_link *lnk)
2687 struct libalias *la;
2688 int r; /* Result code */
2689 struct ip_fw rule; /* On-the-fly built rule */
2690 int fwhole; /* Where to punch hole */
2694 /* Don't do anything unless we are asked to */
2695 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2696 la->fireWallFD < 0 ||
2697 lnk->link_type != LINK_TCP)
2700 memset(&rule, 0, sizeof rule);
2704 /* Find empty slot */
2705 for (fwhole = la->fireWallActiveNum;
2706 fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2707 fw_tstfield(la, la->fireWallField, fwhole);
2709 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2710 for (fwhole = la->fireWallBaseNum;
2711 fwhole < la->fireWallActiveNum &&
2712 fw_tstfield(la, la->fireWallField, fwhole);
2714 if (fwhole == la->fireWallActiveNum) {
2715 /* No rule point empty - we can't punch more holes. */
2716 la->fireWallActiveNum = la->fireWallBaseNum;
2717 #ifdef LIBALIAS_DEBUG
2718 fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2723 /* Start next search at next position */
2724 la->fireWallActiveNum = fwhole + 1;
2727 * generate two rules of the form
2729 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2730 * accept tcp from DAddr DPort to OAddr OPort
2732 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2733 u_int32_t rulebuf[255];
2736 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2737 O_ACCEPT, IPPROTO_TCP,
2738 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
2739 GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
2740 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2742 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2744 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2745 O_ACCEPT, IPPROTO_TCP,
2746 GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
2747 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
2748 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2750 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2753 /* Indicate hole applied */
2754 lnk->data.tcp->fwhole = fwhole;
2755 fw_setfield(la, la->fireWallField, fwhole);
2758 /* Remove a hole in a firewall associated with a particular alias
2759 lnk. Calling this too often is harmless. */
2761 ClearFWHole(struct alias_link *lnk)
2763 struct libalias *la;
2766 if (lnk->link_type == LINK_TCP) {
2767 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall
2774 memset(&rule, 0, sizeof rule); /* useless for ipfw2 */
2775 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL,
2776 &fwhole, sizeof fwhole));
2777 fw_clrfield(la, la->fireWallField, fwhole);
2778 lnk->data.tcp->fwhole = -1;
2782 /* Clear out the entire range dedicated to firewall holes. */
2784 ClearAllFWHoles(struct libalias *la)
2786 struct ip_fw rule; /* On-the-fly built rule */
2789 if (la->fireWallFD < 0)
2792 memset(&rule, 0, sizeof rule);
2793 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2796 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2798 /* XXX: third arg correct here ? /phk */
2799 memset(la->fireWallField, 0, la->fireWallNumNums);
2802 #endif /* !NO_FW_PUNCH */
2805 LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2810 la->fireWallBaseNum = base;
2811 la->fireWallNumNums = num;
2813 LIBALIAS_UNLOCK(la);
2817 LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2821 la->skinnyPort = port;
2822 LIBALIAS_UNLOCK(la);
2826 * Find the address to redirect incoming packets
2829 FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm)
2831 struct alias_link *lnk;
2832 struct in_addr redir;
2834 LIBALIAS_LOCK_ASSERT(la);
2835 lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst,
2836 sm->sctp_hdr->dest_port,sm->sctp_hdr->dest_port, LINK_SCTP, 1);
2838 return(lnk->src_addr); /* port redirect */
2840 redir = FindOriginalAddress(la,sm->ip_hdr->ip_dst);
2841 if (redir.s_addr == la->aliasAddress.s_addr ||
2842 redir.s_addr == la->targetAddress.s_addr) { /* No address found */
2843 lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst,
2844 NO_DEST_PORT, 0, LINK_SCTP, 1);
2846 return(lnk->src_addr); /* redirect proto */
2848 return(redir); /* address redirect */