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.
52 Initial version: August, 1996 (cjm)
54 Version 1.4: September 16, 1996 (cjm)
55 Facility for handling incoming links added.
57 Version 1.6: September 18, 1996 (cjm)
58 ICMP data handling simplified.
60 Version 1.7: January 9, 1997 (cjm)
61 Fragment handling simplified.
62 Saves pointers for unresolved fragments.
63 Permits links for unspecified remote ports
64 or unspecified remote addresses.
65 Fixed bug which did not properly zero port
66 table entries after a link was deleted.
67 Cleaned up some obsolete comments.
69 Version 1.8: January 14, 1997 (cjm)
70 Fixed data type error in StartPoint().
71 (This error did not exist prior to v1.7
72 and was discovered and fixed by Ari Suutari)
74 Version 1.9: February 1, 1997
75 Optionally, connections initiated from packet aliasing host
76 machine will will not have their port number aliased unless it
77 conflicts with an aliasing port already being used. (cjm)
79 All options earlier being #ifdef'ed are now available through
80 a new interface, SetPacketAliasMode(). This allows run time
81 control (which is now available in PPP+pktAlias through the
82 'alias' keyword). (ee)
84 Added ability to create an alias port without
85 either destination address or port specified.
86 port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
88 Removed K&R style function headers
89 and general cleanup. (ee)
91 Added packetAliasMode to replace compiler #defines's (ee)
93 Allocates sockets for partially specified
94 ports if ALIAS_USE_SOCKETS defined. (cjm)
96 Version 2.0: March, 1997
97 SetAliasAddress() will now clean up alias links
98 if the aliasing address is changed. (cjm)
100 PacketAliasPermanentLink() function added to support permanent
101 links. (J. Fortes suggested the need for this.)
104 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
106 (192.168.0.2, port 21) <-> alias port 3604, known dest addr
109 These permanent links allow for incoming connections to
110 machines on the local network. They can be given with a
111 user-chosen amount of specificity, with increasing specificity
112 meaning more security. (cjm)
114 Quite a bit of rework to the basic engine. The portTable[]
115 array, which kept track of which ports were in use was replaced
116 by a table/linked list structure. (cjm)
118 SetExpire() function added. (cjm)
120 DeleteLink() no longer frees memory association with a pointer
121 to a fragment (this bug was first recognized by E. Eklund in
124 Version 2.1: May, 1997 (cjm)
125 Packet aliasing engine reworked so that it can handle
126 multiple external addresses rather than just a single
129 PacketAliasRedirectPort() and PacketAliasRedirectAddr()
130 added to the API. The first function is a more generalized
131 version of PacketAliasPermanentLink(). The second function
132 implements static network address translation.
134 Version 3.2: July, 2000 (salander and satoh)
135 Added FindNewPortGroup to get contiguous range of port values.
137 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
138 link but not actually add one.
140 Added FindRtspOut, which is closely derived from FindUdpTcpOut,
141 except that the alias port (from FindNewPortGroup) is provided
144 See HISTORY file for additional revisions.
148 #include <machine/stdarg.h>
149 #include <sys/param.h>
150 #include <sys/kernel.h>
151 #include <sys/systm.h>
152 #include <sys/lock.h>
153 #include <sys/module.h>
154 #include <sys/rwlock.h>
155 #include <sys/syslog.h>
160 #include <sys/errno.h>
161 #include <sys/time.h>
165 #include <sys/socket.h>
166 #include <netinet/tcp.h>
169 #include <netinet/libalias/alias.h>
170 #include <netinet/libalias/alias_local.h>
171 #include <netinet/libalias/alias_mod.h>
175 #include "alias_local.h"
176 #include "alias_mod.h"
179 static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
183 Constants (note: constants are also defined
184 near relevant functions or structs)
187 /* Parameters used for cleanup of expired links */
188 /* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */
189 #define ALIAS_CLEANUP_INTERVAL_SECS 64
190 #define ALIAS_CLEANUP_MAX_SPOKES (LINK_TABLE_OUT_SIZE/5)
192 /* Timeouts (in seconds) for different link types */
193 #define ICMP_EXPIRE_TIME 60
194 #define UDP_EXPIRE_TIME 60
195 #define PROTO_EXPIRE_TIME 60
196 #define FRAGMENT_ID_EXPIRE_TIME 10
197 #define FRAGMENT_PTR_EXPIRE_TIME 30
199 /* TCP link expire time for different cases */
200 /* When the link has been used and closed - minimal grace time to
201 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
202 #ifndef TCP_EXPIRE_DEAD
203 #define TCP_EXPIRE_DEAD 10
206 /* When the link has been used and closed on one side - the other side
207 is allowed to still send data */
208 #ifndef TCP_EXPIRE_SINGLEDEAD
209 #define TCP_EXPIRE_SINGLEDEAD 90
212 /* When the link isn't yet up */
213 #ifndef TCP_EXPIRE_INITIAL
214 #define TCP_EXPIRE_INITIAL 300
217 /* When the link is up */
218 #ifndef TCP_EXPIRE_CONNECTED
219 #define TCP_EXPIRE_CONNECTED 86400
223 /* Dummy port number codes used for FindLinkIn/Out() and AddLink().
224 These constants can be anything except zero, which indicates an
225 unknown port number. */
227 #define NO_DEST_PORT 1
228 #define NO_SRC_PORT 1
234 The fundamental data structure used in this program is
235 "struct alias_link". Whenever a TCP connection is made,
236 a UDP datagram is sent out, or an ICMP echo request is made,
237 a link record is made (if it has not already been created).
238 The link record is identified by the source address/port
239 and the destination address/port. In the case of an ICMP
240 echo request, the source port is treated as being equivalent
241 with the 16-bit ID number of the ICMP packet.
243 The link record also can store some auxiliary data. For
244 TCP connections that have had sequence and acknowledgment
245 modifications, data space is available to track these changes.
246 A state field is used to keep track in changes to the TCP
247 connection state. ID numbers of fragments can also be
248 stored in the auxiliary space. Pointers to unresolved
249 fragments can also be stored.
251 The link records support two independent chainings. Lookup
252 tables for input and out tables hold the initial pointers
253 the link chains. On input, the lookup table indexes on alias
254 port and link type. On output, the lookup table indexes on
255 source address, destination address, source port, destination
259 struct ack_data_record { /* used to save changes to ACK/sequence
267 struct tcp_state { /* Information about TCP connection */
268 int in; /* State for outside -> inside */
269 int out; /* State for inside -> outside */
270 int index; /* Index to ACK data array */
271 int ack_modified; /* Indicates whether ACK and
272 * sequence numbers */
276 #define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes
277 * saved for a modified TCP stream */
279 struct tcp_state state;
280 struct ack_data_record ack[N_LINK_TCP_DATA];
281 int fwhole; /* Which firewall record is used for this
285 struct server { /* LSNAT server pool (circular list) */
291 struct alias_link { /* Main data structure */
293 struct in_addr src_addr; /* Address and port information */
294 struct in_addr dst_addr;
295 struct in_addr alias_addr;
296 struct in_addr proxy_addr;
301 struct server *server;
303 int link_type; /* Type of link: TCP, UDP, ICMP,
306 /* values for link_type */
307 #define LINK_ICMP IPPROTO_ICMP
308 #define LINK_UDP IPPROTO_UDP
309 #define LINK_TCP IPPROTO_TCP
310 #define LINK_FRAGMENT_ID (IPPROTO_MAX + 1)
311 #define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2)
312 #define LINK_ADDR (IPPROTO_MAX + 3)
313 #define LINK_PPTP (IPPROTO_MAX + 4)
315 int flags; /* indicates special characteristics */
316 int pflags; /* protocol-specific flags */
319 #define LINK_UNKNOWN_DEST_PORT 0x01
320 #define LINK_UNKNOWN_DEST_ADDR 0x02
321 #define LINK_PERMANENT 0x04
322 #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
323 #define LINK_UNFIREWALLED 0x08
325 int timestamp; /* Time link was last accessed */
326 int expire_time; /* Expire time for link */
327 #ifndef NO_USE_SOCKETS
328 int sockfd; /* socket descriptor */
330 LIST_ENTRY (alias_link) list_out; /* Linked list of
332 LIST_ENTRY (alias_link) list_in; /* input and output
335 union { /* Auxiliary data */
337 struct in_addr frag_addr;
342 /* Clean up procedure. */
343 static void finishoff(void);
345 /* Kernel module definition. */
347 MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing");
349 MODULE_VERSION(libalias, 1);
352 alias_mod_handler(module_t mod, int type, void *data)
366 static moduledata_t alias_mod = {
367 "alias", alias_mod_handler, NULL
370 DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
373 /* Internal utility routines (used only in alias_db.c)
375 Lookup table starting points:
376 StartPointIn() -- link table initial search point for
378 StartPointOut() -- link table initial search point for
382 SeqDiff() -- difference between two TCP sequences
383 ShowAliasStats() -- send alias statistics to a monitor file
387 /* Local prototypes */
388 static u_int StartPointIn(struct in_addr, u_short, int);
391 StartPointOut(struct in_addr, struct in_addr,
392 u_short, u_short, int);
394 static int SeqDiff(u_long, u_long);
397 /* Firewall control */
398 static void InitPunchFW(struct libalias *);
399 static void UninitPunchFW(struct libalias *);
400 static void ClearFWHole(struct alias_link *);
404 /* Log file control */
405 static void ShowAliasStats(struct libalias *);
406 static int InitPacketAliasLog(struct libalias *);
407 static void UninitPacketAliasLog(struct libalias *);
409 void SctpShowAliasStats(struct libalias *la);
412 StartPointIn(struct in_addr alias_addr,
418 n = alias_addr.s_addr;
419 if (link_type != LINK_PPTP)
422 return (n % LINK_TABLE_IN_SIZE);
427 StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
428 u_short src_port, u_short dst_port, int link_type)
433 n += dst_addr.s_addr;
434 if (link_type != LINK_PPTP) {
440 return (n % LINK_TABLE_OUT_SIZE);
445 SeqDiff(u_long x, u_long y)
447 /* Return the difference between two TCP sequence numbers */
450 This function is encapsulated in case there are any unusual
451 arithmetic conditions that need to be considered.
454 return (ntohl(y) - ntohl(x));
460 AliasLog(char *str, const char *format, ...)
464 va_start(ap, format);
465 vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
470 AliasLog(FILE *stream, const char *format, ...)
474 va_start(ap, format);
475 vfprintf(stream, format, ap);
482 ShowAliasStats(struct libalias *la)
485 LIBALIAS_LOCK_ASSERT(la);
486 /* Used for debugging */
488 int tot = la->icmpLinkCount + la->udpLinkCount +
489 (la->sctpLinkCount>>1) + /* sctp counts half associations */
490 la->tcpLinkCount + la->pptpLinkCount +
491 la->protoLinkCount + la->fragmentIdLinkCount +
492 la->fragmentPtrLinkCount;
494 AliasLog(la->logDesc,
495 "icmp=%u, udp=%u, tcp=%u, sctp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
499 la->sctpLinkCount>>1, /* sctp counts half associations */
502 la->fragmentIdLinkCount,
503 la->fragmentPtrLinkCount, tot);
505 AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
510 void SctpShowAliasStats(struct libalias *la)
517 /* Internal routines for finding, deleting and adding links
520 GetNewPort() -- find and reserve new alias port number
521 GetSocket() -- try to allocate a socket for a given port
523 Link creation and deletion:
524 CleanupAliasData() - remove all link chains from lookup table
525 IncrementalCleanup() - look for stale links in a single chain
526 DeleteLink() - remove link
528 ReLink() - change link
531 FindLinkOut() - find link for outgoing packets
532 FindLinkIn() - find link for incoming packets
535 FindNewPortGroup() - find an available group of ports
538 /* Local prototypes */
539 static int GetNewPort(struct libalias *, struct alias_link *, int);
540 #ifndef NO_USE_SOCKETS
541 static u_short GetSocket(struct libalias *, u_short, int *, int);
543 static void CleanupAliasData(struct libalias *);
545 static void IncrementalCleanup(struct libalias *);
547 static void DeleteLink(struct alias_link *);
549 static struct alias_link *
550 ReLink(struct alias_link *,
551 struct in_addr, struct in_addr, struct in_addr,
552 u_short, u_short, int, int);
554 static struct alias_link *
555 FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
557 static struct alias_link *
558 FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
561 #define ALIAS_PORT_BASE 0x08000
562 #define ALIAS_PORT_MASK 0x07fff
563 #define ALIAS_PORT_MASK_EVEN 0x07ffe
564 #define GET_NEW_PORT_MAX_ATTEMPTS 20
566 #define FIND_EVEN_ALIAS_BASE 1
568 /* GetNewPort() allocates port numbers. Note that if a port number
569 is already in use, that does not mean that it cannot be used by
570 another link concurrently. This is because GetNewPort() looks for
571 unused triplets: (dest addr, dest port, alias port). */
574 GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
581 LIBALIAS_LOCK_ASSERT(la);
583 Description of alias_port_param for GetNewPort(). When
584 this parameter is zero or positive, it precisely specifies
585 the port number. GetNewPort() will return this number
586 without check that it is in use.
588 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
589 selected port number.
592 if (alias_port_param == GET_ALIAS_PORT) {
594 * The aliasing port is automatically selected by one of
597 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
599 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
601 * When the PKT_ALIAS_SAME_PORTS option is chosen,
602 * the first try will be the actual source port. If
603 * this is already in use, the remainder of the
604 * trials will be random.
606 port_net = lnk->src_port;
607 port_sys = ntohs(port_net);
609 /* First trial and all subsequent are random. */
610 port_sys = arc4random() & ALIAS_PORT_MASK;
611 port_sys += ALIAS_PORT_BASE;
612 port_net = htons(port_sys);
614 } else if (alias_port_param >= 0 && alias_port_param < 0x10000) {
615 lnk->alias_port = (u_short) alias_port_param;
618 #ifdef LIBALIAS_DEBUG
619 fprintf(stderr, "PacketAlias/GetNewPort(): ");
620 fprintf(stderr, "input parameter error\n");
626 /* Port number search */
627 for (i = 0; i < max_trials; i++) {
629 struct alias_link *search_result;
631 search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr,
632 lnk->dst_port, port_net,
635 if (search_result == NULL)
637 else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED)
638 && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
644 #ifndef NO_USE_SOCKETS
645 if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS)
646 && (lnk->flags & LINK_PARTIALLY_SPECIFIED)
647 && ((lnk->link_type == LINK_TCP) ||
648 (lnk->link_type == LINK_UDP))) {
649 if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) {
650 lnk->alias_port = port_net;
655 lnk->alias_port = port_net;
657 #ifndef NO_USE_SOCKETS
661 port_sys = arc4random() & ALIAS_PORT_MASK;
662 port_sys += ALIAS_PORT_BASE;
663 port_net = htons(port_sys);
666 #ifdef LIBALIAS_DEBUG
667 fprintf(stderr, "PacketAlias/GetNewPort(): ");
668 fprintf(stderr, "could not find free port\n");
674 #ifndef NO_USE_SOCKETS
676 GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
680 struct sockaddr_in sock_addr;
682 LIBALIAS_LOCK_ASSERT(la);
683 if (link_type == LINK_TCP)
684 sock = socket(AF_INET, SOCK_STREAM, 0);
685 else if (link_type == LINK_UDP)
686 sock = socket(AF_INET, SOCK_DGRAM, 0);
688 #ifdef LIBALIAS_DEBUG
689 fprintf(stderr, "PacketAlias/GetSocket(): ");
690 fprintf(stderr, "incorrect link type\n");
696 #ifdef LIBALIAS_DEBUG
697 fprintf(stderr, "PacketAlias/GetSocket(): ");
698 fprintf(stderr, "socket() error %d\n", *sockfd);
702 sock_addr.sin_family = AF_INET;
703 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
704 sock_addr.sin_port = port_net;
707 (struct sockaddr *)&sock_addr,
720 /* FindNewPortGroup() returns a base port number for an available
721 range of contiguous port numbers. Note that if a port number
722 is already in use, that does not mean that it cannot be used by
723 another link concurrently. This is because FindNewPortGroup()
724 looks for unused triplets: (dest addr, dest port, alias port). */
727 FindNewPortGroup(struct libalias *la,
728 struct in_addr dst_addr,
729 struct in_addr alias_addr,
741 LIBALIAS_LOCK_ASSERT(la);
743 * Get link_type from protocol
748 link_type = LINK_UDP;
751 link_type = LINK_TCP;
759 * The aliasing port is automatically selected by one of two
762 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
764 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
766 * When the ALIAS_SAME_PORTS option is chosen, the first
767 * try will be the actual source port. If this is already
768 * in use, the remainder of the trials will be random.
770 port_sys = ntohs(src_port);
774 /* First trial and all subsequent are random. */
775 if (align == FIND_EVEN_ALIAS_BASE)
776 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
778 port_sys = arc4random() & ALIAS_PORT_MASK;
780 port_sys += ALIAS_PORT_BASE;
783 /* Port number search */
784 for (i = 0; i < max_trials; i++) {
786 struct alias_link *search_result;
788 for (j = 0; j < port_count; j++)
789 if ((search_result = FindLinkIn(la, dst_addr,
790 alias_addr, dst_port, htons(port_sys + j),
791 link_type, 0)) != NULL)
794 /* Found a good range, return base */
796 return (htons(port_sys));
798 /* Find a new base to try */
799 if (align == FIND_EVEN_ALIAS_BASE)
800 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
802 port_sys = arc4random() & ALIAS_PORT_MASK;
804 port_sys += ALIAS_PORT_BASE;
807 #ifdef LIBALIAS_DEBUG
808 fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
809 fprintf(stderr, "could not find free port(s)\n");
816 CleanupAliasData(struct libalias *la)
818 struct alias_link *lnk;
821 LIBALIAS_LOCK_ASSERT(la);
822 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) {
823 lnk = LIST_FIRST(&la->linkTableOut[i]);
824 while (lnk != NULL) {
825 struct alias_link *link_next = LIST_NEXT(lnk, list_out);
831 la->cleanupIndex = 0;
836 IncrementalCleanup(struct libalias *la)
838 struct alias_link *lnk, *lnk_tmp;
840 LIBALIAS_LOCK_ASSERT(la);
841 LIST_FOREACH_SAFE(lnk, &la->linkTableOut[la->cleanupIndex++],
843 if (la->timeStamp - lnk->timestamp > lnk->expire_time)
847 if (la->cleanupIndex == LINK_TABLE_OUT_SIZE)
848 la->cleanupIndex = 0;
852 DeleteLink(struct alias_link *lnk)
854 struct libalias *la = lnk->la;
856 LIBALIAS_LOCK_ASSERT(la);
857 /* Don't do anything if the link is marked permanent */
858 if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT)
862 /* Delete associated firewall hole, if any */
866 /* Free memory allocated for LSNAT server pool */
867 if (lnk->server != NULL) {
868 struct server *head, *curr, *next;
870 head = curr = lnk->server;
874 } while ((curr = next) != head);
876 /* Adjust output table pointers */
877 LIST_REMOVE(lnk, list_out);
879 /* Adjust input table pointers */
880 LIST_REMOVE(lnk, list_in);
881 #ifndef NO_USE_SOCKETS
882 /* Close socket, if one has been allocated */
883 if (lnk->sockfd != -1) {
888 /* Link-type dependent cleanup */
889 switch (lnk->link_type) {
903 case LINK_FRAGMENT_ID:
904 la->fragmentIdLinkCount--;
906 case LINK_FRAGMENT_PTR:
907 la->fragmentPtrLinkCount--;
908 if (lnk->data.frag_ptr != NULL)
909 free(lnk->data.frag_ptr);
914 la->protoLinkCount--;
921 /* Write statistics, if logging enabled */
922 if (la->packetAliasMode & PKT_ALIAS_LOG) {
929 AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr,
930 struct in_addr alias_addr, u_short src_port, u_short dst_port,
931 int alias_port_param, int link_type)
934 struct alias_link *lnk;
936 LIBALIAS_LOCK_ASSERT(la);
937 lnk = malloc(sizeof(struct alias_link));
939 /* Basic initialization */
941 lnk->src_addr = src_addr;
942 lnk->dst_addr = dst_addr;
943 lnk->alias_addr = alias_addr;
944 lnk->proxy_addr.s_addr = INADDR_ANY;
945 lnk->src_port = src_port;
946 lnk->dst_port = dst_port;
949 lnk->link_type = link_type;
950 #ifndef NO_USE_SOCKETS
955 lnk->timestamp = la->timeStamp;
957 /* Expiration time */
960 lnk->expire_time = ICMP_EXPIRE_TIME;
963 lnk->expire_time = UDP_EXPIRE_TIME;
966 lnk->expire_time = TCP_EXPIRE_INITIAL;
969 lnk->flags |= LINK_PERMANENT; /* no timeout. */
971 case LINK_FRAGMENT_ID:
972 lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME;
974 case LINK_FRAGMENT_PTR:
975 lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
980 lnk->expire_time = PROTO_EXPIRE_TIME;
984 /* Determine alias flags */
985 if (dst_addr.s_addr == INADDR_ANY)
986 lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
988 lnk->flags |= LINK_UNKNOWN_DEST_PORT;
990 /* Determine alias port */
991 if (GetNewPort(la, lnk, alias_port_param) != 0) {
995 /* Link-type dependent initialization */
997 struct tcp_dat *aux_tcp;
1000 la->icmpLinkCount++;
1006 aux_tcp = malloc(sizeof(struct tcp_dat));
1007 if (aux_tcp != NULL) {
1011 aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
1012 aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
1013 aux_tcp->state.index = 0;
1014 aux_tcp->state.ack_modified = 0;
1015 for (i = 0; i < N_LINK_TCP_DATA; i++)
1016 aux_tcp->ack[i].active = 0;
1017 aux_tcp->fwhole = -1;
1018 lnk->data.tcp = aux_tcp;
1020 #ifdef LIBALIAS_DEBUG
1021 fprintf(stderr, "PacketAlias/AddLink: ");
1022 fprintf(stderr, " cannot allocate auxiliary TCP data\n");
1029 la->pptpLinkCount++;
1031 case LINK_FRAGMENT_ID:
1032 la->fragmentIdLinkCount++;
1034 case LINK_FRAGMENT_PTR:
1035 la->fragmentPtrLinkCount++;
1040 la->protoLinkCount++;
1044 /* Set up pointers for output lookup table */
1045 start_point = StartPointOut(src_addr, dst_addr,
1046 src_port, dst_port, link_type);
1047 LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out);
1049 /* Set up pointers for input lookup table */
1050 start_point = StartPointIn(alias_addr, lnk->alias_port, link_type);
1051 LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in);
1053 #ifdef LIBALIAS_DEBUG
1054 fprintf(stderr, "PacketAlias/AddLink(): ");
1055 fprintf(stderr, "malloc() call failed.\n");
1058 if (la->packetAliasMode & PKT_ALIAS_LOG) {
1064 static struct alias_link *
1065 ReLink(struct alias_link *old_lnk,
1066 struct in_addr src_addr,
1067 struct in_addr dst_addr,
1068 struct in_addr alias_addr,
1071 int alias_port_param, /* if less than zero, alias */
1073 { /* port will be automatically *//* chosen.
1074 * If greater than */
1075 struct alias_link *new_lnk; /* zero, equal to alias port */
1076 struct libalias *la = old_lnk->la;
1078 LIBALIAS_LOCK_ASSERT(la);
1079 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1080 src_port, dst_port, alias_port_param,
1083 if (new_lnk != NULL &&
1084 old_lnk->link_type == LINK_TCP &&
1085 old_lnk->data.tcp->fwhole > 0) {
1086 PunchFWHole(new_lnk);
1089 DeleteLink(old_lnk);
1093 static struct alias_link *
1094 _FindLinkOut(struct libalias *la, struct in_addr src_addr,
1095 struct in_addr dst_addr,
1099 int replace_partial_links)
1102 struct alias_link *lnk;
1104 LIBALIAS_LOCK_ASSERT(la);
1105 i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
1106 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) {
1107 if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
1108 lnk->src_addr.s_addr == src_addr.s_addr &&
1109 lnk->src_port == src_port &&
1110 lnk->dst_port == dst_port &&
1111 lnk->link_type == link_type &&
1112 lnk->server == NULL) {
1113 lnk->timestamp = la->timeStamp;
1118 /* Search for partially specified links. */
1119 if (lnk == NULL && replace_partial_links) {
1120 if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
1121 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0,
1124 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port,
1125 dst_port, link_type, 0);
1128 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
1129 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0,
1134 src_addr, dst_addr, lnk->alias_addr,
1135 src_port, dst_port, lnk->alias_port,
1142 static struct alias_link *
1143 FindLinkOut(struct libalias *la, struct in_addr src_addr,
1144 struct in_addr dst_addr,
1148 int replace_partial_links)
1150 struct alias_link *lnk;
1152 LIBALIAS_LOCK_ASSERT(la);
1153 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port,
1154 link_type, replace_partial_links);
1158 * The following allows permanent links to be specified as
1159 * using the default source address (i.e. device interface
1160 * address) without knowing in advance what that address
1163 if (la->aliasAddress.s_addr != INADDR_ANY &&
1164 src_addr.s_addr == la->aliasAddress.s_addr) {
1165 lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port,
1166 link_type, replace_partial_links);
1173 static struct alias_link *
1174 _FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1175 struct in_addr alias_addr,
1179 int replace_partial_links)
1183 struct alias_link *lnk;
1184 struct alias_link *lnk_fully_specified;
1185 struct alias_link *lnk_unknown_all;
1186 struct alias_link *lnk_unknown_dst_addr;
1187 struct alias_link *lnk_unknown_dst_port;
1189 LIBALIAS_LOCK_ASSERT(la);
1190 /* Initialize pointers */
1191 lnk_fully_specified = NULL;
1192 lnk_unknown_all = NULL;
1193 lnk_unknown_dst_addr = NULL;
1194 lnk_unknown_dst_port = NULL;
1196 /* If either the dest addr or port is unknown, the search
1197 loop will have to know about this. */
1200 if (dst_addr.s_addr == INADDR_ANY)
1201 flags_in |= LINK_UNKNOWN_DEST_ADDR;
1203 flags_in |= LINK_UNKNOWN_DEST_PORT;
1206 start_point = StartPointIn(alias_addr, alias_port, link_type);
1207 LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) {
1210 flags = flags_in | lnk->flags;
1211 if (!(flags & LINK_PARTIALLY_SPECIFIED)) {
1212 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1213 && lnk->alias_port == alias_port
1214 && lnk->dst_addr.s_addr == dst_addr.s_addr
1215 && lnk->dst_port == dst_port
1216 && lnk->link_type == link_type) {
1217 lnk_fully_specified = lnk;
1220 } else if ((flags & LINK_UNKNOWN_DEST_ADDR)
1221 && (flags & LINK_UNKNOWN_DEST_PORT)) {
1222 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1223 && lnk->alias_port == alias_port
1224 && lnk->link_type == link_type) {
1225 if (lnk_unknown_all == NULL)
1226 lnk_unknown_all = lnk;
1228 } else if (flags & LINK_UNKNOWN_DEST_ADDR) {
1229 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1230 && lnk->alias_port == alias_port
1231 && lnk->link_type == link_type
1232 && lnk->dst_port == dst_port) {
1233 if (lnk_unknown_dst_addr == NULL)
1234 lnk_unknown_dst_addr = lnk;
1236 } else if (flags & LINK_UNKNOWN_DEST_PORT) {
1237 if (lnk->alias_addr.s_addr == alias_addr.s_addr
1238 && lnk->alias_port == alias_port
1239 && lnk->link_type == link_type
1240 && lnk->dst_addr.s_addr == dst_addr.s_addr) {
1241 if (lnk_unknown_dst_port == NULL)
1242 lnk_unknown_dst_port = lnk;
1249 if (lnk_fully_specified != NULL) {
1250 lnk_fully_specified->timestamp = la->timeStamp;
1251 lnk = lnk_fully_specified;
1252 } else if (lnk_unknown_dst_port != NULL)
1253 lnk = lnk_unknown_dst_port;
1254 else if (lnk_unknown_dst_addr != NULL)
1255 lnk = lnk_unknown_dst_addr;
1256 else if (lnk_unknown_all != NULL)
1257 lnk = lnk_unknown_all;
1261 if (replace_partial_links &&
1262 (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) {
1263 struct in_addr src_addr;
1266 if (lnk->server != NULL) { /* LSNAT link */
1267 src_addr = lnk->server->addr;
1268 src_port = lnk->server->port;
1269 lnk->server = lnk->server->next;
1271 src_addr = lnk->src_addr;
1272 src_port = lnk->src_port;
1275 if (link_type == LINK_SCTP) {
1276 lnk->src_addr = src_addr;
1277 lnk->src_port = src_port;
1281 src_addr, dst_addr, alias_addr,
1282 src_port, dst_port, alias_port,
1288 static struct alias_link *
1289 FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1290 struct in_addr alias_addr,
1294 int replace_partial_links)
1296 struct alias_link *lnk;
1298 LIBALIAS_LOCK_ASSERT(la);
1299 lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port,
1300 link_type, replace_partial_links);
1304 * The following allows permanent links to be specified as
1305 * using the default aliasing address (i.e. device
1306 * interface address) without knowing in advance what that
1309 if (la->aliasAddress.s_addr != INADDR_ANY &&
1310 alias_addr.s_addr == la->aliasAddress.s_addr) {
1311 lnk = _FindLinkIn(la, dst_addr, la->nullAddress, dst_port, alias_port,
1312 link_type, replace_partial_links);
1321 /* External routines for finding/adding links
1323 -- "external" means outside alias_db.c, but within alias*.c --
1325 FindIcmpIn(), FindIcmpOut()
1326 FindFragmentIn1(), FindFragmentIn2()
1327 AddFragmentPtrLink(), FindFragmentPtr()
1328 FindProtoIn(), FindProtoOut()
1329 FindUdpTcpIn(), FindUdpTcpOut()
1330 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1331 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1332 FindOriginalAddress(), FindAliasAddress()
1334 (prototypes in alias_local.h)
1339 FindIcmpIn(struct libalias *la, struct in_addr dst_addr,
1340 struct in_addr alias_addr,
1344 struct alias_link *lnk;
1346 LIBALIAS_LOCK_ASSERT(la);
1347 lnk = FindLinkIn(la, dst_addr, alias_addr,
1348 NO_DEST_PORT, id_alias,
1350 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1351 struct in_addr target_addr;
1353 target_addr = FindOriginalAddress(la, alias_addr);
1354 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1355 id_alias, NO_DEST_PORT, id_alias,
1363 FindIcmpOut(struct libalias *la, struct in_addr src_addr,
1364 struct in_addr dst_addr,
1368 struct alias_link *lnk;
1370 LIBALIAS_LOCK_ASSERT(la);
1371 lnk = FindLinkOut(la, src_addr, dst_addr,
1374 if (lnk == NULL && create) {
1375 struct in_addr alias_addr;
1377 alias_addr = FindAliasAddress(la, src_addr);
1378 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1379 id, NO_DEST_PORT, GET_ALIAS_ID,
1387 FindFragmentIn1(struct libalias *la, struct in_addr dst_addr,
1388 struct in_addr alias_addr,
1391 struct alias_link *lnk;
1393 LIBALIAS_LOCK_ASSERT(la);
1394 lnk = FindLinkIn(la, dst_addr, alias_addr,
1395 NO_DEST_PORT, ip_id,
1396 LINK_FRAGMENT_ID, 0);
1399 lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr,
1400 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1408 FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if
1410 struct in_addr alias_addr, /* is not found. */
1414 LIBALIAS_LOCK_ASSERT(la);
1415 return FindLinkIn(la, dst_addr, alias_addr,
1416 NO_DEST_PORT, ip_id,
1417 LINK_FRAGMENT_ID, 0);
1422 AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr,
1426 LIBALIAS_LOCK_ASSERT(la);
1427 return AddLink(la, la->nullAddress, dst_addr, la->nullAddress,
1428 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1434 FindFragmentPtr(struct libalias *la, struct in_addr dst_addr,
1438 LIBALIAS_LOCK_ASSERT(la);
1439 return FindLinkIn(la, dst_addr, la->nullAddress,
1440 NO_DEST_PORT, ip_id,
1441 LINK_FRAGMENT_PTR, 0);
1446 FindProtoIn(struct libalias *la, struct in_addr dst_addr,
1447 struct in_addr alias_addr,
1450 struct alias_link *lnk;
1452 LIBALIAS_LOCK_ASSERT(la);
1453 lnk = FindLinkIn(la, dst_addr, alias_addr,
1457 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1458 struct in_addr target_addr;
1460 target_addr = FindOriginalAddress(la, alias_addr);
1461 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1462 NO_SRC_PORT, NO_DEST_PORT, 0,
1470 FindProtoOut(struct libalias *la, struct in_addr src_addr,
1471 struct in_addr dst_addr,
1474 struct alias_link *lnk;
1476 LIBALIAS_LOCK_ASSERT(la);
1477 lnk = FindLinkOut(la, src_addr, dst_addr,
1478 NO_SRC_PORT, NO_DEST_PORT,
1482 struct in_addr alias_addr;
1484 alias_addr = FindAliasAddress(la, src_addr);
1485 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1486 NO_SRC_PORT, NO_DEST_PORT, 0,
1494 FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr,
1495 struct in_addr alias_addr,
1502 struct alias_link *lnk;
1504 LIBALIAS_LOCK_ASSERT(la);
1507 link_type = LINK_UDP;
1510 link_type = LINK_TCP;
1517 lnk = FindLinkIn(la, dst_addr, alias_addr,
1518 dst_port, alias_port,
1521 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1522 struct in_addr target_addr;
1524 target_addr = FindOriginalAddress(la, alias_addr);
1525 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1526 alias_port, dst_port, alias_port,
1534 FindUdpTcpOut(struct libalias *la, struct in_addr src_addr,
1535 struct in_addr dst_addr,
1542 struct alias_link *lnk;
1544 LIBALIAS_LOCK_ASSERT(la);
1547 link_type = LINK_UDP;
1550 link_type = LINK_TCP;
1557 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create);
1559 if (lnk == NULL && create) {
1560 struct in_addr alias_addr;
1562 alias_addr = FindAliasAddress(la, src_addr);
1563 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1564 src_port, dst_port, GET_ALIAS_PORT,
1572 AddPptp(struct libalias *la, struct in_addr src_addr,
1573 struct in_addr dst_addr,
1574 struct in_addr alias_addr,
1575 u_int16_t src_call_id)
1577 struct alias_link *lnk;
1579 LIBALIAS_LOCK_ASSERT(la);
1580 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1581 src_call_id, 0, GET_ALIAS_PORT,
1589 FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr,
1590 struct in_addr dst_addr,
1591 u_int16_t src_call_id)
1594 struct alias_link *lnk;
1596 LIBALIAS_LOCK_ASSERT(la);
1597 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1598 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1599 if (lnk->link_type == LINK_PPTP &&
1600 lnk->src_addr.s_addr == src_addr.s_addr &&
1601 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1602 lnk->src_port == src_call_id)
1610 FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr,
1611 struct in_addr dst_addr,
1612 u_int16_t dst_call_id)
1615 struct alias_link *lnk;
1617 LIBALIAS_LOCK_ASSERT(la);
1618 i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1619 LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1620 if (lnk->link_type == LINK_PPTP &&
1621 lnk->src_addr.s_addr == src_addr.s_addr &&
1622 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1623 lnk->dst_port == dst_call_id)
1631 FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr,
1632 struct in_addr alias_addr,
1633 u_int16_t dst_call_id)
1636 struct alias_link *lnk;
1638 LIBALIAS_LOCK_ASSERT(la);
1639 i = StartPointIn(alias_addr, 0, LINK_PPTP);
1640 LIST_FOREACH(lnk, &la->linkTableIn[i], list_in)
1641 if (lnk->link_type == LINK_PPTP &&
1642 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1643 lnk->alias_addr.s_addr == alias_addr.s_addr &&
1644 lnk->dst_port == dst_call_id)
1652 FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr,
1653 struct in_addr alias_addr,
1654 u_int16_t alias_call_id)
1656 struct alias_link *lnk;
1658 LIBALIAS_LOCK_ASSERT(la);
1659 lnk = FindLinkIn(la, dst_addr, alias_addr,
1660 0 /* any */ , alias_call_id,
1669 FindRtspOut(struct libalias *la, struct in_addr src_addr,
1670 struct in_addr dst_addr,
1676 struct alias_link *lnk;
1678 LIBALIAS_LOCK_ASSERT(la);
1681 link_type = LINK_UDP;
1684 link_type = LINK_TCP;
1691 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1);
1694 struct in_addr alias_addr;
1696 alias_addr = FindAliasAddress(la, src_addr);
1697 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1698 src_port, 0, alias_port,
1706 FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
1708 struct alias_link *lnk;
1710 LIBALIAS_LOCK_ASSERT(la);
1711 lnk = FindLinkIn(la, la->nullAddress, alias_addr,
1712 0, 0, LINK_ADDR, 0);
1714 la->newDefaultLink = 1;
1715 if (la->targetAddress.s_addr == INADDR_ANY)
1716 return (alias_addr);
1717 else if (la->targetAddress.s_addr == INADDR_NONE)
1718 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1719 la->aliasAddress : alias_addr;
1721 return (la->targetAddress);
1723 if (lnk->server != NULL) { /* LSNAT link */
1724 struct in_addr src_addr;
1726 src_addr = lnk->server->addr;
1727 lnk->server = lnk->server->next;
1729 } else if (lnk->src_addr.s_addr == INADDR_ANY)
1730 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1731 la->aliasAddress : alias_addr;
1733 return (lnk->src_addr);
1739 FindAliasAddress(struct libalias *la, struct in_addr original_addr)
1741 struct alias_link *lnk;
1743 LIBALIAS_LOCK_ASSERT(la);
1744 lnk = FindLinkOut(la, original_addr, la->nullAddress,
1745 0, 0, LINK_ADDR, 0);
1747 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1748 la->aliasAddress : original_addr;
1750 if (lnk->alias_addr.s_addr == INADDR_ANY)
1751 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1752 la->aliasAddress : original_addr;
1754 return (lnk->alias_addr);
1759 /* External routines for getting or changing link data
1760 (external to alias_db.c, but internal to alias*.c)
1762 SetFragmentData(), GetFragmentData()
1763 SetFragmentPtr(), GetFragmentPtr()
1764 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1765 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1766 GetOriginalPort(), GetAliasPort()
1767 SetAckModified(), GetAckModified()
1768 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1769 SetProtocolFlags(), GetProtocolFlags()
1775 SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
1777 lnk->data.frag_addr = src_addr;
1782 GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
1784 *src_addr = lnk->data.frag_addr;
1789 SetFragmentPtr(struct alias_link *lnk, char *fptr)
1791 lnk->data.frag_ptr = fptr;
1796 GetFragmentPtr(struct alias_link *lnk, char **fptr)
1798 *fptr = lnk->data.frag_ptr;
1803 SetStateIn(struct alias_link *lnk, int state)
1805 /* TCP input state */
1807 case ALIAS_TCP_STATE_DISCONNECTED:
1808 if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED)
1809 lnk->expire_time = TCP_EXPIRE_DEAD;
1811 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1813 case ALIAS_TCP_STATE_CONNECTED:
1814 if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED)
1815 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1819 panic("libalias:SetStateIn() unknown state");
1824 lnk->data.tcp->state.in = state;
1829 SetStateOut(struct alias_link *lnk, int state)
1831 /* TCP output state */
1833 case ALIAS_TCP_STATE_DISCONNECTED:
1834 if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED)
1835 lnk->expire_time = TCP_EXPIRE_DEAD;
1837 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1839 case ALIAS_TCP_STATE_CONNECTED:
1840 if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED)
1841 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1845 panic("libalias:SetStateOut() unknown state");
1850 lnk->data.tcp->state.out = state;
1855 GetStateIn(struct alias_link *lnk)
1857 /* TCP input state */
1858 return (lnk->data.tcp->state.in);
1863 GetStateOut(struct alias_link *lnk)
1865 /* TCP output state */
1866 return (lnk->data.tcp->state.out);
1871 GetOriginalAddress(struct alias_link *lnk)
1873 if (lnk->src_addr.s_addr == INADDR_ANY)
1874 return (lnk->la->aliasAddress);
1876 return (lnk->src_addr);
1881 GetDestAddress(struct alias_link *lnk)
1883 return (lnk->dst_addr);
1888 GetAliasAddress(struct alias_link *lnk)
1890 if (lnk->alias_addr.s_addr == INADDR_ANY)
1891 return (lnk->la->aliasAddress);
1893 return (lnk->alias_addr);
1898 GetDefaultAliasAddress(struct libalias *la)
1901 LIBALIAS_LOCK_ASSERT(la);
1902 return (la->aliasAddress);
1907 SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
1910 LIBALIAS_LOCK_ASSERT(la);
1911 la->aliasAddress = alias_addr;
1916 GetOriginalPort(struct alias_link *lnk)
1918 return (lnk->src_port);
1923 GetAliasPort(struct alias_link *lnk)
1925 return (lnk->alias_port);
1930 GetDestPort(struct alias_link *lnk)
1932 return (lnk->dst_port);
1938 SetAckModified(struct alias_link *lnk)
1940 /* Indicate that ACK numbers have been modified in a TCP connection */
1941 lnk->data.tcp->state.ack_modified = 1;
1946 GetProxyAddress(struct alias_link *lnk)
1948 return (lnk->proxy_addr);
1953 SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
1955 lnk->proxy_addr = addr;
1960 GetProxyPort(struct alias_link *lnk)
1962 return (lnk->proxy_port);
1967 SetProxyPort(struct alias_link *lnk, u_short port)
1969 lnk->proxy_port = port;
1974 GetAckModified(struct alias_link *lnk)
1976 /* See if ACK numbers have been modified */
1977 return (lnk->data.tcp->state.ack_modified);
1982 GetDeltaAckIn(u_long ack, struct alias_link *lnk)
1985 Find out how much the ACK number has been altered for an incoming
1986 TCP packet. To do this, a circular list of ACK numbers where the TCP
1987 packet size was altered is searched.
1991 int delta, ack_diff_min;
1995 for (i = 0; i < N_LINK_TCP_DATA; i++) {
1996 struct ack_data_record x;
1998 x = lnk->data.tcp->ack[i];
1999 if (x.active == 1) {
2002 ack_diff = SeqDiff(x.ack_new, ack);
2003 if (ack_diff >= 0) {
2004 if (ack_diff_min >= 0) {
2005 if (ack_diff < ack_diff_min) {
2007 ack_diff_min = ack_diff;
2011 ack_diff_min = ack_diff;
2021 GetDeltaSeqOut(u_long seq, struct alias_link *lnk)
2024 Find out how much the sequence number has been altered for an outgoing
2025 TCP packet. To do this, a circular list of ACK numbers where the TCP
2026 packet size was altered is searched.
2030 int delta, seq_diff_min;
2034 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2035 struct ack_data_record x;
2037 x = lnk->data.tcp->ack[i];
2038 if (x.active == 1) {
2041 seq_diff = SeqDiff(x.ack_old, seq);
2042 if (seq_diff >= 0) {
2043 if (seq_diff_min >= 0) {
2044 if (seq_diff < seq_diff_min) {
2046 seq_diff_min = seq_diff;
2050 seq_diff_min = seq_diff;
2060 AddSeq(struct alias_link *lnk, int delta, u_int ip_hl, u_short ip_len,
2061 u_long th_seq, u_int th_off)
2064 When a TCP packet has been altered in length, save this
2065 information in a circular list. If enough packets have
2066 been altered, then this list will begin to overwrite itself.
2069 struct ack_data_record x;
2070 int hlen, tlen, dlen;
2073 hlen = (ip_hl + th_off) << 2;
2074 tlen = ntohs(ip_len);
2077 x.ack_old = htonl(ntohl(th_seq) + dlen);
2078 x.ack_new = htonl(ntohl(th_seq) + dlen + delta);
2082 i = lnk->data.tcp->state.index;
2083 lnk->data.tcp->ack[i] = x;
2086 if (i == N_LINK_TCP_DATA)
2087 lnk->data.tcp->state.index = 0;
2089 lnk->data.tcp->state.index = i;
2093 SetExpire(struct alias_link *lnk, int expire)
2096 lnk->flags &= ~LINK_PERMANENT;
2098 } else if (expire == -1) {
2099 lnk->flags |= LINK_PERMANENT;
2100 } else if (expire > 0) {
2101 lnk->expire_time = expire;
2103 #ifdef LIBALIAS_DEBUG
2104 fprintf(stderr, "PacketAlias/SetExpire(): ");
2105 fprintf(stderr, "error in expire parameter\n");
2111 ClearCheckNewLink(struct libalias *la)
2114 LIBALIAS_LOCK_ASSERT(la);
2115 la->newDefaultLink = 0;
2119 SetProtocolFlags(struct alias_link *lnk, int pflags)
2122 lnk->pflags = pflags;
2126 GetProtocolFlags(struct alias_link *lnk)
2129 return (lnk->pflags);
2133 SetDestCallId(struct alias_link *lnk, u_int16_t cid)
2135 struct libalias *la = lnk->la;
2137 LIBALIAS_LOCK_ASSERT(la);
2138 la->deleteAllLinks = 1;
2139 ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr,
2140 lnk->src_port, cid, lnk->alias_port, lnk->link_type);
2141 la->deleteAllLinks = 0;
2145 /* Miscellaneous Functions
2148 InitPacketAliasLog()
2149 UninitPacketAliasLog()
2153 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2154 is called to find and remove timed-out aliasing links. Logic exists
2155 to sweep through the entire table and linked list structure
2158 (prototype in alias_local.h)
2162 HouseKeeping(struct libalias *la)
2169 LIBALIAS_LOCK_ASSERT(la);
2171 * Save system time (seconds) in global variable timeStamp for use
2172 * by other functions. This is done so as not to unnecessarily
2173 * waste timeline by making system calls.
2176 la->timeStamp = time_uptime;
2178 gettimeofday(&tv, NULL);
2179 la->timeStamp = tv.tv_sec;
2182 /* Compute number of spokes (output table link chains) to cover */
2183 n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime);
2184 n /= ALIAS_CLEANUP_INTERVAL_SECS;
2186 /* Handle different cases */
2188 if (n > ALIAS_CLEANUP_MAX_SPOKES)
2189 n = ALIAS_CLEANUP_MAX_SPOKES;
2190 la->lastCleanupTime = la->timeStamp;
2191 for (i = 0; i < n; i++)
2192 IncrementalCleanup(la);
2194 #ifdef LIBALIAS_DEBUG
2195 fprintf(stderr, "PacketAlias/HouseKeeping(): ");
2196 fprintf(stderr, "something unexpected in time values\n");
2198 la->lastCleanupTime = la->timeStamp;
2202 /* Init the log file and enable logging */
2204 InitPacketAliasLog(struct libalias *la)
2207 LIBALIAS_LOCK_ASSERT(la);
2208 if (~la->packetAliasMode & PKT_ALIAS_LOG) {
2210 if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
2213 if ((la->logDesc = fopen("/var/log/alias.log", "w")))
2214 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2217 return (ENOMEM); /* log initialization failed */
2218 la->packetAliasMode |= PKT_ALIAS_LOG;
2224 /* Close the log-file and disable logging. */
2226 UninitPacketAliasLog(struct libalias *la)
2229 LIBALIAS_LOCK_ASSERT(la);
2234 fclose(la->logDesc);
2238 la->packetAliasMode &= ~PKT_ALIAS_LOG;
2241 /* Outside world interfaces
2243 -- "outside world" means other than alias*.c routines --
2245 PacketAliasRedirectPort()
2246 PacketAliasAddServer()
2247 PacketAliasRedirectProto()
2248 PacketAliasRedirectAddr()
2249 PacketAliasRedirectDynamic()
2250 PacketAliasRedirectDelete()
2251 PacketAliasSetAddress()
2254 PacketAliasSetMode()
2256 (prototypes in alias.h)
2259 /* Redirection from a specific public addr:port to a
2260 private addr:port */
2262 LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port,
2263 struct in_addr dst_addr, u_short dst_port,
2264 struct in_addr alias_addr, u_short alias_port,
2268 struct alias_link *lnk;
2273 link_type = LINK_UDP;
2276 link_type = LINK_TCP;
2279 link_type = LINK_SCTP;
2282 #ifdef LIBALIAS_DEBUG
2283 fprintf(stderr, "PacketAliasRedirectPort(): ");
2284 fprintf(stderr, "only SCTP, TCP and UDP protocols allowed\n");
2290 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2291 src_port, dst_port, alias_port,
2295 lnk->flags |= LINK_PERMANENT;
2297 #ifdef LIBALIAS_DEBUG
2299 fprintf(stderr, "PacketAliasRedirectPort(): "
2300 "call to AddLink() failed\n");
2305 LIBALIAS_UNLOCK(la);
2309 /* Add server to the pool of servers */
2311 LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
2313 struct server *server;
2319 server = malloc(sizeof(struct server));
2321 if (server != NULL) {
2322 struct server *head;
2324 server->addr = addr;
2325 server->port = port;
2329 server->next = server;
2333 for (s = head; s->next != head; s = s->next);
2335 server->next = head;
2337 lnk->server = server;
2342 LIBALIAS_UNLOCK(la);
2346 /* Redirect packets of a given IP protocol from a specific
2347 public address to a private address */
2349 LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr,
2350 struct in_addr dst_addr,
2351 struct in_addr alias_addr,
2354 struct alias_link *lnk;
2357 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2358 NO_SRC_PORT, NO_DEST_PORT, 0,
2362 lnk->flags |= LINK_PERMANENT;
2364 #ifdef LIBALIAS_DEBUG
2366 fprintf(stderr, "PacketAliasRedirectProto(): "
2367 "call to AddLink() failed\n");
2371 LIBALIAS_UNLOCK(la);
2375 /* Static address translation */
2377 LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr,
2378 struct in_addr alias_addr)
2380 struct alias_link *lnk;
2383 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
2388 lnk->flags |= LINK_PERMANENT;
2390 #ifdef LIBALIAS_DEBUG
2392 fprintf(stderr, "PacketAliasRedirectAddr(): "
2393 "call to AddLink() failed\n");
2397 LIBALIAS_UNLOCK(la);
2402 /* Mark the aliasing link dynamic */
2404 LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
2411 if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
2414 lnk->flags &= ~LINK_PERMANENT;
2417 LIBALIAS_UNLOCK(la);
2423 LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
2425 /* This is a dangerous function to put in the API,
2426 because an invalid pointer can crash the program. */
2429 la->deleteAllLinks = 1;
2431 la->deleteAllLinks = 0;
2432 LIBALIAS_UNLOCK(la);
2437 LibAliasSetAddress(struct libalias *la, struct in_addr addr)
2441 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2442 && la->aliasAddress.s_addr != addr.s_addr)
2443 CleanupAliasData(la);
2445 la->aliasAddress = addr;
2446 LIBALIAS_UNLOCK(la);
2451 LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2455 la->targetAddress = target_addr;
2456 LIBALIAS_UNLOCK(la);
2463 while (!LIST_EMPTY(&instancehead))
2464 LibAliasUninit(LIST_FIRST(&instancehead));
2468 LibAliasInit(struct libalias *la)
2477 #undef malloc /* XXX: ugly */
2478 la = malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO);
2480 la = calloc(sizeof *la, 1);
2485 #ifndef _KERNEL /* kernel cleans up on module unload */
2486 if (LIST_EMPTY(&instancehead))
2489 LIST_INSERT_HEAD(&instancehead, la, instancelist);
2492 la->timeStamp = time_uptime;
2493 la->lastCleanupTime = time_uptime;
2495 gettimeofday(&tv, NULL);
2496 la->timeStamp = tv.tv_sec;
2497 la->lastCleanupTime = tv.tv_sec;
2500 for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
2501 LIST_INIT(&la->linkTableOut[i]);
2502 for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
2503 LIST_INIT(&la->linkTableIn[i]);
2507 LIBALIAS_LOCK_INIT(la);
2511 la->deleteAllLinks = 1;
2512 CleanupAliasData(la);
2513 la->deleteAllLinks = 0;
2520 la->aliasAddress.s_addr = INADDR_ANY;
2521 la->targetAddress.s_addr = INADDR_ANY;
2523 la->icmpLinkCount = 0;
2524 la->udpLinkCount = 0;
2525 la->tcpLinkCount = 0;
2526 la->sctpLinkCount = 0;
2527 la->pptpLinkCount = 0;
2528 la->protoLinkCount = 0;
2529 la->fragmentIdLinkCount = 0;
2530 la->fragmentPtrLinkCount = 0;
2533 la->cleanupIndex = 0;
2535 la->packetAliasMode = PKT_ALIAS_SAME_PORTS
2536 #ifndef NO_USE_SOCKETS
2537 | PKT_ALIAS_USE_SOCKETS
2539 | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2541 la->fireWallFD = -1;
2544 LibAliasRefreshModules();
2546 LIBALIAS_UNLOCK(la);
2551 LibAliasUninit(struct libalias *la)
2558 la->deleteAllLinks = 1;
2559 CleanupAliasData(la);
2560 la->deleteAllLinks = 0;
2561 UninitPacketAliasLog(la);
2565 LIST_REMOVE(la, instancelist);
2566 LIBALIAS_UNLOCK(la);
2567 LIBALIAS_LOCK_DESTROY(la);
2571 /* Change mode for some operations */
2574 struct libalias *la,
2575 unsigned int flags, /* Which state to bring flags to */
2576 unsigned int mask /* Mask of which flags to affect (use 0 to
2577 * do a probe for flag values) */
2583 /* Enable logging? */
2584 if (flags & mask & PKT_ALIAS_LOG) {
2586 if (InitPacketAliasLog(la) == ENOMEM)
2589 /* _Disable_ logging? */
2590 if (~flags & mask & PKT_ALIAS_LOG) {
2591 UninitPacketAliasLog(la);
2594 /* Start punching holes in the firewall? */
2595 if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2598 /* Stop punching holes in the firewall? */
2599 if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2604 /* Other flags can be set/cleared without special action */
2605 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2606 res = la->packetAliasMode;
2608 LIBALIAS_UNLOCK(la);
2614 LibAliasCheckNewLink(struct libalias *la)
2619 res = la->newDefaultLink;
2620 LIBALIAS_UNLOCK(la);
2628 Code to support firewall punching. This shouldn't really be in this
2629 file, but making variables global is evil too.
2632 /* Firewall include files */
2634 #include <netinet/ip_fw.h>
2639 * helper function, updates the pointer to cmd with the length
2640 * of the current command, and also cleans up the first word of
2641 * the new command in case it has been clobbered before.
2644 next_cmd(ipfw_insn * cmd)
2647 bzero(cmd, sizeof(*cmd));
2652 * A function to fill simple commands of size 1.
2653 * Existing flags are preserved.
2656 fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2657 int flags, u_int16_t arg)
2659 cmd->opcode = opcode;
2660 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2662 return next_cmd(cmd);
2666 fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2668 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1;
2670 cmd->addr.s_addr = addr;
2671 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2675 fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2677 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1;
2679 cmd->ports[0] = cmd->ports[1] = port;
2680 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2684 fill_rule(void *buf, int bufsize, int rulenum,
2685 enum ipfw_opcodes action, int proto,
2686 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
2688 struct ip_fw *rule = (struct ip_fw *)buf;
2689 ipfw_insn *cmd = (ipfw_insn *) rule->cmd;
2691 bzero(buf, bufsize);
2692 rule->rulenum = rulenum;
2694 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto);
2695 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr);
2696 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp);
2697 cmd = fill_ip(cmd, O_IP_DST, da.s_addr);
2698 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
2700 rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2701 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
2703 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2705 return ((char *)cmd - (char *)buf);
2708 static void ClearAllFWHoles(struct libalias *la);
2711 #define fw_setfield(la, field, num) \
2713 (field)[(num) - la->fireWallBaseNum] = 1; \
2714 } /*lint -save -e717 */ while(0)/* lint -restore */
2716 #define fw_clrfield(la, field, num) \
2718 (field)[(num) - la->fireWallBaseNum] = 0; \
2719 } /*lint -save -e717 */ while(0)/* lint -restore */
2721 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2724 InitPunchFW(struct libalias *la)
2727 la->fireWallField = malloc(la->fireWallNumNums);
2728 if (la->fireWallField) {
2729 memset(la->fireWallField, 0, la->fireWallNumNums);
2730 if (la->fireWallFD < 0) {
2731 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2733 ClearAllFWHoles(la);
2734 la->fireWallActiveNum = la->fireWallBaseNum;
2739 UninitPunchFW(struct libalias *la)
2742 ClearAllFWHoles(la);
2743 if (la->fireWallFD >= 0)
2744 close(la->fireWallFD);
2745 la->fireWallFD = -1;
2746 if (la->fireWallField)
2747 free(la->fireWallField);
2748 la->fireWallField = NULL;
2749 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2752 /* Make a certain link go through the firewall */
2754 PunchFWHole(struct alias_link *lnk)
2756 struct libalias *la;
2757 int r; /* Result code */
2758 struct ip_fw rule; /* On-the-fly built rule */
2759 int fwhole; /* Where to punch hole */
2763 /* Don't do anything unless we are asked to */
2764 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2765 la->fireWallFD < 0 ||
2766 lnk->link_type != LINK_TCP)
2769 memset(&rule, 0, sizeof rule);
2773 /* Find empty slot */
2774 for (fwhole = la->fireWallActiveNum;
2775 fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2776 fw_tstfield(la, la->fireWallField, fwhole);
2778 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2779 for (fwhole = la->fireWallBaseNum;
2780 fwhole < la->fireWallActiveNum &&
2781 fw_tstfield(la, la->fireWallField, fwhole);
2783 if (fwhole == la->fireWallActiveNum) {
2784 /* No rule point empty - we can't punch more holes. */
2785 la->fireWallActiveNum = la->fireWallBaseNum;
2786 #ifdef LIBALIAS_DEBUG
2787 fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2792 /* Start next search at next position */
2793 la->fireWallActiveNum = fwhole + 1;
2796 * generate two rules of the form
2798 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2799 * accept tcp from DAddr DPort to OAddr OPort
2801 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2802 u_int32_t rulebuf[255];
2805 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2806 O_ACCEPT, IPPROTO_TCP,
2807 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
2808 GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
2809 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2811 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2813 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2814 O_ACCEPT, IPPROTO_TCP,
2815 GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
2816 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
2817 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2819 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2822 /* Indicate hole applied */
2823 lnk->data.tcp->fwhole = fwhole;
2824 fw_setfield(la, la->fireWallField, fwhole);
2827 /* Remove a hole in a firewall associated with a particular alias
2828 lnk. Calling this too often is harmless. */
2830 ClearFWHole(struct alias_link *lnk)
2832 struct libalias *la;
2835 if (lnk->link_type == LINK_TCP) {
2836 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall
2843 memset(&rule, 0, sizeof rule); /* useless for ipfw2 */
2844 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL,
2845 &fwhole, sizeof fwhole));
2846 fw_clrfield(la, la->fireWallField, fwhole);
2847 lnk->data.tcp->fwhole = -1;
2851 /* Clear out the entire range dedicated to firewall holes. */
2853 ClearAllFWHoles(struct libalias *la)
2855 struct ip_fw rule; /* On-the-fly built rule */
2858 if (la->fireWallFD < 0)
2861 memset(&rule, 0, sizeof rule);
2862 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2865 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2867 /* XXX: third arg correct here ? /phk */
2868 memset(la->fireWallField, 0, la->fireWallNumNums);
2871 #endif /* !NO_FW_PUNCH */
2874 LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2879 la->fireWallBaseNum = base;
2880 la->fireWallNumNums = num;
2882 LIBALIAS_UNLOCK(la);
2886 LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2890 la->skinnyPort = port;
2891 LIBALIAS_UNLOCK(la);
2895 * Find the address to redirect incoming packets
2898 FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm)
2900 struct alias_link *lnk;
2901 struct in_addr redir;
2903 LIBALIAS_LOCK_ASSERT(la);
2904 lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst,
2905 sm->sctp_hdr->dest_port,sm->sctp_hdr->dest_port, LINK_SCTP, 1);
2907 return(lnk->src_addr); /* port redirect */
2909 redir = FindOriginalAddress(la,sm->ip_hdr->ip_dst);
2910 if (redir.s_addr == la->aliasAddress.s_addr ||
2911 redir.s_addr == la->targetAddress.s_addr) { /* No address found */
2912 lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst,
2913 NO_DEST_PORT, 0, LINK_SCTP, 1);
2915 return(lnk->src_addr); /* redirect proto */
2917 return(redir); /* address redirect */