2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
31 Alias_db.c encapsulates all data structures used for storing
32 packet aliasing data. Other parts of the aliasing software
33 access data through functions provided in this file.
35 Data storage is based on the notion of a "link", which is
36 established for ICMP echo/reply packets, UDP datagrams and
37 TCP stream connections. A link stores the original source
38 and destination addresses. For UDP and TCP, it also stores
39 source and destination port numbers, as well as an alias
40 port number. Links are also used to store information about
43 There is a facility for sweeping through and deleting old
44 links as new packets are sent through. A simple timeout is
45 used for ICMP and UDP links. TCP links are left alone unless
46 there is an incomplete connection, in which case the link
47 can be deleted after a certain amount of time.
50 Initial version: August, 1996 (cjm)
52 Version 1.4: September 16, 1996 (cjm)
53 Facility for handling incoming links added.
55 Version 1.6: September 18, 1996 (cjm)
56 ICMP data handling simplified.
58 Version 1.7: January 9, 1997 (cjm)
59 Fragment handling simplified.
60 Saves pointers for unresolved fragments.
61 Permits links for unspecified remote ports
62 or unspecified remote addresses.
63 Fixed bug which did not properly zero port
64 table entries after a link was deleted.
65 Cleaned up some obsolete comments.
67 Version 1.8: January 14, 1997 (cjm)
68 Fixed data type error in StartPoint().
69 (This error did not exist prior to v1.7
70 and was discovered and fixed by Ari Suutari)
72 Version 1.9: February 1, 1997
73 Optionally, connections initiated from packet aliasing host
74 machine will will not have their port number aliased unless it
75 conflicts with an aliasing port already being used. (cjm)
77 All options earlier being #ifdef'ed are now available through
78 a new interface, SetPacketAliasMode(). This allows run time
79 control (which is now available in PPP+pktAlias through the
80 'alias' keyword). (ee)
82 Added ability to create an alias port without
83 either destination address or port specified.
84 port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
86 Removed K&R style function headers
87 and general cleanup. (ee)
89 Added packetAliasMode to replace compiler #defines's (ee)
91 Allocates sockets for partially specified
92 ports if ALIAS_USE_SOCKETS defined. (cjm)
94 Version 2.0: March, 1997
95 SetAliasAddress() will now clean up alias links
96 if the aliasing address is changed. (cjm)
98 PacketAliasPermanentLink() function added to support permanent
99 links. (J. Fortes suggested the need for this.)
102 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
104 (192.168.0.2, port 21) <-> alias port 3604, known dest addr
107 These permanent links allow for incoming connections to
108 machines on the local network. They can be given with a
109 user-chosen amount of specificity, with increasing specificity
110 meaning more security. (cjm)
112 Quite a bit of rework to the basic engine. The portTable[]
113 array, which kept track of which ports were in use was replaced
114 by a table/linked list structure. (cjm)
116 SetExpire() function added. (cjm)
118 DeleteLink() no longer frees memory association with a pointer
119 to a fragment (this bug was first recognized by E. Eklund in
122 Version 2.1: May, 1997 (cjm)
123 Packet aliasing engine reworked so that it can handle
124 multiple external addresses rather than just a single
127 PacketAliasRedirectPort() and PacketAliasRedirectAddr()
128 added to the API. The first function is a more generalized
129 version of PacketAliasPermanentLink(). The second function
130 implements static network address translation.
132 Version 3.2: July, 2000 (salander and satoh)
133 Added FindNewPortGroup to get contiguous range of port values.
135 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
136 link but not actually add one.
138 Added FindRtspOut, which is closely derived from FindUdpTcpOut,
139 except that the alias port (from FindNewPortGroup) is provided
142 See HISTORY file for additional revisions.
146 #include <machine/stdarg.h>
147 #include <sys/param.h>
148 #include <sys/kernel.h>
149 #include <sys/lock.h>
150 #include <sys/module.h>
151 #include <sys/rwlock.h>
152 #include <sys/syslog.h>
157 #include <sys/errno.h>
158 #include <sys/time.h>
162 #include <sys/socket.h>
163 #include <netinet/tcp.h>
166 #include <netinet/libalias/alias.h>
167 #include <netinet/libalias/alias_local.h>
168 #include <netinet/libalias/alias_mod.h>
172 #include "alias_local.h"
173 #include "alias_mod.h"
176 static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
180 Constants (note: constants are also defined
181 near relevant functions or structs)
184 /* Parameters used for cleanup of expired links */
185 /* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */
186 #define ALIAS_CLEANUP_INTERVAL_SECS 64
187 #define ALIAS_CLEANUP_MAX_SPOKES (LINK_TABLE_OUT_SIZE/5)
189 /* Timeouts (in seconds) for different link types */
190 #define ICMP_EXPIRE_TIME 60
191 #define UDP_EXPIRE_TIME 60
192 #define PROTO_EXPIRE_TIME 60
193 #define FRAGMENT_ID_EXPIRE_TIME 10
194 #define FRAGMENT_PTR_EXPIRE_TIME 30
196 /* TCP link expire time for different cases */
197 /* When the link has been used and closed - minimal grace time to
198 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
199 #ifndef TCP_EXPIRE_DEAD
200 #define TCP_EXPIRE_DEAD 10
203 /* When the link has been used and closed on one side - the other side
204 is allowed to still send data */
205 #ifndef TCP_EXPIRE_SINGLEDEAD
206 #define TCP_EXPIRE_SINGLEDEAD 90
209 /* When the link isn't yet up */
210 #ifndef TCP_EXPIRE_INITIAL
211 #define TCP_EXPIRE_INITIAL 300
214 /* When the link is up */
215 #ifndef TCP_EXPIRE_CONNECTED
216 #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
231 The fundamental data structure used in this program is
232 "struct alias_link". Whenever a TCP connection is made,
233 a UDP datagram is sent out, or an ICMP echo request is made,
234 a link record is made (if it has not already been created).
235 The link record is identified by the source address/port
236 and the destination address/port. In the case of an ICMP
237 echo request, the source port is treated as being equivalent
238 with the 16-bit ID number of the ICMP packet.
240 The link record also can store some auxiliary data. For
241 TCP connections that have had sequence and acknowledgment
242 modifications, data space is available to track these changes.
243 A state field is used to keep track in changes to the TCP
244 connection state. ID numbers of fragments can also be
245 stored in the auxiliary space. Pointers to unresolved
246 fragments can also be stored.
248 The link records support two independent chainings. Lookup
249 tables for input and out tables hold the initial pointers
250 the link chains. On input, the lookup table indexes on alias
251 port and link type. On output, the lookup table indexes on
252 source address, destination address, source port, destination
256 struct ack_data_record { /* used to save changes to ACK/sequence
264 struct tcp_state { /* Information about TCP connection */
265 int in; /* State for outside -> inside */
266 int out; /* State for inside -> outside */
267 int index; /* Index to ACK data array */
268 int ack_modified; /* Indicates whether ACK and
269 * sequence numbers */
273 #define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes
274 * saved for a modified TCP stream */
276 struct tcp_state state;
277 struct ack_data_record ack[N_LINK_TCP_DATA];
278 int fwhole; /* Which firewall record is used for this
282 struct server { /* LSNAT server pool (circular list) */
288 struct alias_link { /* Main data structure */
290 struct in_addr src_addr; /* Address and port information */
291 struct in_addr dst_addr;
292 struct in_addr alias_addr;
293 struct in_addr proxy_addr;
298 struct server *server;
300 int link_type; /* Type of link: TCP, UDP, ICMP,
303 /* values for link_type */
304 #define LINK_ICMP IPPROTO_ICMP
305 #define LINK_UDP IPPROTO_UDP
306 #define LINK_TCP IPPROTO_TCP
307 #define LINK_FRAGMENT_ID (IPPROTO_MAX + 1)
308 #define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2)
309 #define LINK_ADDR (IPPROTO_MAX + 3)
310 #define LINK_PPTP (IPPROTO_MAX + 4)
312 int flags; /* indicates special characteristics */
313 int pflags; /* protocol-specific flags */
316 #define LINK_UNKNOWN_DEST_PORT 0x01
317 #define LINK_UNKNOWN_DEST_ADDR 0x02
318 #define LINK_PERMANENT 0x04
319 #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
320 #define LINK_UNFIREWALLED 0x08
322 int timestamp; /* Time link was last accessed */
323 int expire_time; /* Expire time for link */
324 #ifndef NO_USE_SOCKETS
325 int sockfd; /* socket descriptor */
327 LIST_ENTRY (alias_link) list_out; /* Linked list of
329 LIST_ENTRY (alias_link) list_in; /* input and output
332 union { /* Auxiliary data */
334 struct in_addr frag_addr;
339 /* Clean up procedure. */
340 static void finishoff(void);
342 /* Kernel module definition. */
344 MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing");
346 MODULE_VERSION(libalias, 1);
349 alias_mod_handler(module_t mod, int type, void *data)
356 handler_chain_init();
360 handler_chain_destroy();
371 static moduledata_t alias_mod = {
372 "alias", alias_mod_handler, NULL
375 DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
378 /* Internal utility routines (used only in alias_db.c)
380 Lookup table starting points:
381 StartPointIn() -- link table initial search point for
383 StartPointOut() -- link table initial search point for
387 SeqDiff() -- difference between two TCP sequences
388 ShowAliasStats() -- send alias statistics to a monitor file
392 /* Local prototypes */
393 static u_int StartPointIn(struct in_addr, u_short, int);
396 StartPointOut(struct in_addr, struct in_addr,
397 u_short, u_short, int);
399 static int SeqDiff(u_long, u_long);
402 /* Firewall control */
403 static void InitPunchFW(struct libalias *);
404 static void UninitPunchFW(struct libalias *);
405 static void ClearFWHole(struct alias_link *);
409 /* Log file control */
410 static void ShowAliasStats(struct libalias *);
411 static int InitPacketAliasLog(struct libalias *);
412 static void UninitPacketAliasLog(struct libalias *);
414 void SctpShowAliasStats(struct libalias *la);
417 StartPointIn(struct in_addr alias_addr,
423 n = alias_addr.s_addr;
424 if (link_type != LINK_PPTP)
427 return (n % LINK_TABLE_IN_SIZE);
432 StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
433 u_short src_port, u_short dst_port, int link_type)
438 n += dst_addr.s_addr;
439 if (link_type != LINK_PPTP) {
445 return (n % LINK_TABLE_OUT_SIZE);
450 SeqDiff(u_long x, u_long y)
452 /* Return the difference between two TCP sequence numbers */
455 This function is encapsulated in case there are any unusual
456 arithmetic conditions that need to be considered.
459 return (ntohl(y) - ntohl(x));
465 AliasLog(char *str, const char *format, ...)
469 va_start(ap, format);
470 vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
475 AliasLog(FILE *stream, const char *format, ...)
479 va_start(ap, format);
480 vfprintf(stream, format, ap);
487 ShowAliasStats(struct libalias *la)
490 LIBALIAS_LOCK_ASSERT(la);
491 /* Used for debugging */
493 int tot = la->icmpLinkCount + la->udpLinkCount +
494 (la->sctpLinkCount>>1) + /* sctp counts half associations */
495 la->tcpLinkCount + la->pptpLinkCount +
496 la->protoLinkCount + la->fragmentIdLinkCount +
497 la->fragmentPtrLinkCount;
499 AliasLog(la->logDesc,
500 "icmp=%u, udp=%u, tcp=%u, sctp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
504 la->sctpLinkCount>>1, /* sctp counts half associations */
507 la->fragmentIdLinkCount,
508 la->fragmentPtrLinkCount, tot);
510 AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
515 void SctpShowAliasStats(struct libalias *la)
522 /* Internal routines for finding, deleting and adding links
525 GetNewPort() -- find and reserve new alias port number
526 GetSocket() -- try to allocate a socket for a given port
528 Link creation and deletion:
529 CleanupAliasData() - remove all link chains from lookup table
530 IncrementalCleanup() - look for stale links in a single chain
531 DeleteLink() - remove link
533 ReLink() - change link
536 FindLinkOut() - find link for outgoing packets
537 FindLinkIn() - find link for incoming packets
540 FindNewPortGroup() - find an available group of ports
543 /* Local prototypes */
544 static int GetNewPort(struct libalias *, struct alias_link *, int);
545 #ifndef NO_USE_SOCKETS
546 static u_short GetSocket(struct libalias *, u_short, int *, int);
548 static void CleanupAliasData(struct libalias *);
550 static void IncrementalCleanup(struct libalias *);
552 static void DeleteLink(struct alias_link *);
554 static struct alias_link *
555 ReLink(struct alias_link *,
556 struct in_addr, struct in_addr, struct in_addr,
557 u_short, u_short, int, int);
559 static struct alias_link *
560 FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
562 static struct alias_link *
563 FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
566 #define ALIAS_PORT_BASE 0x08000
567 #define ALIAS_PORT_MASK 0x07fff
568 #define ALIAS_PORT_MASK_EVEN 0x07ffe
569 #define GET_NEW_PORT_MAX_ATTEMPTS 20
571 #define FIND_EVEN_ALIAS_BASE 1
573 /* GetNewPort() allocates port numbers. Note that if a port number
574 is already in use, that does not mean that it cannot be used by
575 another link concurrently. This is because GetNewPort() looks for
576 unused triplets: (dest addr, dest port, alias port). */
579 GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
586 LIBALIAS_LOCK_ASSERT(la);
588 Description of alias_port_param for GetNewPort(). When
589 this parameter is zero or positive, it precisely specifies
590 the port number. GetNewPort() will return this number
591 without check that it is in use.
593 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
594 selected port number.
597 if (alias_port_param == GET_ALIAS_PORT) {
599 * The aliasing port is automatically selected by one of
602 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
604 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
606 * When the PKT_ALIAS_SAME_PORTS option is chosen,
607 * the first try will be the actual source port. If
608 * this is already in use, the remainder of the
609 * trials will be random.
611 port_net = lnk->src_port;
612 port_sys = ntohs(port_net);
614 /* First trial and all subsequent are random. */
615 port_sys = arc4random() & ALIAS_PORT_MASK;
616 port_sys += ALIAS_PORT_BASE;
617 port_net = htons(port_sys);
619 } else if (alias_port_param >= 0 && alias_port_param < 0x10000) {
620 lnk->alias_port = (u_short) alias_port_param;
623 #ifdef LIBALIAS_DEBUG
624 fprintf(stderr, "PacketAlias/GetNewPort(): ");
625 fprintf(stderr, "input parameter error\n");
631 /* Port number search */
632 for (i = 0; i < max_trials; i++) {
634 struct alias_link *search_result;
636 search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr,
637 lnk->dst_port, port_net,
640 if (search_result == NULL)
642 else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED)
643 && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
649 #ifndef NO_USE_SOCKETS
650 if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS)
651 && (lnk->flags & LINK_PARTIALLY_SPECIFIED)
652 && ((lnk->link_type == LINK_TCP) ||
653 (lnk->link_type == LINK_UDP))) {
654 if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) {
655 lnk->alias_port = port_net;
660 lnk->alias_port = port_net;
662 #ifndef NO_USE_SOCKETS
666 port_sys = arc4random() & ALIAS_PORT_MASK;
667 port_sys += ALIAS_PORT_BASE;
668 port_net = htons(port_sys);
671 #ifdef LIBALIAS_DEBUG
672 fprintf(stderr, "PacketAlias/GetnewPort(): ");
673 fprintf(stderr, "could not find free port\n");
679 #ifndef NO_USE_SOCKETS
681 GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
685 struct sockaddr_in sock_addr;
687 LIBALIAS_LOCK_ASSERT(la);
688 if (link_type == LINK_TCP)
689 sock = socket(AF_INET, SOCK_STREAM, 0);
690 else if (link_type == LINK_UDP)
691 sock = socket(AF_INET, SOCK_DGRAM, 0);
693 #ifdef LIBALIAS_DEBUG
694 fprintf(stderr, "PacketAlias/GetSocket(): ");
695 fprintf(stderr, "incorrect link type\n");
701 #ifdef LIBALIAS_DEBUG
702 fprintf(stderr, "PacketAlias/GetSocket(): ");
703 fprintf(stderr, "socket() error %d\n", *sockfd);
707 sock_addr.sin_family = AF_INET;
708 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
709 sock_addr.sin_port = port_net;
712 (struct sockaddr *)&sock_addr,
725 /* FindNewPortGroup() returns a base port number for an available
726 range of contiguous port numbers. Note that if a port number
727 is already in use, that does not mean that it cannot be used by
728 another link concurrently. This is because FindNewPortGroup()
729 looks for unused triplets: (dest addr, dest port, alias port). */
732 FindNewPortGroup(struct libalias *la,
733 struct in_addr dst_addr,
734 struct in_addr alias_addr,
746 LIBALIAS_LOCK_ASSERT(la);
748 * Get link_type from protocol
753 link_type = LINK_UDP;
756 link_type = LINK_TCP;
764 * The aliasing port is automatically selected by one of two
767 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
769 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
771 * When the ALIAS_SAME_PORTS option is chosen, the first
772 * try will be the actual source port. If this is already
773 * in use, the remainder of the trials will be random.
775 port_sys = ntohs(src_port);
779 /* First trial and all subsequent are random. */
780 if (align == FIND_EVEN_ALIAS_BASE)
781 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
783 port_sys = arc4random() & ALIAS_PORT_MASK;
785 port_sys += ALIAS_PORT_BASE;
788 /* Port number search */
789 for (i = 0; i < max_trials; i++) {
791 struct alias_link *search_result;
793 for (j = 0; j < port_count; j++)
794 if (0 != (search_result = FindLinkIn(la, dst_addr, alias_addr,
795 dst_port, htons(port_sys + j),
799 /* Found a good range, return base */
801 return (htons(port_sys));
803 /* Find a new base to try */
804 if (align == FIND_EVEN_ALIAS_BASE)
805 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
807 port_sys = arc4random() & ALIAS_PORT_MASK;
809 port_sys += ALIAS_PORT_BASE;
812 #ifdef LIBALIAS_DEBUG
813 fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
814 fprintf(stderr, "could not find free port(s)\n");
821 CleanupAliasData(struct libalias *la)
823 struct alias_link *lnk;
826 LIBALIAS_LOCK_ASSERT(la);
827 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) {
828 lnk = LIST_FIRST(&la->linkTableOut[i]);
829 while (lnk != NULL) {
830 struct alias_link *link_next = LIST_NEXT(lnk, list_out);
836 la->cleanupIndex = 0;
841 IncrementalCleanup(struct libalias *la)
843 struct alias_link *lnk, *lnk_tmp;
845 LIBALIAS_LOCK_ASSERT(la);
846 LIST_FOREACH_SAFE(lnk, &la->linkTableOut[la->cleanupIndex++],
848 if (la->timeStamp - lnk->timestamp > lnk->expire_time)
852 if (la->cleanupIndex == LINK_TABLE_OUT_SIZE)
853 la->cleanupIndex = 0;
857 DeleteLink(struct alias_link *lnk)
859 struct libalias *la = lnk->la;
861 LIBALIAS_LOCK_ASSERT(la);
862 /* Don't do anything if the link is marked permanent */
863 if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT)
867 /* Delete associated firewall hole, if any */
871 /* Free memory allocated for LSNAT server pool */
872 if (lnk->server != NULL) {
873 struct server *head, *curr, *next;
875 head = curr = lnk->server;
879 } while ((curr = next) != head);
881 /* Adjust output table pointers */
882 LIST_REMOVE(lnk, list_out);
884 /* Adjust input table pointers */
885 LIST_REMOVE(lnk, list_in);
886 #ifndef NO_USE_SOCKETS
887 /* Close socket, if one has been allocated */
888 if (lnk->sockfd != -1) {
893 /* Link-type dependent cleanup */
894 switch (lnk->link_type) {
908 case LINK_FRAGMENT_ID:
909 la->fragmentIdLinkCount--;
911 case LINK_FRAGMENT_PTR:
912 la->fragmentPtrLinkCount--;
913 if (lnk->data.frag_ptr != NULL)
914 free(lnk->data.frag_ptr);
919 la->protoLinkCount--;
926 /* Write statistics, if logging enabled */
927 if (la->packetAliasMode & PKT_ALIAS_LOG) {
934 AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr,
935 struct in_addr alias_addr, u_short src_port, u_short dst_port,
936 int alias_port_param, int link_type)
939 struct alias_link *lnk;
941 LIBALIAS_LOCK_ASSERT(la);
942 lnk = malloc(sizeof(struct alias_link));
944 /* Basic initialization */
946 lnk->src_addr = src_addr;
947 lnk->dst_addr = dst_addr;
948 lnk->alias_addr = alias_addr;
949 lnk->proxy_addr.s_addr = INADDR_ANY;
950 lnk->src_port = src_port;
951 lnk->dst_port = dst_port;
954 lnk->link_type = link_type;
955 #ifndef NO_USE_SOCKETS
960 lnk->timestamp = la->timeStamp;
962 /* Expiration time */
965 lnk->expire_time = ICMP_EXPIRE_TIME;
968 lnk->expire_time = UDP_EXPIRE_TIME;
971 lnk->expire_time = TCP_EXPIRE_INITIAL;
974 lnk->flags |= LINK_PERMANENT; /* no timeout. */
976 case LINK_FRAGMENT_ID:
977 lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME;
979 case LINK_FRAGMENT_PTR:
980 lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
985 lnk->expire_time = PROTO_EXPIRE_TIME;
989 /* Determine alias flags */
990 if (dst_addr.s_addr == INADDR_ANY)
991 lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
993 lnk->flags |= LINK_UNKNOWN_DEST_PORT;
995 /* Determine alias port */
996 if (GetNewPort(la, lnk, alias_port_param) != 0) {
1000 /* Link-type dependent initialization */
1001 switch (link_type) {
1002 struct tcp_dat *aux_tcp;
1005 la->icmpLinkCount++;
1011 aux_tcp = malloc(sizeof(struct tcp_dat));
1012 if (aux_tcp != NULL) {
1016 aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
1017 aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
1018 aux_tcp->state.index = 0;
1019 aux_tcp->state.ack_modified = 0;
1020 for (i = 0; i < N_LINK_TCP_DATA; i++)
1021 aux_tcp->ack[i].active = 0;
1022 aux_tcp->fwhole = -1;
1023 lnk->data.tcp = aux_tcp;
1025 #ifdef LIBALIAS_DEBUG
1026 fprintf(stderr, "PacketAlias/AddLink: ");
1027 fprintf(stderr, " cannot allocate auxiliary TCP data\n");
1034 la->pptpLinkCount++;
1036 case LINK_FRAGMENT_ID:
1037 la->fragmentIdLinkCount++;
1039 case LINK_FRAGMENT_PTR:
1040 la->fragmentPtrLinkCount++;
1045 la->protoLinkCount++;
1049 /* Set up pointers for output lookup table */
1050 start_point = StartPointOut(src_addr, dst_addr,
1051 src_port, dst_port, link_type);
1052 LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out);
1054 /* Set up pointers for input lookup table */
1055 start_point = StartPointIn(alias_addr, lnk->alias_port, link_type);
1056 LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in);
1058 #ifdef LIBALIAS_DEBUG
1059 fprintf(stderr, "PacketAlias/AddLink(): ");
1060 fprintf(stderr, "malloc() call failed.\n");
1063 if (la->packetAliasMode & PKT_ALIAS_LOG) {
1069 static struct alias_link *
1070 ReLink(struct alias_link *old_lnk,
1071 struct in_addr src_addr,
1072 struct in_addr dst_addr,
1073 struct in_addr alias_addr,
1076 int alias_port_param, /* if less than zero, alias */
1078 { /* port will be automatically *//* chosen.
1079 * If greater than */
1080 struct alias_link *new_lnk; /* zero, equal to alias port */
1081 struct libalias *la = old_lnk->la;
1083 LIBALIAS_LOCK_ASSERT(la);
1084 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1085 src_port, dst_port, alias_port_param,
1088 if (new_lnk != NULL &&
1089 old_lnk->link_type == LINK_TCP &&
1090 old_lnk->data.tcp->fwhole > 0) {
1091 PunchFWHole(new_lnk);
1094 DeleteLink(old_lnk);
1098 static struct alias_link *
1099 _FindLinkOut(struct libalias *la, struct in_addr src_addr,
1100 struct in_addr dst_addr,
1104 int replace_partial_links)
1107 struct alias_link *lnk;
1109 LIBALIAS_LOCK_ASSERT(la);
1110 i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
1111 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) {
1112 if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
1113 lnk->src_addr.s_addr == src_addr.s_addr &&
1114 lnk->src_port == src_port &&
1115 lnk->dst_port == dst_port &&
1116 lnk->link_type == link_type &&
1117 lnk->server == NULL) {
1118 lnk->timestamp = la->timeStamp;
1123 /* Search for partially specified links. */
1124 if (lnk == NULL && replace_partial_links) {
1125 if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
1126 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0,
1129 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port,
1130 dst_port, link_type, 0);
1133 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
1134 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0,
1139 src_addr, dst_addr, lnk->alias_addr,
1140 src_port, dst_port, lnk->alias_port,
1147 static struct alias_link *
1148 FindLinkOut(struct libalias *la, struct in_addr src_addr,
1149 struct in_addr dst_addr,
1153 int replace_partial_links)
1155 struct alias_link *lnk;
1157 LIBALIAS_LOCK_ASSERT(la);
1158 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port,
1159 link_type, replace_partial_links);
1163 * The following allows permanent links to be specified as
1164 * using the default source address (i.e. device interface
1165 * address) without knowing in advance what that address
1168 if (la->aliasAddress.s_addr != INADDR_ANY &&
1169 src_addr.s_addr == la->aliasAddress.s_addr) {
1170 lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port,
1171 link_type, replace_partial_links);
1178 static struct alias_link *
1179 _FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1180 struct in_addr alias_addr,
1184 int replace_partial_links)
1188 struct alias_link *lnk;
1189 struct alias_link *lnk_fully_specified;
1190 struct alias_link *lnk_unknown_all;
1191 struct alias_link *lnk_unknown_dst_addr;
1192 struct alias_link *lnk_unknown_dst_port;
1194 LIBALIAS_LOCK_ASSERT(la);
1195 /* Initialize pointers */
1196 lnk_fully_specified = NULL;
1197 lnk_unknown_all = NULL;
1198 lnk_unknown_dst_addr = NULL;
1199 lnk_unknown_dst_port = NULL;
1201 /* If either the dest addr or port is unknown, the search
1202 loop will have to know about this. */
1205 if (dst_addr.s_addr == INADDR_ANY)
1206 flags_in |= LINK_UNKNOWN_DEST_ADDR;
1208 flags_in |= LINK_UNKNOWN_DEST_PORT;
1211 start_point = StartPointIn(alias_addr, alias_port, link_type);
1212 LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) {
1215 flags = flags_in | lnk->flags;
1216 if (!(flags & LINK_PARTIALLY_SPECIFIED)) {
1217 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1218 && lnk->alias_port == alias_port
1219 && lnk->dst_addr.s_addr == dst_addr.s_addr
1220 && lnk->dst_port == dst_port
1221 && lnk->link_type == link_type) {
1222 lnk_fully_specified = lnk;
1225 } else if ((flags & LINK_UNKNOWN_DEST_ADDR)
1226 && (flags & LINK_UNKNOWN_DEST_PORT)) {
1227 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1228 && lnk->alias_port == alias_port
1229 && lnk->link_type == link_type) {
1230 if (lnk_unknown_all == NULL)
1231 lnk_unknown_all = lnk;
1233 } else if (flags & LINK_UNKNOWN_DEST_ADDR) {
1234 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1235 && lnk->alias_port == alias_port
1236 && lnk->link_type == link_type
1237 && lnk->dst_port == dst_port) {
1238 if (lnk_unknown_dst_addr == NULL)
1239 lnk_unknown_dst_addr = lnk;
1241 } else if (flags & LINK_UNKNOWN_DEST_PORT) {
1242 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1243 && lnk->alias_port == alias_port
1244 && lnk->link_type == link_type
1245 && lnk->dst_addr.s_addr == dst_addr.s_addr) {
1246 if (lnk_unknown_dst_port == NULL)
1247 lnk_unknown_dst_port = lnk;
1254 if (lnk_fully_specified != NULL) {
1255 lnk_fully_specified->timestamp = la->timeStamp;
1256 lnk = lnk_fully_specified;
1257 } else if (lnk_unknown_dst_port != NULL)
1258 lnk = lnk_unknown_dst_port;
1259 else if (lnk_unknown_dst_addr != NULL)
1260 lnk = lnk_unknown_dst_addr;
1261 else if (lnk_unknown_all != NULL)
1262 lnk = lnk_unknown_all;
1266 if (replace_partial_links &&
1267 (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) {
1268 struct in_addr src_addr;
1271 if (lnk->server != NULL) { /* LSNAT link */
1272 src_addr = lnk->server->addr;
1273 src_port = lnk->server->port;
1274 lnk->server = lnk->server->next;
1276 src_addr = lnk->src_addr;
1277 src_port = lnk->src_port;
1280 if (link_type == LINK_SCTP) {
1281 lnk->src_addr = src_addr;
1282 lnk->src_port = src_port;
1286 src_addr, dst_addr, alias_addr,
1287 src_port, dst_port, alias_port,
1293 static struct alias_link *
1294 FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1295 struct in_addr alias_addr,
1299 int replace_partial_links)
1301 struct alias_link *lnk;
1303 LIBALIAS_LOCK_ASSERT(la);
1304 lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port,
1305 link_type, replace_partial_links);
1309 * The following allows permanent links to be specified as
1310 * using the default aliasing address (i.e. device
1311 * interface address) without knowing in advance what that
1314 if (la->aliasAddress.s_addr != INADDR_ANY &&
1315 alias_addr.s_addr == la->aliasAddress.s_addr) {
1316 lnk = _FindLinkIn(la, dst_addr, la->nullAddress, dst_port, alias_port,
1317 link_type, replace_partial_links);
1326 /* External routines for finding/adding links
1328 -- "external" means outside alias_db.c, but within alias*.c --
1330 FindIcmpIn(), FindIcmpOut()
1331 FindFragmentIn1(), FindFragmentIn2()
1332 AddFragmentPtrLink(), FindFragmentPtr()
1333 FindProtoIn(), FindProtoOut()
1334 FindUdpTcpIn(), FindUdpTcpOut()
1335 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1336 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1337 FindOriginalAddress(), FindAliasAddress()
1339 (prototypes in alias_local.h)
1344 FindIcmpIn(struct libalias *la, struct in_addr dst_addr,
1345 struct in_addr alias_addr,
1349 struct alias_link *lnk;
1351 LIBALIAS_LOCK_ASSERT(la);
1352 lnk = FindLinkIn(la, dst_addr, alias_addr,
1353 NO_DEST_PORT, id_alias,
1355 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1356 struct in_addr target_addr;
1358 target_addr = FindOriginalAddress(la, alias_addr);
1359 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1360 id_alias, NO_DEST_PORT, id_alias,
1368 FindIcmpOut(struct libalias *la, struct in_addr src_addr,
1369 struct in_addr dst_addr,
1373 struct alias_link *lnk;
1375 LIBALIAS_LOCK_ASSERT(la);
1376 lnk = FindLinkOut(la, src_addr, dst_addr,
1379 if (lnk == NULL && create) {
1380 struct in_addr alias_addr;
1382 alias_addr = FindAliasAddress(la, src_addr);
1383 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1384 id, NO_DEST_PORT, GET_ALIAS_ID,
1392 FindFragmentIn1(struct libalias *la, struct in_addr dst_addr,
1393 struct in_addr alias_addr,
1396 struct alias_link *lnk;
1398 LIBALIAS_LOCK_ASSERT(la);
1399 lnk = FindLinkIn(la, dst_addr, alias_addr,
1400 NO_DEST_PORT, ip_id,
1401 LINK_FRAGMENT_ID, 0);
1404 lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr,
1405 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1413 FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if
1415 struct in_addr alias_addr, /* is not found. */
1419 LIBALIAS_LOCK_ASSERT(la);
1420 return FindLinkIn(la, dst_addr, alias_addr,
1421 NO_DEST_PORT, ip_id,
1422 LINK_FRAGMENT_ID, 0);
1427 AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr,
1431 LIBALIAS_LOCK_ASSERT(la);
1432 return AddLink(la, la->nullAddress, dst_addr, la->nullAddress,
1433 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1439 FindFragmentPtr(struct libalias *la, struct in_addr dst_addr,
1443 LIBALIAS_LOCK_ASSERT(la);
1444 return FindLinkIn(la, dst_addr, la->nullAddress,
1445 NO_DEST_PORT, ip_id,
1446 LINK_FRAGMENT_PTR, 0);
1451 FindProtoIn(struct libalias *la, struct in_addr dst_addr,
1452 struct in_addr alias_addr,
1455 struct alias_link *lnk;
1457 LIBALIAS_LOCK_ASSERT(la);
1458 lnk = FindLinkIn(la, dst_addr, alias_addr,
1462 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1463 struct in_addr target_addr;
1465 target_addr = FindOriginalAddress(la, alias_addr);
1466 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1467 NO_SRC_PORT, NO_DEST_PORT, 0,
1475 FindProtoOut(struct libalias *la, struct in_addr src_addr,
1476 struct in_addr dst_addr,
1479 struct alias_link *lnk;
1481 LIBALIAS_LOCK_ASSERT(la);
1482 lnk = FindLinkOut(la, src_addr, dst_addr,
1483 NO_SRC_PORT, NO_DEST_PORT,
1487 struct in_addr alias_addr;
1489 alias_addr = FindAliasAddress(la, src_addr);
1490 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1491 NO_SRC_PORT, NO_DEST_PORT, 0,
1499 FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr,
1500 struct in_addr alias_addr,
1507 struct alias_link *lnk;
1509 LIBALIAS_LOCK_ASSERT(la);
1512 link_type = LINK_UDP;
1515 link_type = LINK_TCP;
1522 lnk = FindLinkIn(la, dst_addr, alias_addr,
1523 dst_port, alias_port,
1526 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1527 struct in_addr target_addr;
1529 target_addr = FindOriginalAddress(la, alias_addr);
1530 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1531 alias_port, dst_port, alias_port,
1539 FindUdpTcpOut(struct libalias *la, struct in_addr src_addr,
1540 struct in_addr dst_addr,
1547 struct alias_link *lnk;
1549 LIBALIAS_LOCK_ASSERT(la);
1552 link_type = LINK_UDP;
1555 link_type = LINK_TCP;
1562 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create);
1564 if (lnk == NULL && create) {
1565 struct in_addr alias_addr;
1567 alias_addr = FindAliasAddress(la, src_addr);
1568 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1569 src_port, dst_port, GET_ALIAS_PORT,
1577 AddPptp(struct libalias *la, struct in_addr src_addr,
1578 struct in_addr dst_addr,
1579 struct in_addr alias_addr,
1580 u_int16_t src_call_id)
1582 struct alias_link *lnk;
1584 LIBALIAS_LOCK_ASSERT(la);
1585 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1586 src_call_id, 0, GET_ALIAS_PORT,
1594 FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr,
1595 struct in_addr dst_addr,
1596 u_int16_t src_call_id)
1599 struct alias_link *lnk;
1601 LIBALIAS_LOCK_ASSERT(la);
1602 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1603 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1604 if (lnk->link_type == LINK_PPTP &&
1605 lnk->src_addr.s_addr == src_addr.s_addr &&
1606 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1607 lnk->src_port == src_call_id)
1615 FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr,
1616 struct in_addr dst_addr,
1617 u_int16_t dst_call_id)
1620 struct alias_link *lnk;
1622 LIBALIAS_LOCK_ASSERT(la);
1623 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1624 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1625 if (lnk->link_type == LINK_PPTP &&
1626 lnk->src_addr.s_addr == src_addr.s_addr &&
1627 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1628 lnk->dst_port == dst_call_id)
1636 FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr,
1637 struct in_addr alias_addr,
1638 u_int16_t dst_call_id)
1641 struct alias_link *lnk;
1643 LIBALIAS_LOCK_ASSERT(la);
1644 i = StartPointIn(alias_addr, 0, LINK_PPTP);
1645 LIST_FOREACH(lnk, &la->linkTableIn[i], list_in)
1646 if (lnk->link_type == LINK_PPTP &&
1647 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1648 lnk->alias_addr.s_addr == alias_addr.s_addr &&
1649 lnk->dst_port == dst_call_id)
1657 FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr,
1658 struct in_addr alias_addr,
1659 u_int16_t alias_call_id)
1661 struct alias_link *lnk;
1663 LIBALIAS_LOCK_ASSERT(la);
1664 lnk = FindLinkIn(la, dst_addr, alias_addr,
1665 0 /* any */ , alias_call_id,
1674 FindRtspOut(struct libalias *la, struct in_addr src_addr,
1675 struct in_addr dst_addr,
1681 struct alias_link *lnk;
1683 LIBALIAS_LOCK_ASSERT(la);
1686 link_type = LINK_UDP;
1689 link_type = LINK_TCP;
1696 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1);
1699 struct in_addr alias_addr;
1701 alias_addr = FindAliasAddress(la, src_addr);
1702 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1703 src_port, 0, alias_port,
1711 FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
1713 struct alias_link *lnk;
1715 LIBALIAS_LOCK_ASSERT(la);
1716 lnk = FindLinkIn(la, la->nullAddress, alias_addr,
1717 0, 0, LINK_ADDR, 0);
1719 la->newDefaultLink = 1;
1720 if (la->targetAddress.s_addr == INADDR_ANY)
1721 return (alias_addr);
1722 else if (la->targetAddress.s_addr == INADDR_NONE)
1723 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1724 la->aliasAddress : alias_addr;
1726 return (la->targetAddress);
1728 if (lnk->server != NULL) { /* LSNAT link */
1729 struct in_addr src_addr;
1731 src_addr = lnk->server->addr;
1732 lnk->server = lnk->server->next;
1734 } else if (lnk->src_addr.s_addr == INADDR_ANY)
1735 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1736 la->aliasAddress : alias_addr;
1738 return (lnk->src_addr);
1744 FindAliasAddress(struct libalias *la, struct in_addr original_addr)
1746 struct alias_link *lnk;
1748 LIBALIAS_LOCK_ASSERT(la);
1749 lnk = FindLinkOut(la, original_addr, la->nullAddress,
1750 0, 0, LINK_ADDR, 0);
1752 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1753 la->aliasAddress : original_addr;
1755 if (lnk->alias_addr.s_addr == INADDR_ANY)
1756 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1757 la->aliasAddress : original_addr;
1759 return (lnk->alias_addr);
1764 /* External routines for getting or changing link data
1765 (external to alias_db.c, but internal to alias*.c)
1767 SetFragmentData(), GetFragmentData()
1768 SetFragmentPtr(), GetFragmentPtr()
1769 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1770 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1771 GetOriginalPort(), GetAliasPort()
1772 SetAckModified(), GetAckModified()
1773 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1774 SetProtocolFlags(), GetProtocolFlags()
1780 SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
1782 lnk->data.frag_addr = src_addr;
1787 GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
1789 *src_addr = lnk->data.frag_addr;
1794 SetFragmentPtr(struct alias_link *lnk, char *fptr)
1796 lnk->data.frag_ptr = fptr;
1801 GetFragmentPtr(struct alias_link *lnk, char **fptr)
1803 *fptr = lnk->data.frag_ptr;
1808 SetStateIn(struct alias_link *lnk, int state)
1810 /* TCP input state */
1812 case ALIAS_TCP_STATE_DISCONNECTED:
1813 if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED)
1814 lnk->expire_time = TCP_EXPIRE_DEAD;
1816 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1818 case ALIAS_TCP_STATE_CONNECTED:
1819 if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED)
1820 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1824 panic("libalias:SetStateIn() unknown state");
1829 lnk->data.tcp->state.in = state;
1834 SetStateOut(struct alias_link *lnk, int state)
1836 /* TCP output state */
1838 case ALIAS_TCP_STATE_DISCONNECTED:
1839 if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED)
1840 lnk->expire_time = TCP_EXPIRE_DEAD;
1842 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1844 case ALIAS_TCP_STATE_CONNECTED:
1845 if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED)
1846 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1850 panic("libalias:SetStateOut() unknown state");
1855 lnk->data.tcp->state.out = state;
1860 GetStateIn(struct alias_link *lnk)
1862 /* TCP input state */
1863 return (lnk->data.tcp->state.in);
1868 GetStateOut(struct alias_link *lnk)
1870 /* TCP output state */
1871 return (lnk->data.tcp->state.out);
1876 GetOriginalAddress(struct alias_link *lnk)
1878 if (lnk->src_addr.s_addr == INADDR_ANY)
1879 return (lnk->la->aliasAddress);
1881 return (lnk->src_addr);
1886 GetDestAddress(struct alias_link *lnk)
1888 return (lnk->dst_addr);
1893 GetAliasAddress(struct alias_link *lnk)
1895 if (lnk->alias_addr.s_addr == INADDR_ANY)
1896 return (lnk->la->aliasAddress);
1898 return (lnk->alias_addr);
1903 GetDefaultAliasAddress(struct libalias *la)
1906 LIBALIAS_LOCK_ASSERT(la);
1907 return (la->aliasAddress);
1912 SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
1915 LIBALIAS_LOCK_ASSERT(la);
1916 la->aliasAddress = alias_addr;
1921 GetOriginalPort(struct alias_link *lnk)
1923 return (lnk->src_port);
1928 GetAliasPort(struct alias_link *lnk)
1930 return (lnk->alias_port);
1935 GetDestPort(struct alias_link *lnk)
1937 return (lnk->dst_port);
1943 SetAckModified(struct alias_link *lnk)
1945 /* Indicate that ACK numbers have been modified in a TCP connection */
1946 lnk->data.tcp->state.ack_modified = 1;
1951 GetProxyAddress(struct alias_link *lnk)
1953 return (lnk->proxy_addr);
1958 SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
1960 lnk->proxy_addr = addr;
1965 GetProxyPort(struct alias_link *lnk)
1967 return (lnk->proxy_port);
1972 SetProxyPort(struct alias_link *lnk, u_short port)
1974 lnk->proxy_port = port;
1979 GetAckModified(struct alias_link *lnk)
1981 /* See if ACK numbers have been modified */
1982 return (lnk->data.tcp->state.ack_modified);
1987 GetDeltaAckIn(u_long ack, struct alias_link *lnk)
1990 Find out how much the ACK number has been altered for an incoming
1991 TCP packet. To do this, a circular list of ACK numbers where the TCP
1992 packet size was altered is searched.
1996 int delta, ack_diff_min;
2000 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2001 struct ack_data_record x;
2003 x = lnk->data.tcp->ack[i];
2004 if (x.active == 1) {
2007 ack_diff = SeqDiff(x.ack_new, ack);
2008 if (ack_diff >= 0) {
2009 if (ack_diff_min >= 0) {
2010 if (ack_diff < ack_diff_min) {
2012 ack_diff_min = ack_diff;
2016 ack_diff_min = ack_diff;
2026 GetDeltaSeqOut(u_long seq, struct alias_link *lnk)
2029 Find out how much the sequence number has been altered for an outgoing
2030 TCP packet. To do this, a circular list of ACK numbers where the TCP
2031 packet size was altered is searched.
2035 int delta, seq_diff_min;
2039 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2040 struct ack_data_record x;
2042 x = lnk->data.tcp->ack[i];
2043 if (x.active == 1) {
2046 seq_diff = SeqDiff(x.ack_old, seq);
2047 if (seq_diff >= 0) {
2048 if (seq_diff_min >= 0) {
2049 if (seq_diff < seq_diff_min) {
2051 seq_diff_min = seq_diff;
2055 seq_diff_min = seq_diff;
2065 AddSeq(struct alias_link *lnk, int delta, u_int ip_hl, u_short ip_len,
2066 u_long th_seq, u_int th_off)
2069 When a TCP packet has been altered in length, save this
2070 information in a circular list. If enough packets have
2071 been altered, then this list will begin to overwrite itself.
2074 struct ack_data_record x;
2075 int hlen, tlen, dlen;
2078 hlen = (ip_hl + th_off) << 2;
2079 tlen = ntohs(ip_len);
2082 x.ack_old = htonl(ntohl(th_seq) + dlen);
2083 x.ack_new = htonl(ntohl(th_seq) + dlen + delta);
2087 i = lnk->data.tcp->state.index;
2088 lnk->data.tcp->ack[i] = x;
2091 if (i == N_LINK_TCP_DATA)
2092 lnk->data.tcp->state.index = 0;
2094 lnk->data.tcp->state.index = i;
2098 SetExpire(struct alias_link *lnk, int expire)
2101 lnk->flags &= ~LINK_PERMANENT;
2103 } else if (expire == -1) {
2104 lnk->flags |= LINK_PERMANENT;
2105 } else if (expire > 0) {
2106 lnk->expire_time = expire;
2108 #ifdef LIBALIAS_DEBUG
2109 fprintf(stderr, "PacketAlias/SetExpire(): ");
2110 fprintf(stderr, "error in expire parameter\n");
2116 ClearCheckNewLink(struct libalias *la)
2119 LIBALIAS_LOCK_ASSERT(la);
2120 la->newDefaultLink = 0;
2124 SetProtocolFlags(struct alias_link *lnk, int pflags)
2127 lnk->pflags = pflags;
2131 GetProtocolFlags(struct alias_link *lnk)
2134 return (lnk->pflags);
2138 SetDestCallId(struct alias_link *lnk, u_int16_t cid)
2140 struct libalias *la = lnk->la;
2142 LIBALIAS_LOCK_ASSERT(la);
2143 la->deleteAllLinks = 1;
2144 ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr,
2145 lnk->src_port, cid, lnk->alias_port, lnk->link_type);
2146 la->deleteAllLinks = 0;
2150 /* Miscellaneous Functions
2153 InitPacketAliasLog()
2154 UninitPacketAliasLog()
2158 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2159 is called to find and remove timed-out aliasing links. Logic exists
2160 to sweep through the entire table and linked list structure
2163 (prototype in alias_local.h)
2167 HouseKeeping(struct libalias *la)
2174 LIBALIAS_LOCK_ASSERT(la);
2176 * Save system time (seconds) in global variable timeStamp for use
2177 * by other functions. This is done so as not to unnecessarily
2178 * waste timeline by making system calls.
2181 la->timeStamp = time_uptime;
2183 gettimeofday(&tv, NULL);
2184 la->timeStamp = tv.tv_sec;
2187 /* Compute number of spokes (output table link chains) to cover */
2188 n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime);
2189 n /= ALIAS_CLEANUP_INTERVAL_SECS;
2191 /* Handle different cases */
2193 if (n > ALIAS_CLEANUP_MAX_SPOKES)
2194 n = ALIAS_CLEANUP_MAX_SPOKES;
2195 la->lastCleanupTime = la->timeStamp;
2196 for (i = 0; i < n; i++)
2197 IncrementalCleanup(la);
2199 #ifdef LIBALIAS_DEBUG
2200 fprintf(stderr, "PacketAlias/HouseKeeping(): ");
2201 fprintf(stderr, "something unexpected in time values\n");
2203 la->lastCleanupTime = la->timeStamp;
2207 /* Init the log file and enable logging */
2209 InitPacketAliasLog(struct libalias *la)
2212 LIBALIAS_LOCK_ASSERT(la);
2213 if (~la->packetAliasMode & PKT_ALIAS_LOG) {
2215 if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
2218 if ((la->logDesc = fopen("/var/log/alias.log", "w")))
2219 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2222 return (ENOMEM); /* log initialization failed */
2223 la->packetAliasMode |= PKT_ALIAS_LOG;
2229 /* Close the log-file and disable logging. */
2231 UninitPacketAliasLog(struct libalias *la)
2234 LIBALIAS_LOCK_ASSERT(la);
2239 fclose(la->logDesc);
2243 la->packetAliasMode &= ~PKT_ALIAS_LOG;
2246 /* Outside world interfaces
2248 -- "outside world" means other than alias*.c routines --
2250 PacketAliasRedirectPort()
2251 PacketAliasAddServer()
2252 PacketAliasRedirectProto()
2253 PacketAliasRedirectAddr()
2254 PacketAliasRedirectDynamic()
2255 PacketAliasRedirectDelete()
2256 PacketAliasSetAddress()
2259 PacketAliasSetMode()
2261 (prototypes in alias.h)
2264 /* Redirection from a specific public addr:port to a
2265 private addr:port */
2267 LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port,
2268 struct in_addr dst_addr, u_short dst_port,
2269 struct in_addr alias_addr, u_short alias_port,
2273 struct alias_link *lnk;
2278 link_type = LINK_UDP;
2281 link_type = LINK_TCP;
2284 link_type = LINK_SCTP;
2287 #ifdef LIBALIAS_DEBUG
2288 fprintf(stderr, "PacketAliasRedirectPort(): ");
2289 fprintf(stderr, "only SCTP, TCP and UDP protocols allowed\n");
2295 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2296 src_port, dst_port, alias_port,
2300 lnk->flags |= LINK_PERMANENT;
2302 #ifdef LIBALIAS_DEBUG
2304 fprintf(stderr, "PacketAliasRedirectPort(): "
2305 "call to AddLink() failed\n");
2310 LIBALIAS_UNLOCK(la);
2314 /* Add server to the pool of servers */
2316 LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
2318 struct server *server;
2324 server = malloc(sizeof(struct server));
2326 if (server != NULL) {
2327 struct server *head;
2329 server->addr = addr;
2330 server->port = port;
2334 server->next = server;
2338 for (s = head; s->next != head; s = s->next);
2340 server->next = head;
2342 lnk->server = server;
2347 LIBALIAS_UNLOCK(la);
2351 /* Redirect packets of a given IP protocol from a specific
2352 public address to a private address */
2354 LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr,
2355 struct in_addr dst_addr,
2356 struct in_addr alias_addr,
2359 struct alias_link *lnk;
2362 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2363 NO_SRC_PORT, NO_DEST_PORT, 0,
2367 lnk->flags |= LINK_PERMANENT;
2369 #ifdef LIBALIAS_DEBUG
2371 fprintf(stderr, "PacketAliasRedirectProto(): "
2372 "call to AddLink() failed\n");
2376 LIBALIAS_UNLOCK(la);
2380 /* Static address translation */
2382 LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr,
2383 struct in_addr alias_addr)
2385 struct alias_link *lnk;
2388 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
2393 lnk->flags |= LINK_PERMANENT;
2395 #ifdef LIBALIAS_DEBUG
2397 fprintf(stderr, "PacketAliasRedirectAddr(): "
2398 "call to AddLink() failed\n");
2402 LIBALIAS_UNLOCK(la);
2407 /* Mark the aliasing link dynamic */
2409 LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
2416 if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
2419 lnk->flags &= ~LINK_PERMANENT;
2422 LIBALIAS_UNLOCK(la);
2428 LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
2430 /* This is a dangerous function to put in the API,
2431 because an invalid pointer can crash the program. */
2434 la->deleteAllLinks = 1;
2436 la->deleteAllLinks = 0;
2437 LIBALIAS_UNLOCK(la);
2442 LibAliasSetAddress(struct libalias *la, struct in_addr addr)
2446 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2447 && la->aliasAddress.s_addr != addr.s_addr)
2448 CleanupAliasData(la);
2450 la->aliasAddress = addr;
2451 LIBALIAS_UNLOCK(la);
2456 LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2460 la->targetAddress = target_addr;
2461 LIBALIAS_UNLOCK(la);
2468 while (!LIST_EMPTY(&instancehead))
2469 LibAliasUninit(LIST_FIRST(&instancehead));
2473 LibAliasInit(struct libalias *la)
2482 #undef malloc /* XXX: ugly */
2483 la = malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO);
2485 la = calloc(sizeof *la, 1);
2490 #ifndef _KERNEL /* kernel cleans up on module unload */
2491 if (LIST_EMPTY(&instancehead))
2494 LIST_INSERT_HEAD(&instancehead, la, instancelist);
2497 la->timeStamp = time_uptime;
2498 la->lastCleanupTime = time_uptime;
2500 gettimeofday(&tv, NULL);
2501 la->timeStamp = tv.tv_sec;
2502 la->lastCleanupTime = tv.tv_sec;
2505 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
2506 LIST_INIT(&la->linkTableOut[i]);
2507 for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
2508 LIST_INIT(&la->linkTableIn[i]);
2512 LIBALIAS_LOCK_INIT(la);
2516 la->deleteAllLinks = 1;
2517 CleanupAliasData(la);
2518 la->deleteAllLinks = 0;
2525 la->aliasAddress.s_addr = INADDR_ANY;
2526 la->targetAddress.s_addr = INADDR_ANY;
2528 la->icmpLinkCount = 0;
2529 la->udpLinkCount = 0;
2530 la->tcpLinkCount = 0;
2531 la->sctpLinkCount = 0;
2532 la->pptpLinkCount = 0;
2533 la->protoLinkCount = 0;
2534 la->fragmentIdLinkCount = 0;
2535 la->fragmentPtrLinkCount = 0;
2538 la->cleanupIndex = 0;
2540 la->packetAliasMode = PKT_ALIAS_SAME_PORTS
2541 #ifndef NO_USE_SOCKETS
2542 | PKT_ALIAS_USE_SOCKETS
2544 | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2546 la->fireWallFD = -1;
2549 LibAliasRefreshModules();
2551 LIBALIAS_UNLOCK(la);
2556 LibAliasUninit(struct libalias *la)
2563 la->deleteAllLinks = 1;
2564 CleanupAliasData(la);
2565 la->deleteAllLinks = 0;
2566 UninitPacketAliasLog(la);
2570 LIST_REMOVE(la, instancelist);
2571 LIBALIAS_UNLOCK(la);
2572 LIBALIAS_LOCK_DESTROY(la);
2576 /* Change mode for some operations */
2579 struct libalias *la,
2580 unsigned int flags, /* Which state to bring flags to */
2581 unsigned int mask /* Mask of which flags to affect (use 0 to
2582 * do a probe for flag values) */
2588 /* Enable logging? */
2589 if (flags & mask & PKT_ALIAS_LOG) {
2591 if (InitPacketAliasLog(la) == ENOMEM)
2594 /* _Disable_ logging? */
2595 if (~flags & mask & PKT_ALIAS_LOG) {
2596 UninitPacketAliasLog(la);
2599 /* Start punching holes in the firewall? */
2600 if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2603 /* Stop punching holes in the firewall? */
2604 if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2609 /* Other flags can be set/cleared without special action */
2610 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2611 res = la->packetAliasMode;
2613 LIBALIAS_UNLOCK(la);
2619 LibAliasCheckNewLink(struct libalias *la)
2624 res = la->newDefaultLink;
2625 LIBALIAS_UNLOCK(la);
2633 Code to support firewall punching. This shouldn't really be in this
2634 file, but making variables global is evil too.
2637 /* Firewall include files */
2639 #include <netinet/ip_fw.h>
2644 * helper function, updates the pointer to cmd with the length
2645 * of the current command, and also cleans up the first word of
2646 * the new command in case it has been clobbered before.
2649 next_cmd(ipfw_insn * cmd)
2652 bzero(cmd, sizeof(*cmd));
2657 * A function to fill simple commands of size 1.
2658 * Existing flags are preserved.
2661 fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2662 int flags, u_int16_t arg)
2664 cmd->opcode = opcode;
2665 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2667 return next_cmd(cmd);
2671 fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2673 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1;
2675 cmd->addr.s_addr = addr;
2676 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2680 fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2682 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1;
2684 cmd->ports[0] = cmd->ports[1] = port;
2685 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2689 fill_rule(void *buf, int bufsize, int rulenum,
2690 enum ipfw_opcodes action, int proto,
2691 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
2693 struct ip_fw *rule = (struct ip_fw *)buf;
2694 ipfw_insn *cmd = (ipfw_insn *) rule->cmd;
2696 bzero(buf, bufsize);
2697 rule->rulenum = rulenum;
2699 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto);
2700 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr);
2701 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp);
2702 cmd = fill_ip(cmd, O_IP_DST, da.s_addr);
2703 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
2705 rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2706 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
2708 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2710 return ((char *)cmd - (char *)buf);
2713 static void ClearAllFWHoles(struct libalias *la);
2716 #define fw_setfield(la, field, num) \
2718 (field)[(num) - la->fireWallBaseNum] = 1; \
2719 } /*lint -save -e717 */ while(0)/* lint -restore */
2721 #define fw_clrfield(la, field, num) \
2723 (field)[(num) - la->fireWallBaseNum] = 0; \
2724 } /*lint -save -e717 */ while(0)/* lint -restore */
2726 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2729 InitPunchFW(struct libalias *la)
2732 la->fireWallField = malloc(la->fireWallNumNums);
2733 if (la->fireWallField) {
2734 memset(la->fireWallField, 0, la->fireWallNumNums);
2735 if (la->fireWallFD < 0) {
2736 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2738 ClearAllFWHoles(la);
2739 la->fireWallActiveNum = la->fireWallBaseNum;
2744 UninitPunchFW(struct libalias *la)
2747 ClearAllFWHoles(la);
2748 if (la->fireWallFD >= 0)
2749 close(la->fireWallFD);
2750 la->fireWallFD = -1;
2751 if (la->fireWallField)
2752 free(la->fireWallField);
2753 la->fireWallField = NULL;
2754 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2757 /* Make a certain link go through the firewall */
2759 PunchFWHole(struct alias_link *lnk)
2761 struct libalias *la;
2762 int r; /* Result code */
2763 struct ip_fw rule; /* On-the-fly built rule */
2764 int fwhole; /* Where to punch hole */
2768 /* Don't do anything unless we are asked to */
2769 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2770 la->fireWallFD < 0 ||
2771 lnk->link_type != LINK_TCP)
2774 memset(&rule, 0, sizeof rule);
2778 /* Find empty slot */
2779 for (fwhole = la->fireWallActiveNum;
2780 fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2781 fw_tstfield(la, la->fireWallField, fwhole);
2783 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2784 for (fwhole = la->fireWallBaseNum;
2785 fwhole < la->fireWallActiveNum &&
2786 fw_tstfield(la, la->fireWallField, fwhole);
2788 if (fwhole == la->fireWallActiveNum) {
2789 /* No rule point empty - we can't punch more holes. */
2790 la->fireWallActiveNum = la->fireWallBaseNum;
2791 #ifdef LIBALIAS_DEBUG
2792 fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2797 /* Start next search at next position */
2798 la->fireWallActiveNum = fwhole + 1;
2801 * generate two rules of the form
2803 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2804 * accept tcp from DAddr DPort to OAddr OPort
2806 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2807 u_int32_t rulebuf[255];
2810 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2811 O_ACCEPT, IPPROTO_TCP,
2812 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
2813 GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
2814 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2816 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2818 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2819 O_ACCEPT, IPPROTO_TCP,
2820 GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
2821 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
2822 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2824 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2827 /* Indicate hole applied */
2828 lnk->data.tcp->fwhole = fwhole;
2829 fw_setfield(la, la->fireWallField, fwhole);
2832 /* Remove a hole in a firewall associated with a particular alias
2833 lnk. Calling this too often is harmless. */
2835 ClearFWHole(struct alias_link *lnk)
2837 struct libalias *la;
2840 if (lnk->link_type == LINK_TCP) {
2841 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall
2848 memset(&rule, 0, sizeof rule); /* useless for ipfw2 */
2849 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL,
2850 &fwhole, sizeof fwhole));
2851 fw_clrfield(la, la->fireWallField, fwhole);
2852 lnk->data.tcp->fwhole = -1;
2856 /* Clear out the entire range dedicated to firewall holes. */
2858 ClearAllFWHoles(struct libalias *la)
2860 struct ip_fw rule; /* On-the-fly built rule */
2863 if (la->fireWallFD < 0)
2866 memset(&rule, 0, sizeof rule);
2867 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2870 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2872 /* XXX: third arg correct here ? /phk */
2873 memset(la->fireWallField, 0, la->fireWallNumNums);
2876 #endif /* !NO_FW_PUNCH */
2879 LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2884 la->fireWallBaseNum = base;
2885 la->fireWallNumNums = num;
2887 LIBALIAS_UNLOCK(la);
2891 LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2895 la->skinnyPort = port;
2896 LIBALIAS_UNLOCK(la);
2900 * Find the address to redirect incoming packets
2903 FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm)
2905 struct alias_link *lnk;
2906 struct in_addr redir;
2908 LIBALIAS_LOCK_ASSERT(la);
2909 lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst,
2910 sm->sctp_hdr->dest_port,sm->sctp_hdr->dest_port, LINK_SCTP, 1);
2912 return(lnk->src_addr); /* port redirect */
2914 redir = FindOriginalAddress(la,sm->ip_hdr->ip_dst);
2915 if (redir.s_addr == la->aliasAddress.s_addr ||
2916 redir.s_addr == la->targetAddress.s_addr) { /* No address found */
2917 lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst,
2918 NO_DEST_PORT, 0, LINK_SCTP, 1);
2920 return(lnk->src_addr); /* redirect proto */
2922 return(redir); /* address redirect */