2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: src/sys/netinet/libalias/alias_db.c,v 1.71.2.2.2.1 2008/11/25 02:59:29 kensmith Exp $");
31 Alias_db.c encapsulates all data structures used for storing
32 packet aliasing data. Other parts of the aliasing software
33 access data through functions provided in this file.
35 Data storage is based on the notion of a "link", which is
36 established for ICMP echo/reply packets, UDP datagrams and
37 TCP stream connections. A link stores the original source
38 and destination addresses. For UDP and TCP, it also stores
39 source and destination port numbers, as well as an alias
40 port number. Links are also used to store information about
43 There is a facility for sweeping through and deleting old
44 links as new packets are sent through. A simple timeout is
45 used for ICMP and UDP links. TCP links are left alone unless
46 there is an incomplete connection, in which case the link
47 can be deleted after a certain amount of time.
50 Initial version: August, 1996 (cjm)
52 Version 1.4: September 16, 1996 (cjm)
53 Facility for handling incoming links added.
55 Version 1.6: September 18, 1996 (cjm)
56 ICMP data handling simplified.
58 Version 1.7: January 9, 1997 (cjm)
59 Fragment handling simplified.
60 Saves pointers for unresolved fragments.
61 Permits links for unspecified remote ports
62 or unspecified remote addresses.
63 Fixed bug which did not properly zero port
64 table entries after a link was deleted.
65 Cleaned up some obsolete comments.
67 Version 1.8: January 14, 1997 (cjm)
68 Fixed data type error in StartPoint().
69 (This error did not exist prior to v1.7
70 and was discovered and fixed by Ari Suutari)
72 Version 1.9: February 1, 1997
73 Optionally, connections initiated from packet aliasing host
74 machine will will not have their port number aliased unless it
75 conflicts with an aliasing port already being used. (cjm)
77 All options earlier being #ifdef'ed are now available through
78 a new interface, SetPacketAliasMode(). This allows run time
79 control (which is now available in PPP+pktAlias through the
80 'alias' keyword). (ee)
82 Added ability to create an alias port without
83 either destination address or port specified.
84 port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
86 Removed K&R style function headers
87 and general cleanup. (ee)
89 Added packetAliasMode to replace compiler #defines's (ee)
91 Allocates sockets for partially specified
92 ports if ALIAS_USE_SOCKETS defined. (cjm)
94 Version 2.0: March, 1997
95 SetAliasAddress() will now clean up alias links
96 if the aliasing address is changed. (cjm)
98 PacketAliasPermanentLink() function added to support permanent
99 links. (J. Fortes suggested the need for this.)
102 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
104 (192.168.0.2, port 21) <-> alias port 3604, known dest addr
107 These permanent links allow for incoming connections to
108 machines on the local network. They can be given with a
109 user-chosen amount of specificity, with increasing specificity
110 meaning more security. (cjm)
112 Quite a bit of rework to the basic engine. The portTable[]
113 array, which kept track of which ports were in use was replaced
114 by a table/linked list structure. (cjm)
116 SetExpire() function added. (cjm)
118 DeleteLink() no longer frees memory association with a pointer
119 to a fragment (this bug was first recognized by E. Eklund in
122 Version 2.1: May, 1997 (cjm)
123 Packet aliasing engine reworked so that it can handle
124 multiple external addresses rather than just a single
127 PacketAliasRedirectPort() and PacketAliasRedirectAddr()
128 added to the API. The first function is a more generalized
129 version of PacketAliasPermanentLink(). The second function
130 implements static network address translation.
132 Version 3.2: July, 2000 (salander and satoh)
133 Added FindNewPortGroup to get contiguous range of port values.
135 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
136 link but not actually add one.
138 Added FindRtspOut, which is closely derived from FindUdpTcpOut,
139 except that the alias port (from FindNewPortGroup) is provided
142 See HISTORY file for additional revisions.
144 #include <sys/param.h>
145 #include <sys/kernel.h>
146 #include <sys/module.h>
147 #include <sys/syslog.h>
148 #include <sys/queue.h>
150 #include <sys/socket.h>
151 #include <netinet/tcp.h>
154 #include "alias_local.h"
155 #include "alias_mod.h"
158 static LIST_HEAD(, libalias
) instancehead
= LIST_HEAD_INITIALIZER(instancehead
);
162 Constants (note: constants are also defined
163 near relevant functions or structs)
166 /* Parameters used for cleanup of expired links */
167 /* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */
168 #define ALIAS_CLEANUP_INTERVAL_SECS 64
169 #define ALIAS_CLEANUP_MAX_SPOKES (LINK_TABLE_OUT_SIZE/5)
171 /* Timeouts (in seconds) for different link types */
172 #define ICMP_EXPIRE_TIME 60
173 #define UDP_EXPIRE_TIME 60
174 #define PROTO_EXPIRE_TIME 60
175 #define FRAGMENT_ID_EXPIRE_TIME 10
176 #define FRAGMENT_PTR_EXPIRE_TIME 30
178 /* TCP link expire time for different cases */
179 /* When the link has been used and closed - minimal grace time to
180 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
181 #ifndef TCP_EXPIRE_DEAD
182 #define TCP_EXPIRE_DEAD 10
185 /* When the link has been used and closed on one side - the other side
186 is allowed to still send data */
187 #ifndef TCP_EXPIRE_SINGLEDEAD
188 #define TCP_EXPIRE_SINGLEDEAD 90
191 /* When the link isn't yet up */
192 #ifndef TCP_EXPIRE_INITIAL
193 #define TCP_EXPIRE_INITIAL 300
196 /* When the link is up */
197 #ifndef TCP_EXPIRE_CONNECTED
198 #define TCP_EXPIRE_CONNECTED 86400
202 /* Dummy port number codes used for FindLinkIn/Out() and AddLink().
203 These constants can be anything except zero, which indicates an
204 unknown port number. */
206 #define NO_DEST_PORT 1
207 #define NO_SRC_PORT 1
209 /* Clean up procedure. */
210 static void finishoff(void);
212 /* Kernel module definition. */
214 MALLOC_DEFINE(M_ALIAS
, "libalias", "packet aliasing");
216 MODULE_VERSION(libalias
, 1);
219 alias_mod_handler(module_t mod
, int type
, void *data
)
226 handler_chain_init();
229 handler_chain_destroy();
240 static moduledata_t alias_mod
= {
241 "alias", alias_mod_handler
, NULL
244 DECLARE_MODULE(alias
, alias_mod
, SI_SUB_DRIVERS
, SI_ORDER_SECOND
);
247 /* Internal utility routines (used only in alias_db.c)
249 Lookup table starting points:
250 StartPointIn() -- link table initial search point for
252 StartPointOut() -- link table initial search point for
256 SeqDiff() -- difference between two TCP sequences
257 ShowAliasStats() -- send alias statistics to a monitor file
261 /* Local prototypes */
262 static u_int
StartPointIn(struct in_addr
, u_short
, int);
265 StartPointOut(struct in_addr
, struct in_addr
,
266 u_short
, u_short
, int);
268 static int SeqDiff(u_long
, u_long
);
271 /* Firewall control */
272 static void InitPunchFW(struct libalias
*);
273 static void UninitPunchFW(struct libalias
*);
274 static void ClearFWHole(struct alias_link
*);
278 /* Log file control */
279 static void ShowAliasStats(struct libalias
*);
280 static int InitPacketAliasLog(struct libalias
*);
281 static void UninitPacketAliasLog(struct libalias
*);
284 StartPointIn(struct in_addr alias_addr
,
290 n
= alias_addr
.s_addr
;
291 if (link_type
!= LINK_PPTP
)
294 return (n
% LINK_TABLE_IN_SIZE
);
299 StartPointOut(struct in_addr src_addr
, struct in_addr dst_addr
,
300 u_short src_port
, u_short dst_port
, int link_type
)
305 n
+= dst_addr
.s_addr
;
306 if (link_type
!= LINK_PPTP
) {
312 return (n
% LINK_TABLE_OUT_SIZE
);
317 SeqDiff(u_long x
, u_long y
)
319 /* Return the difference between two TCP sequence numbers */
322 This function is encapsulated in case there are any unusual
323 arithmetic conditions that need to be considered.
326 return (ntohl(y
) - ntohl(x
));
332 AliasLog(char *str
, const char *format
, ...)
336 __va_start(ap
, format
);
337 kvsnprintf(str
, LIBALIAS_BUF_SIZE
, format
, ap
);
342 AliasLog(FILE *stream
, const char *format
, ...)
346 va_start(ap
, format
);
347 vfprintf(stream
, format
, ap
);
354 ShowAliasStats(struct libalias
*la
)
357 LIBALIAS_LOCK_ASSERT(la
);
358 /* Used for debugging */
360 int tot
= la
->icmpLinkCount
+ la
->udpLinkCount
+
361 la
->tcpLinkCount
+ la
->pptpLinkCount
+
362 la
->protoLinkCount
+ la
->fragmentIdLinkCount
+
363 la
->fragmentPtrLinkCount
;
365 AliasLog(la
->logDesc
,
366 "icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
372 la
->fragmentIdLinkCount
,
373 la
->fragmentPtrLinkCount
, tot
);
375 AliasLog(la
->logDesc
, " (sock=%u)\n", la
->sockCount
);
380 /* Internal routines for finding, deleting and adding links
383 GetNewPort() -- find and reserve new alias port number
384 GetSocket() -- try to allocate a socket for a given port
386 Link creation and deletion:
387 CleanupAliasData() - remove all link chains from lookup table
388 IncrementalCleanup() - look for stale links in a single chain
389 DeleteLink() - remove link
391 ReLink() - change link
394 FindLinkOut() - find link for outgoing packets
395 FindLinkIn() - find link for incoming packets
398 FindNewPortGroup() - find an available group of ports
401 /* Local prototypes */
402 static int GetNewPort(struct libalias
*, struct alias_link
*, int);
403 #ifndef NO_USE_SOCKETS
404 static u_short
GetSocket(struct libalias
*, u_short
, int *, int);
406 static void CleanupAliasData(struct libalias
*);
408 static void IncrementalCleanup(struct libalias
*);
410 static void DeleteLink(struct alias_link
*);
412 static struct alias_link
*
413 AddLink(struct libalias
*, struct in_addr
, struct in_addr
, struct in_addr
,
414 u_short
, u_short
, int, int);
416 static struct alias_link
*
417 ReLink(struct alias_link
*,
418 struct in_addr
, struct in_addr
, struct in_addr
,
419 u_short
, u_short
, int, int);
421 static struct alias_link
*
422 FindLinkOut (struct libalias
*, struct in_addr
, struct in_addr
, u_short
, u_short
, int, int);
424 static struct alias_link
*
425 FindLinkIn (struct libalias
*, struct in_addr
, struct in_addr
, u_short
, u_short
, int, int);
428 #define ALIAS_PORT_BASE 0x08000
429 #define ALIAS_PORT_MASK 0x07fff
430 #define ALIAS_PORT_MASK_EVEN 0x07ffe
431 #define GET_NEW_PORT_MAX_ATTEMPTS 20
433 #define GET_ALIAS_PORT -1
434 #define GET_ALIAS_ID GET_ALIAS_PORT
436 #define FIND_EVEN_ALIAS_BASE 1
438 /* GetNewPort() allocates port numbers. Note that if a port number
439 is already in use, that does not mean that it cannot be used by
440 another link concurrently. This is because GetNewPort() looks for
441 unused triplets: (dest addr, dest port, alias port). */
444 GetNewPort(struct libalias
*la
, struct alias_link
*lnk
, int alias_port_param
)
451 LIBALIAS_LOCK_ASSERT(la
);
453 Description of alias_port_param for GetNewPort(). When
454 this parameter is zero or positive, it precisely specifies
455 the port number. GetNewPort() will return this number
456 without check that it is in use.
458 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
459 selected port number.
462 if (alias_port_param
== GET_ALIAS_PORT
) {
464 * The aliasing port is automatically selected by one of
467 max_trials
= GET_NEW_PORT_MAX_ATTEMPTS
;
469 if (la
->packetAliasMode
& PKT_ALIAS_SAME_PORTS
) {
471 * When the PKT_ALIAS_SAME_PORTS option is chosen,
472 * the first try will be the actual source port. If
473 * this is already in use, the remainder of the
474 * trials will be random.
476 port_net
= lnk
->src_port
;
477 port_sys
= ntohs(port_net
);
479 /* First trial and all subsequent are random. */
480 port_sys
= krandom() & ALIAS_PORT_MASK
;
481 port_sys
+= ALIAS_PORT_BASE
;
482 port_net
= htons(port_sys
);
484 } else if (alias_port_param
>= 0 && alias_port_param
< 0x10000) {
485 lnk
->alias_port
= (u_short
) alias_port_param
;
488 #ifdef LIBALIAS_DEBUG
489 fprintf(stderr
, "PacketAlias/GetNewPort(): ");
490 fprintf(stderr
, "input parameter error\n");
496 /* Port number search */
497 for (i
= 0; i
< max_trials
; i
++) {
499 struct alias_link
*search_result
;
501 search_result
= FindLinkIn(la
, lnk
->dst_addr
, lnk
->alias_addr
,
502 lnk
->dst_port
, port_net
,
505 if (search_result
== NULL
)
507 else if (!(lnk
->flags
& LINK_PARTIALLY_SPECIFIED
)
508 && (search_result
->flags
& LINK_PARTIALLY_SPECIFIED
))
514 #ifndef NO_USE_SOCKETS
515 if ((la
->packetAliasMode
& PKT_ALIAS_USE_SOCKETS
)
516 && (lnk
->flags
& LINK_PARTIALLY_SPECIFIED
)
517 && ((lnk
->link_type
== LINK_TCP
) ||
518 (lnk
->link_type
== LINK_UDP
))) {
519 if (GetSocket(la
, port_net
, &lnk
->sockfd
, lnk
->link_type
)) {
520 lnk
->alias_port
= port_net
;
525 lnk
->alias_port
= port_net
;
527 #ifndef NO_USE_SOCKETS
531 port_sys
= krandom() & ALIAS_PORT_MASK
;
532 port_sys
+= ALIAS_PORT_BASE
;
533 port_net
= htons(port_sys
);
536 #ifdef LIBALIAS_DEBUG
537 fprintf(stderr
, "PacketAlias/GetnewPort(): ");
538 fprintf(stderr
, "could not find free port\n");
544 #ifndef NO_USE_SOCKETS
546 GetSocket(struct libalias
*la
, u_short port_net
, int *sockfd
, int link_type
)
550 struct sockaddr_in sock_addr
;
552 LIBALIAS_LOCK_ASSERT(la
);
553 if (link_type
== LINK_TCP
)
554 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
555 else if (link_type
== LINK_UDP
)
556 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
558 #ifdef LIBALIAS_DEBUG
559 fprintf(stderr
, "PacketAlias/GetSocket(): ");
560 fprintf(stderr
, "incorrect link type\n");
566 #ifdef LIBALIAS_DEBUG
567 fprintf(stderr
, "PacketAlias/GetSocket(): ");
568 fprintf(stderr
, "socket() error %d\n", *sockfd
);
572 sock_addr
.sin_family
= AF_INET
;
573 sock_addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
574 sock_addr
.sin_port
= port_net
;
577 (struct sockaddr
*)&sock_addr
,
590 /* FindNewPortGroup() returns a base port number for an available
591 range of contiguous port numbers. Note that if a port number
592 is already in use, that does not mean that it cannot be used by
593 another link concurrently. This is because FindNewPortGroup()
594 looks for unused triplets: (dest addr, dest port, alias port). */
597 FindNewPortGroup(struct libalias
*la
,
598 struct in_addr dst_addr
,
599 struct in_addr alias_addr
,
611 LIBALIAS_LOCK_ASSERT(la
);
613 * Get link_type from protocol
618 link_type
= LINK_UDP
;
621 link_type
= LINK_TCP
;
629 * The aliasing port is automatically selected by one of two
632 max_trials
= GET_NEW_PORT_MAX_ATTEMPTS
;
634 if (la
->packetAliasMode
& PKT_ALIAS_SAME_PORTS
) {
636 * When the ALIAS_SAME_PORTS option is chosen, the first
637 * try will be the actual source port. If this is already
638 * in use, the remainder of the trials will be random.
640 port_sys
= ntohs(src_port
);
644 /* First trial and all subsequent are random. */
645 if (align
== FIND_EVEN_ALIAS_BASE
)
646 port_sys
= krandom() & ALIAS_PORT_MASK_EVEN
;
648 port_sys
= krandom() & ALIAS_PORT_MASK
;
650 port_sys
+= ALIAS_PORT_BASE
;
653 /* Port number search */
654 for (i
= 0; i
< max_trials
; i
++) {
656 struct alias_link
*search_result
;
658 for (j
= 0; j
< port_count
; j
++)
659 if (0 != (search_result
= FindLinkIn(la
, dst_addr
, alias_addr
,
660 dst_port
, htons(port_sys
+ j
),
664 /* Found a good range, return base */
666 return (htons(port_sys
));
668 /* Find a new base to try */
669 if (align
== FIND_EVEN_ALIAS_BASE
)
670 port_sys
= krandom() & ALIAS_PORT_MASK_EVEN
;
672 port_sys
= krandom() & ALIAS_PORT_MASK
;
674 port_sys
+= ALIAS_PORT_BASE
;
677 #ifdef LIBALIAS_DEBUG
678 fprintf(stderr
, "PacketAlias/FindNewPortGroup(): ");
679 fprintf(stderr
, "could not find free port(s)\n");
686 CleanupAliasData(struct libalias
*la
)
688 struct alias_link
*lnk
;
691 LIBALIAS_LOCK_ASSERT(la
);
692 for (i
= 0; i
< LINK_TABLE_OUT_SIZE
; i
++) {
693 lnk
= LIST_FIRST(&la
->linkTableOut
[i
]);
694 while (lnk
!= NULL
) {
695 struct alias_link
*link_next
= LIST_NEXT(lnk
, list_out
);
701 la
->cleanupIndex
= 0;
706 IncrementalCleanup(struct libalias
*la
)
708 struct alias_link
*lnk
, *lnk_tmp
;
710 LIBALIAS_LOCK_ASSERT(la
);
712 LIST_FOREACH_MUTABLE(lnk
, &la
->linkTableOut
[la
->cleanupIndex
++],list_out
, lnk_tmp
) {
713 if (la
->timeStamp
- lnk
->timestamp
> lnk
->expire_time
)
717 if (la
->cleanupIndex
== LINK_TABLE_OUT_SIZE
)
718 la
->cleanupIndex
= 0;
722 DeleteLink(struct alias_link
*lnk
)
724 struct libalias
*la
= lnk
->la
;
726 LIBALIAS_LOCK_ASSERT(la
);
727 /* Don't do anything if the link is marked permanent */
728 if (la
->deleteAllLinks
== 0 && lnk
->flags
& LINK_PERMANENT
)
732 /* Delete associated firewall hole, if any */
736 /* Free memory allocated for LSNAT server pool */
737 if (lnk
->server
!= NULL
) {
738 struct server
*head
, *curr
, *next
;
740 head
= curr
= lnk
->server
;
744 } while ((curr
= next
) != head
);
746 /* Adjust output table pointers */
747 LIST_REMOVE(lnk
, list_out
);
749 /* Adjust input table pointers */
750 LIST_REMOVE(lnk
, list_in
);
751 #ifndef NO_USE_SOCKETS
752 /* Close socket, if one has been allocated */
753 if (lnk
->sockfd
!= -1) {
758 /* Link-type dependent cleanup */
759 switch (lnk
->link_type
) {
768 kfree(lnk
->data
.tcp
,M_ALIAS
);
773 case LINK_FRAGMENT_ID
:
774 la
->fragmentIdLinkCount
--;
776 case LINK_FRAGMENT_PTR
:
777 la
->fragmentPtrLinkCount
--;
778 if (lnk
->data
.frag_ptr
!= NULL
)
779 kfree(lnk
->data
.frag_ptr
,M_ALIAS
);
784 la
->protoLinkCount
--;
791 /* Write statistics, if logging enabled */
792 if (la
->packetAliasMode
& PKT_ALIAS_LOG
) {
798 static struct alias_link
*
799 AddLink(struct libalias
*la
, struct in_addr src_addr
,
800 struct in_addr dst_addr
,
801 struct in_addr alias_addr
,
804 int alias_port_param
, /* if less than zero, alias */
806 { /* port will be automatically *//* chosen.
808 u_int start_point
; /* zero, equal to alias port */
809 struct alias_link
*lnk
;
811 LIBALIAS_LOCK_ASSERT(la
);
812 lnk
= kmalloc(sizeof(struct alias_link
),M_ALIAS
, M_WAITOK
| M_ZERO
);
814 /* Basic initialization */
816 lnk
->src_addr
= src_addr
;
817 lnk
->dst_addr
= dst_addr
;
818 lnk
->alias_addr
= alias_addr
;
819 lnk
->proxy_addr
.s_addr
= INADDR_ANY
;
820 lnk
->src_port
= src_port
;
821 lnk
->dst_port
= dst_port
;
824 lnk
->link_type
= link_type
;
825 #ifndef NO_USE_SOCKETS
830 lnk
->timestamp
= la
->timeStamp
;
832 /* Expiration time */
835 lnk
->expire_time
= ICMP_EXPIRE_TIME
;
838 lnk
->expire_time
= UDP_EXPIRE_TIME
;
841 lnk
->expire_time
= TCP_EXPIRE_INITIAL
;
844 lnk
->flags
|= LINK_PERMANENT
; /* no timeout. */
846 case LINK_FRAGMENT_ID
:
847 lnk
->expire_time
= FRAGMENT_ID_EXPIRE_TIME
;
849 case LINK_FRAGMENT_PTR
:
850 lnk
->expire_time
= FRAGMENT_PTR_EXPIRE_TIME
;
855 lnk
->expire_time
= PROTO_EXPIRE_TIME
;
859 /* Determine alias flags */
860 if (dst_addr
.s_addr
== INADDR_ANY
)
861 lnk
->flags
|= LINK_UNKNOWN_DEST_ADDR
;
863 lnk
->flags
|= LINK_UNKNOWN_DEST_PORT
;
865 /* Determine alias port */
866 if (GetNewPort(la
, lnk
, alias_port_param
) != 0) {
870 /* Link-type dependent initialization */
872 struct tcp_dat
*aux_tcp
;
881 aux_tcp
= kmalloc(sizeof(struct tcp_dat
),M_ALIAS
, M_WAITOK
| M_ZERO
);
882 if (aux_tcp
!= NULL
) {
886 aux_tcp
->state
.in
= ALIAS_TCP_STATE_NOT_CONNECTED
;
887 aux_tcp
->state
.out
= ALIAS_TCP_STATE_NOT_CONNECTED
;
888 aux_tcp
->state
.index
= 0;
889 aux_tcp
->state
.ack_modified
= 0;
890 for (i
= 0; i
< N_LINK_TCP_DATA
; i
++)
891 aux_tcp
->ack
[i
].active
= 0;
892 aux_tcp
->fwhole
= -1;
893 lnk
->data
.tcp
= aux_tcp
;
895 #ifdef LIBALIAS_DEBUG
896 fprintf(stderr
, "PacketAlias/AddLink: ");
897 fprintf(stderr
, " cannot allocate auxiliary TCP data\n");
906 case LINK_FRAGMENT_ID
:
907 la
->fragmentIdLinkCount
++;
909 case LINK_FRAGMENT_PTR
:
910 la
->fragmentPtrLinkCount
++;
915 la
->protoLinkCount
++;
919 /* Set up pointers for output lookup table */
920 start_point
= StartPointOut(src_addr
, dst_addr
,
921 src_port
, dst_port
, link_type
);
922 LIST_INSERT_HEAD(&la
->linkTableOut
[start_point
], lnk
, list_out
);
924 /* Set up pointers for input lookup table */
925 start_point
= StartPointIn(alias_addr
, lnk
->alias_port
, link_type
);
926 LIST_INSERT_HEAD(&la
->linkTableIn
[start_point
], lnk
, list_in
);
928 #ifdef LIBALIAS_DEBUG
929 fprintf(stderr
, "PacketAlias/AddLink(): ");
930 fprintf(stderr
, "kmalloc() call failed.\n");
933 if (la
->packetAliasMode
& PKT_ALIAS_LOG
) {
939 static struct alias_link
*
940 ReLink(struct alias_link
*old_lnk
,
941 struct in_addr src_addr
,
942 struct in_addr dst_addr
,
943 struct in_addr alias_addr
,
946 int alias_port_param
, /* if less than zero, alias */
948 { /* port will be automatically *//* chosen.
950 struct alias_link
*new_lnk
; /* zero, equal to alias port */
951 struct libalias
*la
= old_lnk
->la
;
953 LIBALIAS_LOCK_ASSERT(la
);
954 new_lnk
= AddLink(la
, src_addr
, dst_addr
, alias_addr
,
955 src_port
, dst_port
, alias_port_param
,
958 if (new_lnk
!= NULL
&&
959 old_lnk
->link_type
== LINK_TCP
&&
960 old_lnk
->data
.tcp
->fwhole
> 0) {
961 PunchFWHole(new_lnk
);
968 static struct alias_link
*
969 _FindLinkOut(struct libalias
*la
, struct in_addr src_addr
,
970 struct in_addr dst_addr
,
974 int replace_partial_links
)
977 struct alias_link
*lnk
;
979 LIBALIAS_LOCK_ASSERT(la
);
980 i
= StartPointOut(src_addr
, dst_addr
, src_port
, dst_port
, link_type
);
981 LIST_FOREACH(lnk
, &la
->linkTableOut
[i
], list_out
) {
982 if (lnk
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
983 lnk
->src_addr
.s_addr
== src_addr
.s_addr
&&
984 lnk
->src_port
== src_port
&&
985 lnk
->dst_port
== dst_port
&&
986 lnk
->link_type
== link_type
&&
987 lnk
->server
== NULL
) {
988 lnk
->timestamp
= la
->timeStamp
;
993 /* Search for partially specified links. */
994 if (lnk
== NULL
&& replace_partial_links
) {
995 if (dst_port
!= 0 && dst_addr
.s_addr
!= INADDR_ANY
) {
996 lnk
= _FindLinkOut(la
, src_addr
, dst_addr
, src_port
, 0,
999 lnk
= _FindLinkOut(la
, src_addr
, la
->nullAddress
, src_port
,
1000 dst_port
, link_type
, 0);
1003 (dst_port
!= 0 || dst_addr
.s_addr
!= INADDR_ANY
)) {
1004 lnk
= _FindLinkOut(la
, src_addr
, la
->nullAddress
, src_port
, 0,
1009 src_addr
, dst_addr
, lnk
->alias_addr
,
1010 src_port
, dst_port
, lnk
->alias_port
,
1017 static struct alias_link
*
1018 FindLinkOut(struct libalias
*la
, struct in_addr src_addr
,
1019 struct in_addr dst_addr
,
1023 int replace_partial_links
)
1025 struct alias_link
*lnk
;
1027 LIBALIAS_LOCK_ASSERT(la
);
1028 lnk
= _FindLinkOut(la
, src_addr
, dst_addr
, src_port
, dst_port
,
1029 link_type
, replace_partial_links
);
1033 * The following allows permanent links to be specified as
1034 * using the default source address (i.e. device interface
1035 * address) without knowing in advance what that address
1038 if (la
->aliasAddress
.s_addr
!= INADDR_ANY
&&
1039 src_addr
.s_addr
== la
->aliasAddress
.s_addr
) {
1040 lnk
= _FindLinkOut(la
, la
->nullAddress
, dst_addr
, src_port
, dst_port
,
1041 link_type
, replace_partial_links
);
1048 static struct alias_link
*
1049 _FindLinkIn(struct libalias
*la
, struct in_addr dst_addr
,
1050 struct in_addr alias_addr
,
1054 int replace_partial_links
)
1058 struct alias_link
*lnk
;
1059 struct alias_link
*lnk_fully_specified
;
1060 struct alias_link
*lnk_unknown_all
;
1061 struct alias_link
*lnk_unknown_dst_addr
;
1062 struct alias_link
*lnk_unknown_dst_port
;
1064 LIBALIAS_LOCK_ASSERT(la
);
1065 /* Initialize pointers */
1066 lnk_fully_specified
= NULL
;
1067 lnk_unknown_all
= NULL
;
1068 lnk_unknown_dst_addr
= NULL
;
1069 lnk_unknown_dst_port
= NULL
;
1071 /* If either the dest addr or port is unknown, the search
1072 loop will have to know about this. */
1075 if (dst_addr
.s_addr
== INADDR_ANY
)
1076 flags_in
|= LINK_UNKNOWN_DEST_ADDR
;
1078 flags_in
|= LINK_UNKNOWN_DEST_PORT
;
1081 start_point
= StartPointIn(alias_addr
, alias_port
, link_type
);
1082 LIST_FOREACH(lnk
, &la
->linkTableIn
[start_point
], list_in
) {
1085 flags
= flags_in
| lnk
->flags
;
1086 if (!(flags
& LINK_PARTIALLY_SPECIFIED
)) {
1087 if (lnk
->alias_addr
.s_addr
== alias_addr
.s_addr
1088 && lnk
->alias_port
== alias_port
1089 && lnk
->dst_addr
.s_addr
== dst_addr
.s_addr
1090 && lnk
->dst_port
== dst_port
1091 && lnk
->link_type
== link_type
) {
1092 lnk_fully_specified
= lnk
;
1095 } else if ((flags
& LINK_UNKNOWN_DEST_ADDR
)
1096 && (flags
& LINK_UNKNOWN_DEST_PORT
)) {
1097 if (lnk
->alias_addr
.s_addr
== alias_addr
.s_addr
1098 && lnk
->alias_port
== alias_port
1099 && lnk
->link_type
== link_type
) {
1100 if (lnk_unknown_all
== NULL
)
1101 lnk_unknown_all
= lnk
;
1103 } else if (flags
& LINK_UNKNOWN_DEST_ADDR
) {
1104 if (lnk
->alias_addr
.s_addr
== alias_addr
.s_addr
1105 && lnk
->alias_port
== alias_port
1106 && lnk
->link_type
== link_type
1107 && lnk
->dst_port
== dst_port
) {
1108 if (lnk_unknown_dst_addr
== NULL
)
1109 lnk_unknown_dst_addr
= lnk
;
1111 } else if (flags
& LINK_UNKNOWN_DEST_PORT
) {
1112 if (lnk
->alias_addr
.s_addr
== alias_addr
.s_addr
1113 && lnk
->alias_port
== alias_port
1114 && lnk
->link_type
== link_type
1115 && lnk
->dst_addr
.s_addr
== dst_addr
.s_addr
) {
1116 if (lnk_unknown_dst_port
== NULL
)
1117 lnk_unknown_dst_port
= lnk
;
1124 if (lnk_fully_specified
!= NULL
) {
1125 lnk_fully_specified
->timestamp
= la
->timeStamp
;
1126 lnk
= lnk_fully_specified
;
1127 } else if (lnk_unknown_dst_port
!= NULL
)
1128 lnk
= lnk_unknown_dst_port
;
1129 else if (lnk_unknown_dst_addr
!= NULL
)
1130 lnk
= lnk_unknown_dst_addr
;
1131 else if (lnk_unknown_all
!= NULL
)
1132 lnk
= lnk_unknown_all
;
1136 if (replace_partial_links
&&
1137 (lnk
->flags
& LINK_PARTIALLY_SPECIFIED
|| lnk
->server
!= NULL
)) {
1138 struct in_addr src_addr
;
1141 if (lnk
->server
!= NULL
) { /* LSNAT link */
1142 src_addr
= lnk
->server
->addr
;
1143 src_port
= lnk
->server
->port
;
1144 lnk
->server
= lnk
->server
->next
;
1146 src_addr
= lnk
->src_addr
;
1147 src_port
= lnk
->src_port
;
1151 src_addr
, dst_addr
, alias_addr
,
1152 src_port
, dst_port
, alias_port
,
1158 static struct alias_link
*
1159 FindLinkIn(struct libalias
*la
, struct in_addr dst_addr
,
1160 struct in_addr alias_addr
,
1164 int replace_partial_links
)
1166 struct alias_link
*lnk
;
1168 LIBALIAS_LOCK_ASSERT(la
);
1169 lnk
= _FindLinkIn(la
, dst_addr
, alias_addr
, dst_port
, alias_port
,
1170 link_type
, replace_partial_links
);
1174 * The following allows permanent links to be specified as
1175 * using the default aliasing address (i.e. device
1176 * interface address) without knowing in advance what that
1179 if (la
->aliasAddress
.s_addr
!= INADDR_ANY
&&
1180 alias_addr
.s_addr
== la
->aliasAddress
.s_addr
) {
1181 lnk
= _FindLinkIn(la
, dst_addr
, la
->nullAddress
, dst_port
, alias_port
,
1182 link_type
, replace_partial_links
);
1191 /* External routines for finding/adding links
1193 -- "external" means outside alias_db.c, but within alias*.c --
1195 FindIcmpIn(), FindIcmpOut()
1196 FindFragmentIn1(), FindFragmentIn2()
1197 AddFragmentPtrLink(), FindFragmentPtr()
1198 FindProtoIn(), FindProtoOut()
1199 FindUdpTcpIn(), FindUdpTcpOut()
1200 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1201 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1202 FindOriginalAddress(), FindAliasAddress()
1204 (prototypes in alias_local.h)
1209 FindIcmpIn(struct libalias
*la
, struct in_addr dst_addr
,
1210 struct in_addr alias_addr
,
1214 struct alias_link
*lnk
;
1216 LIBALIAS_LOCK_ASSERT(la
);
1217 lnk
= FindLinkIn(la
, dst_addr
, alias_addr
,
1218 NO_DEST_PORT
, id_alias
,
1220 if (lnk
== NULL
&& create
&& !(la
->packetAliasMode
& PKT_ALIAS_DENY_INCOMING
)) {
1221 struct in_addr target_addr
;
1223 target_addr
= FindOriginalAddress(la
, alias_addr
);
1224 lnk
= AddLink(la
, target_addr
, dst_addr
, alias_addr
,
1225 id_alias
, NO_DEST_PORT
, id_alias
,
1233 FindIcmpOut(struct libalias
*la
, struct in_addr src_addr
,
1234 struct in_addr dst_addr
,
1238 struct alias_link
*lnk
;
1240 LIBALIAS_LOCK_ASSERT(la
);
1241 lnk
= FindLinkOut(la
, src_addr
, dst_addr
,
1244 if (lnk
== NULL
&& create
) {
1245 struct in_addr alias_addr
;
1247 alias_addr
= FindAliasAddress(la
, src_addr
);
1248 lnk
= AddLink(la
, src_addr
, dst_addr
, alias_addr
,
1249 id
, NO_DEST_PORT
, GET_ALIAS_ID
,
1257 FindFragmentIn1(struct libalias
*la
, struct in_addr dst_addr
,
1258 struct in_addr alias_addr
,
1261 struct alias_link
*lnk
;
1263 LIBALIAS_LOCK_ASSERT(la
);
1264 lnk
= FindLinkIn(la
, dst_addr
, alias_addr
,
1265 NO_DEST_PORT
, ip_id
,
1266 LINK_FRAGMENT_ID
, 0);
1269 lnk
= AddLink(la
, la
->nullAddress
, dst_addr
, alias_addr
,
1270 NO_SRC_PORT
, NO_DEST_PORT
, ip_id
,
1278 FindFragmentIn2(struct libalias
*la
, struct in_addr dst_addr
, /* Doesn't add a link if
1280 struct in_addr alias_addr
, /* is not found. */
1284 LIBALIAS_LOCK_ASSERT(la
);
1285 return FindLinkIn(la
, dst_addr
, alias_addr
,
1286 NO_DEST_PORT
, ip_id
,
1287 LINK_FRAGMENT_ID
, 0);
1292 AddFragmentPtrLink(struct libalias
*la
, struct in_addr dst_addr
,
1296 LIBALIAS_LOCK_ASSERT(la
);
1297 return AddLink(la
, la
->nullAddress
, dst_addr
, la
->nullAddress
,
1298 NO_SRC_PORT
, NO_DEST_PORT
, ip_id
,
1304 FindFragmentPtr(struct libalias
*la
, struct in_addr dst_addr
,
1308 LIBALIAS_LOCK_ASSERT(la
);
1309 return FindLinkIn(la
, dst_addr
, la
->nullAddress
,
1310 NO_DEST_PORT
, ip_id
,
1311 LINK_FRAGMENT_PTR
, 0);
1316 FindProtoIn(struct libalias
*la
, struct in_addr dst_addr
,
1317 struct in_addr alias_addr
,
1320 struct alias_link
*lnk
;
1322 LIBALIAS_LOCK_ASSERT(la
);
1323 lnk
= FindLinkIn(la
, dst_addr
, alias_addr
,
1327 if (lnk
== NULL
&& !(la
->packetAliasMode
& PKT_ALIAS_DENY_INCOMING
)) {
1328 struct in_addr target_addr
;
1330 target_addr
= FindOriginalAddress(la
, alias_addr
);
1331 lnk
= AddLink(la
, target_addr
, dst_addr
, alias_addr
,
1332 NO_SRC_PORT
, NO_DEST_PORT
, 0,
1340 FindProtoOut(struct libalias
*la
, struct in_addr src_addr
,
1341 struct in_addr dst_addr
,
1344 struct alias_link
*lnk
;
1346 LIBALIAS_LOCK_ASSERT(la
);
1347 lnk
= FindLinkOut(la
, src_addr
, dst_addr
,
1348 NO_SRC_PORT
, NO_DEST_PORT
,
1352 struct in_addr alias_addr
;
1354 alias_addr
= FindAliasAddress(la
, src_addr
);
1355 lnk
= AddLink(la
, src_addr
, dst_addr
, alias_addr
,
1356 NO_SRC_PORT
, NO_DEST_PORT
, 0,
1364 FindUdpTcpIn(struct libalias
*la
, struct in_addr dst_addr
,
1365 struct in_addr alias_addr
,
1372 struct alias_link
*lnk
;
1374 LIBALIAS_LOCK_ASSERT(la
);
1377 link_type
= LINK_UDP
;
1380 link_type
= LINK_TCP
;
1387 lnk
= FindLinkIn(la
, dst_addr
, alias_addr
,
1388 dst_port
, alias_port
,
1391 if (lnk
== NULL
&& create
&& !(la
->packetAliasMode
& PKT_ALIAS_DENY_INCOMING
)) {
1392 struct in_addr target_addr
;
1394 target_addr
= FindOriginalAddress(la
, alias_addr
);
1395 lnk
= AddLink(la
, target_addr
, dst_addr
, alias_addr
,
1396 alias_port
, dst_port
, alias_port
,
1404 FindUdpTcpOut(struct libalias
*la
, struct in_addr src_addr
,
1405 struct in_addr dst_addr
,
1412 struct alias_link
*lnk
;
1414 LIBALIAS_LOCK_ASSERT(la
);
1417 link_type
= LINK_UDP
;
1420 link_type
= LINK_TCP
;
1427 lnk
= FindLinkOut(la
, src_addr
, dst_addr
, src_port
, dst_port
, link_type
, create
);
1429 if (lnk
== NULL
&& create
) {
1430 struct in_addr alias_addr
;
1432 alias_addr
= FindAliasAddress(la
, src_addr
);
1433 lnk
= AddLink(la
, src_addr
, dst_addr
, alias_addr
,
1434 src_port
, dst_port
, GET_ALIAS_PORT
,
1442 AddPptp(struct libalias
*la
, struct in_addr src_addr
,
1443 struct in_addr dst_addr
,
1444 struct in_addr alias_addr
,
1445 u_int16_t src_call_id
)
1447 struct alias_link
*lnk
;
1449 LIBALIAS_LOCK_ASSERT(la
);
1450 lnk
= AddLink(la
, src_addr
, dst_addr
, alias_addr
,
1451 src_call_id
, 0, GET_ALIAS_PORT
,
1459 FindPptpOutByCallId(struct libalias
*la
, struct in_addr src_addr
,
1460 struct in_addr dst_addr
,
1461 u_int16_t src_call_id
)
1464 struct alias_link
*lnk
;
1466 LIBALIAS_LOCK_ASSERT(la
);
1467 i
= StartPointOut(src_addr
, dst_addr
, 0, 0, LINK_PPTP
);
1468 LIST_FOREACH(lnk
, &la
->linkTableOut
[i
], list_out
)
1469 if (lnk
->link_type
== LINK_PPTP
&&
1470 lnk
->src_addr
.s_addr
== src_addr
.s_addr
&&
1471 lnk
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1472 lnk
->src_port
== src_call_id
)
1480 FindPptpOutByPeerCallId(struct libalias
*la
, struct in_addr src_addr
,
1481 struct in_addr dst_addr
,
1482 u_int16_t dst_call_id
)
1485 struct alias_link
*lnk
;
1487 LIBALIAS_LOCK_ASSERT(la
);
1488 i
= StartPointOut(src_addr
, dst_addr
, 0, 0, LINK_PPTP
);
1489 LIST_FOREACH(lnk
, &la
->linkTableOut
[i
], list_out
)
1490 if (lnk
->link_type
== LINK_PPTP
&&
1491 lnk
->src_addr
.s_addr
== src_addr
.s_addr
&&
1492 lnk
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1493 lnk
->dst_port
== dst_call_id
)
1501 FindPptpInByCallId(struct libalias
*la
, struct in_addr dst_addr
,
1502 struct in_addr alias_addr
,
1503 u_int16_t dst_call_id
)
1506 struct alias_link
*lnk
;
1508 LIBALIAS_LOCK_ASSERT(la
);
1509 i
= StartPointIn(alias_addr
, 0, LINK_PPTP
);
1510 LIST_FOREACH(lnk
, &la
->linkTableIn
[i
], list_in
)
1511 if (lnk
->link_type
== LINK_PPTP
&&
1512 lnk
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1513 lnk
->alias_addr
.s_addr
== alias_addr
.s_addr
&&
1514 lnk
->dst_port
== dst_call_id
)
1522 FindPptpInByPeerCallId(struct libalias
*la
, struct in_addr dst_addr
,
1523 struct in_addr alias_addr
,
1524 u_int16_t alias_call_id
)
1526 struct alias_link
*lnk
;
1528 LIBALIAS_LOCK_ASSERT(la
);
1529 lnk
= FindLinkIn(la
, dst_addr
, alias_addr
,
1530 0 /* any */ , alias_call_id
,
1539 FindRtspOut(struct libalias
*la
, struct in_addr src_addr
,
1540 struct in_addr dst_addr
,
1546 struct alias_link
*lnk
;
1548 LIBALIAS_LOCK_ASSERT(la
);
1551 link_type
= LINK_UDP
;
1554 link_type
= LINK_TCP
;
1561 lnk
= FindLinkOut(la
, src_addr
, dst_addr
, src_port
, 0, link_type
, 1);
1564 struct in_addr alias_addr
;
1566 alias_addr
= FindAliasAddress(la
, src_addr
);
1567 lnk
= AddLink(la
, src_addr
, dst_addr
, alias_addr
,
1568 src_port
, 0, alias_port
,
1576 FindOriginalAddress(struct libalias
*la
, struct in_addr alias_addr
)
1578 struct alias_link
*lnk
;
1580 LIBALIAS_LOCK_ASSERT(la
);
1581 lnk
= FindLinkIn(la
, la
->nullAddress
, alias_addr
,
1582 0, 0, LINK_ADDR
, 0);
1584 la
->newDefaultLink
= 1;
1585 if (la
->targetAddress
.s_addr
== INADDR_ANY
)
1586 return (alias_addr
);
1587 else if (la
->targetAddress
.s_addr
== INADDR_NONE
)
1588 return (la
->aliasAddress
.s_addr
!= INADDR_ANY
) ?
1589 la
->aliasAddress
: alias_addr
;
1591 return (la
->targetAddress
);
1593 if (lnk
->server
!= NULL
) { /* LSNAT link */
1594 struct in_addr src_addr
;
1596 src_addr
= lnk
->server
->addr
;
1597 lnk
->server
= lnk
->server
->next
;
1599 } else if (lnk
->src_addr
.s_addr
== INADDR_ANY
)
1600 return (la
->aliasAddress
.s_addr
!= INADDR_ANY
) ?
1601 la
->aliasAddress
: alias_addr
;
1603 return (lnk
->src_addr
);
1609 FindAliasAddress(struct libalias
*la
, struct in_addr original_addr
)
1611 struct alias_link
*lnk
;
1613 LIBALIAS_LOCK_ASSERT(la
);
1614 lnk
= FindLinkOut(la
, original_addr
, la
->nullAddress
,
1615 0, 0, LINK_ADDR
, 0);
1617 return (la
->aliasAddress
.s_addr
!= INADDR_ANY
) ?
1618 la
->aliasAddress
: original_addr
;
1620 if (lnk
->alias_addr
.s_addr
== INADDR_ANY
)
1621 return (la
->aliasAddress
.s_addr
!= INADDR_ANY
) ?
1622 la
->aliasAddress
: original_addr
;
1624 return (lnk
->alias_addr
);
1629 /* External routines for getting or changing link data
1630 (external to alias_db.c, but internal to alias*.c)
1632 SetFragmentData(), GetFragmentData()
1633 SetFragmentPtr(), GetFragmentPtr()
1634 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1635 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1636 GetOriginalPort(), GetAliasPort()
1637 SetAckModified(), GetAckModified()
1638 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1639 SetProtocolFlags(), GetProtocolFlags()
1645 SetFragmentAddr(struct alias_link
*lnk
, struct in_addr src_addr
)
1647 lnk
->data
.frag_addr
= src_addr
;
1652 GetFragmentAddr(struct alias_link
*lnk
, struct in_addr
*src_addr
)
1654 *src_addr
= lnk
->data
.frag_addr
;
1659 SetFragmentPtr(struct alias_link
*lnk
, char *fptr
)
1661 lnk
->data
.frag_ptr
= fptr
;
1666 GetFragmentPtr(struct alias_link
*lnk
, char **fptr
)
1668 *fptr
= lnk
->data
.frag_ptr
;
1673 SetStateIn(struct alias_link
*lnk
, int state
)
1675 /* TCP input state */
1677 case ALIAS_TCP_STATE_DISCONNECTED
:
1678 if (lnk
->data
.tcp
->state
.out
!= ALIAS_TCP_STATE_CONNECTED
)
1679 lnk
->expire_time
= TCP_EXPIRE_DEAD
;
1681 lnk
->expire_time
= TCP_EXPIRE_SINGLEDEAD
;
1683 case ALIAS_TCP_STATE_CONNECTED
:
1684 if (lnk
->data
.tcp
->state
.out
== ALIAS_TCP_STATE_CONNECTED
)
1685 lnk
->expire_time
= TCP_EXPIRE_CONNECTED
;
1689 panic("libalias:SetStateIn() unknown state");
1694 lnk
->data
.tcp
->state
.in
= state
;
1699 SetStateOut(struct alias_link
*lnk
, int state
)
1701 /* TCP output state */
1703 case ALIAS_TCP_STATE_DISCONNECTED
:
1704 if (lnk
->data
.tcp
->state
.in
!= ALIAS_TCP_STATE_CONNECTED
)
1705 lnk
->expire_time
= TCP_EXPIRE_DEAD
;
1707 lnk
->expire_time
= TCP_EXPIRE_SINGLEDEAD
;
1709 case ALIAS_TCP_STATE_CONNECTED
:
1710 if (lnk
->data
.tcp
->state
.in
== ALIAS_TCP_STATE_CONNECTED
)
1711 lnk
->expire_time
= TCP_EXPIRE_CONNECTED
;
1715 panic("libalias:SetStateOut() unknown state");
1720 lnk
->data
.tcp
->state
.out
= state
;
1725 GetStateIn(struct alias_link
*lnk
)
1727 /* TCP input state */
1728 return (lnk
->data
.tcp
->state
.in
);
1733 GetStateOut(struct alias_link
*lnk
)
1735 /* TCP output state */
1736 return (lnk
->data
.tcp
->state
.out
);
1741 GetOriginalAddress(struct alias_link
*lnk
)
1743 if (lnk
->src_addr
.s_addr
== INADDR_ANY
)
1744 return (lnk
->la
->aliasAddress
);
1746 return (lnk
->src_addr
);
1751 GetDestAddress(struct alias_link
*lnk
)
1753 return (lnk
->dst_addr
);
1758 GetAliasAddress(struct alias_link
*lnk
)
1760 if (lnk
->alias_addr
.s_addr
== INADDR_ANY
)
1761 return (lnk
->la
->aliasAddress
);
1763 return (lnk
->alias_addr
);
1768 GetDefaultAliasAddress(struct libalias
*la
)
1771 LIBALIAS_LOCK_ASSERT(la
);
1772 return (la
->aliasAddress
);
1777 SetDefaultAliasAddress(struct libalias
*la
, struct in_addr alias_addr
)
1780 LIBALIAS_LOCK_ASSERT(la
);
1781 la
->aliasAddress
= alias_addr
;
1786 GetOriginalPort(struct alias_link
*lnk
)
1788 return (lnk
->src_port
);
1793 GetAliasPort(struct alias_link
*lnk
)
1795 return (lnk
->alias_port
);
1800 GetDestPort(struct alias_link
*lnk
)
1802 return (lnk
->dst_port
);
1808 SetAckModified(struct alias_link
*lnk
)
1810 /* Indicate that ACK numbers have been modified in a TCP connection */
1811 lnk
->data
.tcp
->state
.ack_modified
= 1;
1816 GetProxyAddress(struct alias_link
*lnk
)
1818 return (lnk
->proxy_addr
);
1823 SetProxyAddress(struct alias_link
*lnk
, struct in_addr addr
)
1825 lnk
->proxy_addr
= addr
;
1830 GetProxyPort(struct alias_link
*lnk
)
1832 return (lnk
->proxy_port
);
1837 SetProxyPort(struct alias_link
*lnk
, u_short port
)
1839 lnk
->proxy_port
= port
;
1844 GetAckModified(struct alias_link
*lnk
)
1846 /* See if ACK numbers have been modified */
1847 return (lnk
->data
.tcp
->state
.ack_modified
);
1852 GetDeltaAckIn(struct ip
*pip
, struct alias_link
*lnk
)
1855 Find out how much the ACK number has been altered for an incoming
1856 TCP packet. To do this, a circular list of ACK numbers where the TCP
1857 packet size was altered is searched.
1862 int delta
, ack_diff_min
;
1870 for (i
= 0; i
< N_LINK_TCP_DATA
; i
++) {
1871 struct ack_data_record x
;
1873 x
= lnk
->data
.tcp
->ack
[i
];
1874 if (x
.active
== 1) {
1877 ack_diff
= SeqDiff(x
.ack_new
, ack
);
1878 if (ack_diff
>= 0) {
1879 if (ack_diff_min
>= 0) {
1880 if (ack_diff
< ack_diff_min
) {
1882 ack_diff_min
= ack_diff
;
1886 ack_diff_min
= ack_diff
;
1896 GetDeltaSeqOut(struct ip
*pip
, struct alias_link
*lnk
)
1899 Find out how much the sequence number has been altered for an outgoing
1900 TCP packet. To do this, a circular list of ACK numbers where the TCP
1901 packet size was altered is searched.
1906 int delta
, seq_diff_min
;
1914 for (i
= 0; i
< N_LINK_TCP_DATA
; i
++) {
1915 struct ack_data_record x
;
1917 x
= lnk
->data
.tcp
->ack
[i
];
1918 if (x
.active
== 1) {
1921 seq_diff
= SeqDiff(x
.ack_old
, seq
);
1922 if (seq_diff
>= 0) {
1923 if (seq_diff_min
>= 0) {
1924 if (seq_diff
< seq_diff_min
) {
1926 seq_diff_min
= seq_diff
;
1930 seq_diff_min
= seq_diff
;
1940 AddSeq(struct ip
*pip
, struct alias_link
*lnk
, int delta
)
1943 When a TCP packet has been altered in length, save this
1944 information in a circular list. If enough packets have
1945 been altered, then this list will begin to overwrite itself.
1949 struct ack_data_record x
;
1950 int hlen
, tlen
, dlen
;
1955 hlen
= (pip
->ip_hl
+ tc
->th_off
) << 2;
1956 tlen
= ntohs(pip
->ip_len
);
1959 x
.ack_old
= htonl(ntohl(tc
->th_seq
) + dlen
);
1960 x
.ack_new
= htonl(ntohl(tc
->th_seq
) + dlen
+ delta
);
1964 i
= lnk
->data
.tcp
->state
.index
;
1965 lnk
->data
.tcp
->ack
[i
] = x
;
1968 if (i
== N_LINK_TCP_DATA
)
1969 lnk
->data
.tcp
->state
.index
= 0;
1971 lnk
->data
.tcp
->state
.index
= i
;
1975 SetExpire(struct alias_link
*lnk
, int expire
)
1978 lnk
->flags
&= ~LINK_PERMANENT
;
1980 } else if (expire
== -1) {
1981 lnk
->flags
|= LINK_PERMANENT
;
1982 } else if (expire
> 0) {
1983 lnk
->expire_time
= expire
;
1985 #ifdef LIBALIAS_DEBUG
1986 fprintf(stderr
, "PacketAlias/SetExpire(): ");
1987 fprintf(stderr
, "error in expire parameter\n");
1993 ClearCheckNewLink(struct libalias
*la
)
1996 LIBALIAS_LOCK_ASSERT(la
);
1997 la
->newDefaultLink
= 0;
2001 SetProtocolFlags(struct alias_link
*lnk
, int pflags
)
2004 lnk
->pflags
= pflags
;;
2008 GetProtocolFlags(struct alias_link
*lnk
)
2011 return (lnk
->pflags
);
2015 SetDestCallId(struct alias_link
*lnk
, u_int16_t cid
)
2017 struct libalias
*la
= lnk
->la
;
2019 LIBALIAS_LOCK_ASSERT(la
);
2020 la
->deleteAllLinks
= 1;
2021 ReLink(lnk
, lnk
->src_addr
, lnk
->dst_addr
, lnk
->alias_addr
,
2022 lnk
->src_port
, cid
, lnk
->alias_port
, lnk
->link_type
);
2023 la
->deleteAllLinks
= 0;
2027 /* Miscellaneous Functions
2030 InitPacketAliasLog()
2031 UninitPacketAliasLog()
2035 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2036 is called to find and remove timed-out aliasing links. Logic exists
2037 to sweep through the entire table and linked list structure
2040 (prototype in alias_local.h)
2044 HouseKeeping(struct libalias
*la
)
2052 LIBALIAS_LOCK_ASSERT(la
);
2054 * Save system time (seconds) in global variable timeStamp for use
2055 * by other functions. This is done so as not to unnecessarily
2056 * waste timeline by making system calls.
2059 la
->timeStamp
= time_uptime
;
2061 gettimeofday(&tv
, &tz
);
2062 la
->timeStamp
= tv
.tv_sec
;
2065 /* Compute number of spokes (output table link chains) to cover */
2066 n
= LINK_TABLE_OUT_SIZE
* (la
->timeStamp
- la
->lastCleanupTime
);
2067 n
/= ALIAS_CLEANUP_INTERVAL_SECS
;
2069 /* Handle different cases */
2071 if (n
> ALIAS_CLEANUP_MAX_SPOKES
)
2072 n
= ALIAS_CLEANUP_MAX_SPOKES
;
2073 la
->lastCleanupTime
= la
->timeStamp
;
2074 for (i
= 0; i
< n
; i
++)
2075 IncrementalCleanup(la
);
2077 #ifdef LIBALIAS_DEBUG
2078 fprintf(stderr
, "PacketAlias/HouseKeeping(): ");
2079 fprintf(stderr
, "something unexpected in time values\n");
2081 la
->lastCleanupTime
= la
->timeStamp
;
2085 /* Init the log file and enable logging */
2087 InitPacketAliasLog(struct libalias
*la
)
2090 LIBALIAS_LOCK_ASSERT(la
);
2091 if (~la
->packetAliasMode
& PKT_ALIAS_LOG
) {
2093 if ((la
->logDesc
= kmalloc(LIBALIAS_BUF_SIZE
,M_ALIAS
, M_WAITOK
| M_ZERO
)))
2096 if ((la
->logDesc
= fopen("/var/log/alias.log", "w")))
2097 fprintf(la
->logDesc
, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2100 return (ENOMEM
); /* log initialization failed */
2101 la
->packetAliasMode
|= PKT_ALIAS_LOG
;
2107 /* Close the log-file and disable logging. */
2109 UninitPacketAliasLog(struct libalias
*la
)
2112 LIBALIAS_LOCK_ASSERT(la
);
2115 kfree(la
->logDesc
,M_ALIAS
);
2117 fclose(la
->logDesc
);
2121 la
->packetAliasMode
&= ~PKT_ALIAS_LOG
;
2124 /* Outside world interfaces
2126 -- "outside world" means other than alias*.c routines --
2128 PacketAliasRedirectPort()
2129 PacketAliasAddServer()
2130 PacketAliasRedirectProto()
2131 PacketAliasRedirectAddr()
2132 PacketAliasRedirectDynamic()
2133 PacketAliasRedirectDelete()
2134 PacketAliasSetAddress()
2137 PacketAliasSetMode()
2139 (prototypes in alias.h)
2142 /* Redirection from a specific public addr:port to a
2143 private addr:port */
2145 LibAliasRedirectPort(struct libalias
*la
, struct in_addr src_addr
, u_short src_port
,
2146 struct in_addr dst_addr
, u_short dst_port
,
2147 struct in_addr alias_addr
, u_short alias_port
,
2151 struct alias_link
*lnk
;
2156 link_type
= LINK_UDP
;
2159 link_type
= LINK_TCP
;
2162 #ifdef LIBALIAS_DEBUG
2163 fprintf(stderr
, "PacketAliasRedirectPort(): ");
2164 fprintf(stderr
, "only TCP and UDP protocols allowed\n");
2170 lnk
= AddLink(la
, src_addr
, dst_addr
, alias_addr
,
2171 src_port
, dst_port
, alias_port
,
2175 lnk
->flags
|= LINK_PERMANENT
;
2177 #ifdef LIBALIAS_DEBUG
2179 fprintf(stderr
, "PacketAliasRedirectPort(): "
2180 "call to AddLink() failed\n");
2185 LIBALIAS_UNLOCK(la
);
2189 /* Add server to the pool of servers */
2191 LibAliasAddServer(struct libalias
*la
, struct alias_link
*lnk
, struct in_addr addr
, u_short port
)
2193 struct server
*server
;
2199 server
= kmalloc(sizeof(struct server
),M_ALIAS
, M_WAITOK
| M_ZERO
);
2201 if (server
!= NULL
) {
2202 struct server
*head
;
2204 server
->addr
= addr
;
2205 server
->port
= port
;
2209 server
->next
= server
;
2213 for (s
= head
; s
->next
!= head
; s
= s
->next
);
2215 server
->next
= head
;
2217 lnk
->server
= server
;
2222 LIBALIAS_UNLOCK(la
);
2226 /* Redirect packets of a given IP protocol from a specific
2227 public address to a private address */
2229 LibAliasRedirectProto(struct libalias
*la
, struct in_addr src_addr
,
2230 struct in_addr dst_addr
,
2231 struct in_addr alias_addr
,
2234 struct alias_link
*lnk
;
2237 lnk
= AddLink(la
, src_addr
, dst_addr
, alias_addr
,
2238 NO_SRC_PORT
, NO_DEST_PORT
, 0,
2242 lnk
->flags
|= LINK_PERMANENT
;
2244 #ifdef LIBALIAS_DEBUG
2246 fprintf(stderr
, "PacketAliasRedirectProto(): "
2247 "call to AddLink() failed\n");
2251 LIBALIAS_UNLOCK(la
);
2255 /* Static address translation */
2257 LibAliasRedirectAddr(struct libalias
*la
, struct in_addr src_addr
,
2258 struct in_addr alias_addr
)
2260 struct alias_link
*lnk
;
2263 lnk
= AddLink(la
, src_addr
, la
->nullAddress
, alias_addr
,
2268 lnk
->flags
|= LINK_PERMANENT
;
2270 #ifdef LIBALIAS_DEBUG
2272 fprintf(stderr
, "PacketAliasRedirectAddr(): "
2273 "call to AddLink() failed\n");
2277 LIBALIAS_UNLOCK(la
);
2282 /* Mark the aliasing link dynamic */
2284 LibAliasRedirectDynamic(struct libalias
*la
, struct alias_link
*lnk
)
2291 if (lnk
->flags
& LINK_PARTIALLY_SPECIFIED
)
2294 lnk
->flags
&= ~LINK_PERMANENT
;
2297 LIBALIAS_UNLOCK(la
);
2303 LibAliasRedirectDelete(struct libalias
*la
, struct alias_link
*lnk
)
2305 /* This is a dangerous function to put in the API,
2306 because an invalid pointer can crash the program. */
2309 la
->deleteAllLinks
= 1;
2311 la
->deleteAllLinks
= 0;
2312 LIBALIAS_UNLOCK(la
);
2317 LibAliasSetAddress(struct libalias
*la
, struct in_addr addr
)
2321 if (la
->packetAliasMode
& PKT_ALIAS_RESET_ON_ADDR_CHANGE
2322 && la
->aliasAddress
.s_addr
!= addr
.s_addr
)
2323 CleanupAliasData(la
);
2325 la
->aliasAddress
= addr
;
2326 LIBALIAS_UNLOCK(la
);
2331 LibAliasSetTarget(struct libalias
*la
, struct in_addr target_addr
)
2335 la
->targetAddress
= target_addr
;
2336 LIBALIAS_UNLOCK(la
);
2343 while (!LIST_EMPTY(&instancehead
))
2344 LibAliasUninit(LIST_FIRST(&instancehead
));
2348 LibAliasInit(struct libalias
*la
)
2357 la
= kmalloc(sizeof *la
,M_ALIAS
, M_WAITOK
| M_ZERO
);
2361 #ifndef _KERNEL /* kernel cleans up on module unload */
2362 if (LIST_EMPTY(&instancehead
))
2365 LIST_INSERT_HEAD(&instancehead
, la
, instancelist
);
2368 la
->timeStamp
= time_uptime
;
2369 la
->lastCleanupTime
= time_uptime
;
2371 gettimeofday(&tv
, &tz
);
2372 la
->timeStamp
= tv
.tv_sec
;
2373 la
->lastCleanupTime
= tv
.tv_sec
;
2376 for (i
= 0; i
< LINK_TABLE_OUT_SIZE
; i
++)
2377 LIST_INIT(&la
->linkTableOut
[i
]);
2378 for (i
= 0; i
< LINK_TABLE_IN_SIZE
; i
++)
2379 LIST_INIT(&la
->linkTableIn
[i
]);
2380 LIBALIAS_LOCK_INIT(la
);
2384 la
->deleteAllLinks
= 1;
2385 CleanupAliasData(la
);
2386 la
->deleteAllLinks
= 0;
2389 la
->aliasAddress
.s_addr
= INADDR_ANY
;
2390 la
->targetAddress
.s_addr
= INADDR_ANY
;
2392 la
->icmpLinkCount
= 0;
2393 la
->udpLinkCount
= 0;
2394 la
->tcpLinkCount
= 0;
2395 la
->pptpLinkCount
= 0;
2396 la
->protoLinkCount
= 0;
2397 la
->fragmentIdLinkCount
= 0;
2398 la
->fragmentPtrLinkCount
= 0;
2401 la
->cleanupIndex
= 0;
2403 la
->packetAliasMode
= PKT_ALIAS_SAME_PORTS
2404 #ifndef NO_USE_SOCKETS
2405 | PKT_ALIAS_USE_SOCKETS
2407 | PKT_ALIAS_RESET_ON_ADDR_CHANGE
;
2409 la
->fireWallFD
= -1;
2412 LibAliasRefreshModules();
2414 LIBALIAS_UNLOCK(la
);
2419 LibAliasUninit(struct libalias
*la
)
2423 la
->deleteAllLinks
= 1;
2424 CleanupAliasData(la
);
2425 la
->deleteAllLinks
= 0;
2426 UninitPacketAliasLog(la
);
2430 LIST_REMOVE(la
, instancelist
);
2431 LIBALIAS_UNLOCK(la
);
2432 LIBALIAS_LOCK_DESTROY(la
);
2436 /* Change mode for some operations */
2439 struct libalias
*la
,
2440 unsigned int flags
, /* Which state to bring flags to */
2441 unsigned int mask
/* Mask of which flags to affect (use 0 to
2442 * do a probe for flag values) */
2448 /* Enable logging? */
2449 if (flags
& mask
& PKT_ALIAS_LOG
) {
2451 if (InitPacketAliasLog(la
) == ENOMEM
)
2454 /* _Disable_ logging? */
2455 if (~flags
& mask
& PKT_ALIAS_LOG
) {
2456 UninitPacketAliasLog(la
);
2459 /* Start punching holes in the firewall? */
2460 if (flags
& mask
& PKT_ALIAS_PUNCH_FW
) {
2463 /* Stop punching holes in the firewall? */
2464 if (~flags
& mask
& PKT_ALIAS_PUNCH_FW
) {
2469 /* Other flags can be set/cleared without special action */
2470 la
->packetAliasMode
= (flags
& mask
) | (la
->packetAliasMode
& ~mask
);
2471 res
= la
->packetAliasMode
;
2473 LIBALIAS_UNLOCK(la
);
2479 LibAliasCheckNewLink(struct libalias
*la
)
2484 res
= la
->newDefaultLink
;
2485 LIBALIAS_UNLOCK(la
);
2493 Code to support firewall punching. This shouldn't really be in this
2494 file, but making variables global is evil too.
2497 /* Firewall include files */
2499 #include <netinet/ip_fw.h>
2504 * helper function, updates the pointer to cmd with the length
2505 * of the current command, and also cleans up the first word of
2506 * the new command in case it has been clobbered before.
2509 next_cmd(ipfw_insn
* cmd
)
2512 bzero(cmd
, sizeof(*cmd
));
2517 * A function to fill simple commands of size 1.
2518 * Existing flags are preserved.
2521 fill_cmd(ipfw_insn
* cmd
, enum ipfw_opcodes opcode
, int size
,
2522 int flags
, u_int16_t arg
)
2524 cmd
->opcode
= opcode
;
2525 cmd
->len
= ((cmd
->len
| flags
) & (F_NOT
| F_OR
)) | (size
& F_LEN_MASK
);
2527 return next_cmd(cmd
);
2531 fill_ip(ipfw_insn
* cmd1
, enum ipfw_opcodes opcode
, u_int32_t addr
)
2533 ipfw_insn_ip
*cmd
= (ipfw_insn_ip
*) cmd1
;
2535 cmd
->addr
.s_addr
= addr
;
2536 return fill_cmd(cmd1
, opcode
, F_INSN_SIZE(ipfw_insn_u32
), 0, 0);
2540 fill_one_port(ipfw_insn
* cmd1
, enum ipfw_opcodes opcode
, u_int16_t port
)
2542 ipfw_insn_u16
*cmd
= (ipfw_insn_u16
*) cmd1
;
2544 cmd
->ports
[0] = cmd
->ports
[1] = port
;
2545 return fill_cmd(cmd1
, opcode
, F_INSN_SIZE(ipfw_insn_u16
), 0, 0);
2549 fill_rule(void *buf
, int bufsize
, int rulenum
,
2550 enum ipfw_opcodes action
, int proto
,
2551 struct in_addr sa
, u_int16_t sp
, struct in_addr da
, u_int16_t dp
)
2553 struct ip_fw
*rule
= (struct ip_fw
*)buf
;
2554 ipfw_insn
*cmd
= (ipfw_insn
*) rule
->cmd
;
2556 bzero(buf
, bufsize
);
2557 rule
->rulenum
= rulenum
;
2559 cmd
= fill_cmd(cmd
, O_PROTO
, F_INSN_SIZE(ipfw_insn
), 0, proto
);
2560 cmd
= fill_ip(cmd
, O_IP_SRC
, sa
.s_addr
);
2561 cmd
= fill_one_port(cmd
, O_IP_SRCPORT
, sp
);
2562 cmd
= fill_ip(cmd
, O_IP_DST
, da
.s_addr
);
2563 cmd
= fill_one_port(cmd
, O_IP_DSTPORT
, dp
);
2565 rule
->act_ofs
= (u_int32_t
*) cmd
- (u_int32_t
*) rule
->cmd
;
2566 cmd
= fill_cmd(cmd
, action
, F_INSN_SIZE(ipfw_insn
), 0, 0);
2568 rule
->cmd_len
= (u_int32_t
*) cmd
- (u_int32_t
*) rule
->cmd
;
2570 return ((char *)cmd
- (char *)buf
);
2573 static void ClearAllFWHoles(struct libalias
*la
);
2576 #define fw_setfield(la, field, num) \
2578 (field)[(num) - la->fireWallBaseNum] = 1; \
2579 } /*lint -save -e717 */ while(0)/* lint -restore */
2581 #define fw_clrfield(la, field, num) \
2583 (field)[(num) - la->fireWallBaseNum] = 0; \
2584 } /*lint -save -e717 */ while(0)/* lint -restore */
2586 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2589 InitPunchFW(struct libalias
*la
)
2592 LIBALIAS_LOCK_ASSERT(la
);
2593 la
->fireWallField
= kmalloc(la
->fireWallNumNums
,M_ALIAS
, M_WAITOK
| M_ZERO
);
2594 if (la
->fireWallField
) {
2595 memset(la
->fireWallField
, 0, la
->fireWallNumNums
);
2596 if (la
->fireWallFD
< 0) {
2597 la
->fireWallFD
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
2599 ClearAllFWHoles(la
);
2600 la
->fireWallActiveNum
= la
->fireWallBaseNum
;
2605 UninitPunchFW(struct libalias
*la
)
2608 LIBALIAS_LOCK_ASSERT(la
);
2609 ClearAllFWHoles(la
);
2610 if (la
->fireWallFD
>= 0)
2611 close(la
->fireWallFD
);
2612 la
->fireWallFD
= -1;
2613 if (la
->fireWallField
)
2614 kfree(la
->fireWallField
,M_ALIAS
);
2615 la
->fireWallField
= NULL
;
2616 la
->packetAliasMode
&= ~PKT_ALIAS_PUNCH_FW
;
2619 /* Make a certain link go through the firewall */
2621 PunchFWHole(struct alias_link
*lnk
)
2623 struct libalias
*la
;
2624 int r
; /* Result code */
2625 struct ip_fw rule
; /* On-the-fly built rule */
2626 int fwhole
; /* Where to punch hole */
2628 LIBALIAS_LOCK_ASSERT(la
);
2631 /* Don't do anything unless we are asked to */
2632 if (!(la
->packetAliasMode
& PKT_ALIAS_PUNCH_FW
) ||
2633 la
->fireWallFD
< 0 ||
2634 lnk
->link_type
!= LINK_TCP
)
2637 memset(&rule
, 0, sizeof rule
);
2641 /* Find empty slot */
2642 for (fwhole
= la
->fireWallActiveNum
;
2643 fwhole
< la
->fireWallBaseNum
+ la
->fireWallNumNums
&&
2644 fw_tstfield(la
, la
->fireWallField
, fwhole
);
2646 if (fwhole
== la
->fireWallBaseNum
+ la
->fireWallNumNums
) {
2647 for (fwhole
= la
->fireWallBaseNum
;
2648 fwhole
< la
->fireWallActiveNum
&&
2649 fw_tstfield(la
, la
->fireWallField
, fwhole
);
2651 if (fwhole
== la
->fireWallActiveNum
) {
2652 /* No rule point empty - we can't punch more holes. */
2653 la
->fireWallActiveNum
= la
->fireWallBaseNum
;
2654 #ifdef LIBALIAS_DEBUG
2655 fprintf(stderr
, "libalias: Unable to create firewall hole!\n");
2660 /* Start next search at next position */
2661 la
->fireWallActiveNum
= fwhole
+ 1;
2664 * generate two rules of the form
2666 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2667 * accept tcp from DAddr DPort to OAddr OPort
2669 if (GetOriginalPort(lnk
) != 0 && GetDestPort(lnk
) != 0) {
2670 u_int32_t rulebuf
[255];
2673 i
= fill_rule(rulebuf
, sizeof(rulebuf
), fwhole
,
2674 O_ACCEPT
, IPPROTO_TCP
,
2675 GetOriginalAddress(lnk
), ntohs(GetOriginalPort(lnk
)),
2676 GetDestAddress(lnk
), ntohs(GetDestPort(lnk
)));
2677 r
= setsockopt(la
->fireWallFD
, IPPROTO_IP
, IP_FW_ADD
, rulebuf
, i
);
2679 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2681 i
= fill_rule(rulebuf
, sizeof(rulebuf
), fwhole
,
2682 O_ACCEPT
, IPPROTO_TCP
,
2683 GetDestAddress(lnk
), ntohs(GetDestPort(lnk
)),
2684 GetOriginalAddress(lnk
), ntohs(GetOriginalPort(lnk
)));
2685 r
= setsockopt(la
->fireWallFD
, IPPROTO_IP
, IP_FW_ADD
, rulebuf
, i
);
2687 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2690 /* Indicate hole applied */
2691 lnk
->data
.tcp
->fwhole
= fwhole
;
2692 fw_setfield(la
, la
->fireWallField
, fwhole
);
2695 /* Remove a hole in a firewall associated with a particular alias
2696 lnk. Calling this too often is harmless. */
2698 ClearFWHole(struct alias_link
*lnk
)
2700 struct libalias
*la
;
2702 LIBALIAS_LOCK_ASSERT(la
);
2704 if (lnk
->link_type
== LINK_TCP
) {
2705 int fwhole
= lnk
->data
.tcp
->fwhole
; /* Where is the firewall
2712 memset(&rule
, 0, sizeof rule
); /* useless for ipfw3 */
2713 while (!setsockopt(la
->fireWallFD
, IPPROTO_IP
, IP_FW_DEL
,
2714 &fwhole
, sizeof fwhole
));
2715 fw_clrfield(la
, la
->fireWallField
, fwhole
);
2716 lnk
->data
.tcp
->fwhole
= -1;
2720 /* Clear out the entire range dedicated to firewall holes. */
2722 ClearAllFWHoles(struct libalias
*la
)
2724 struct ip_fw rule
; /* On-the-fly built rule */
2727 LIBALIAS_LOCK_ASSERT(la
);
2728 if (la
->fireWallFD
< 0)
2731 memset(&rule
, 0, sizeof rule
);
2732 for (i
= la
->fireWallBaseNum
; i
< la
->fireWallBaseNum
+ la
->fireWallNumNums
; i
++) {
2735 while (!setsockopt(la
->fireWallFD
, IPPROTO_IP
, IP_FW_DEL
, &r
, sizeof r
));
2737 /* XXX: third arg correct here ? /phk */
2738 memset(la
->fireWallField
, 0, la
->fireWallNumNums
);
2744 LibAliasSetFWBase(struct libalias
*la
, unsigned int base
, unsigned int num
)
2749 la
->fireWallBaseNum
= base
;
2750 la
->fireWallNumNums
= num
;
2752 LIBALIAS_UNLOCK(la
);
2756 LibAliasSetSkinnyPort(struct libalias
*la
, unsigned int port
)
2760 la
->skinnyPort
= port
;
2761 LIBALIAS_UNLOCK(la
);