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
28
#include <sys/cdefs.h>
29
__FBSDID("$FreeBSD: src/sys/netinet/libalias/alias_db.c,v 1.71.2.2.4.1 2009/04/15 03:14:26 kensmith Exp $");
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.
149
#include <machine/stdarg.h>
150
#include <sys/param.h>
151
#include <sys/kernel.h>
152
#include <sys/module.h>
153
#include <sys/syslog.h>
158
#include <sys/errno.h>
159
#include <sys/time.h>
163
#include <sys/socket.h>
164
#include <netinet/tcp.h>
167
#include <netinet/libalias/alias.h>
168
#include <netinet/libalias/alias_local.h>
169
#include <netinet/libalias/alias_mod.h>
173
#include "alias_local.h"
174
#include "alias_mod.h"
177
# include <iprt/assert.h>
179
# include "alias_local.h"
180
# include "alias_mod.h"
185
static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
190
Constants (note: constants are also defined
191
near relevant functions or structs)
194
/* Parameters used for cleanup of expired links */
195
/* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */
196
#define ALIAS_CLEANUP_INTERVAL_SECS 64
197
#define ALIAS_CLEANUP_MAX_SPOKES (LINK_TABLE_OUT_SIZE/5)
199
/* Timeouts (in seconds) for different link types */
200
#define ICMP_EXPIRE_TIME 60
201
#define UDP_EXPIRE_TIME 60
202
#define PROTO_EXPIRE_TIME 60
203
#define FRAGMENT_ID_EXPIRE_TIME 10
204
#define FRAGMENT_PTR_EXPIRE_TIME 30
206
/* TCP link expire time for different cases */
207
/* When the link has been used and closed - minimal grace time to
208
allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
209
#ifndef TCP_EXPIRE_DEAD
210
#define TCP_EXPIRE_DEAD 10
213
/* When the link has been used and closed on one side - the other side
214
is allowed to still send data */
215
#ifndef TCP_EXPIRE_SINGLEDEAD
216
#define TCP_EXPIRE_SINGLEDEAD 90
219
/* When the link isn't yet up */
220
#ifndef TCP_EXPIRE_INITIAL
221
#define TCP_EXPIRE_INITIAL 300
224
/* When the link is up */
225
#ifndef TCP_EXPIRE_CONNECTED
226
#define TCP_EXPIRE_CONNECTED 86400
230
/* Dummy port number codes used for FindLinkIn/Out() and AddLink().
231
These constants can be anything except zero, which indicates an
232
unknown port number. */
234
#define NO_DEST_PORT 1
235
#define NO_SRC_PORT 1
241
The fundamental data structure used in this program is
242
"struct alias_link". Whenever a TCP connection is made,
243
a UDP datagram is sent out, or an ICMP echo request is made,
244
a link record is made (if it has not already been created).
245
The link record is identified by the source address/port
246
and the destination address/port. In the case of an ICMP
247
echo request, the source port is treated as being equivalent
248
with the 16-bit ID number of the ICMP packet.
250
The link record also can store some auxiliary data. For
251
TCP connections that have had sequence and acknowledgment
252
modifications, data space is available to track these changes.
253
A state field is used to keep track in changes to the TCP
254
connection state. ID numbers of fragments can also be
255
stored in the auxiliary space. Pointers to unresolved
256
fragments can also be stored.
258
The link records support two independent chainings. Lookup
259
tables for input and out tables hold the initial pointers
260
the link chains. On input, the lookup table indexes on alias
261
port and link type. On output, the lookup table indexes on
262
source address, destination address, source port, destination
266
struct ack_data_record { /* used to save changes to ACK/sequence
274
struct tcp_state { /* Information about TCP connection */
275
int in; /* State for outside -> inside */
276
int out; /* State for inside -> outside */
277
int index; /* Index to ACK data array */
278
int ack_modified; /* Indicates whether ACK and
279
* sequence numbers */
283
#define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes
284
* saved for a modified TCP stream */
286
struct tcp_state state;
287
struct ack_data_record ack[N_LINK_TCP_DATA];
288
int fwhole; /* Which firewall record is used for this
292
struct server { /* LSNAT server pool (circular list) */
298
struct alias_link { /* Main data structure */
300
struct in_addr src_addr; /* Address and port information */
301
struct in_addr dst_addr;
302
struct in_addr alias_addr;
303
struct in_addr proxy_addr;
308
struct server *server;
310
int link_type; /* Type of link: TCP, UDP, ICMP,
313
/* values for link_type */
314
#define LINK_ICMP IPPROTO_ICMP
315
#define LINK_UDP IPPROTO_UDP
316
#define LINK_TCP IPPROTO_TCP
317
#define LINK_FRAGMENT_ID (IPPROTO_MAX + 1)
318
#define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2)
319
#define LINK_ADDR (IPPROTO_MAX + 3)
320
#define LINK_PPTP (IPPROTO_MAX + 4)
322
int flags; /* indicates special characteristics */
323
int pflags; /* protocol-specific flags */
326
#define LINK_UNKNOWN_DEST_PORT 0x01
327
#define LINK_UNKNOWN_DEST_ADDR 0x02
328
#define LINK_PERMANENT 0x04
329
#define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
331
# define LINK_UNFIREWALLED 0x08 /* This macro definition isn't used in this revision of libalias */
333
int timestamp; /* Time link was last accessed */
334
int expire_time; /* Expire time for link */
336
unsigned int timestamp; /* Time link was last accessed */
337
unsigned int expire_time; /* Expire time for link */
340
#ifndef NO_USE_SOCKETS
341
int sockfd; /* socket descriptor */
343
LIST_ENTRY (alias_link) list_out; /* Linked list of
345
LIST_ENTRY (alias_link) list_in; /* input and output
348
union { /* Auxiliary data */
350
struct in_addr frag_addr;
355
/* Clean up procedure. */
357
static void finishoff(void);
360
/* Kernel module definition. */
362
MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing");
364
MODULE_VERSION(libalias, 1);
367
alias_mod_handler(module_t mod, int type, void *data)
374
handler_chain_init();
378
handler_chain_destroy();
389
static moduledata_t alias_mod = {
390
"alias", alias_mod_handler, NULL
393
DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
396
/* Internal utility routines (used only in alias_db.c)
398
Lookup table starting points:
399
StartPointIn() -- link table initial search point for
401
StartPointOut() -- link table initial search point for
405
SeqDiff() -- difference between two TCP sequences
406
ShowAliasStats() -- send alias statistics to a monitor file
410
/* Local prototypes */
411
static u_int StartPointIn(struct in_addr, u_short, int);
414
StartPointOut(struct in_addr, struct in_addr,
415
u_short, u_short, int);
417
static int SeqDiff(u_long, u_long);
420
/* Firewall control */
421
static void InitPunchFW(struct libalias *);
422
static void UninitPunchFW(struct libalias *);
423
static void ClearFWHole(struct alias_link *);
427
/* Log file control */
428
static void ShowAliasStats(struct libalias *);
429
static int InitPacketAliasLog(struct libalias *);
430
static void UninitPacketAliasLog(struct libalias *);
433
StartPointIn(struct in_addr alias_addr,
439
n = alias_addr.s_addr;
440
if (link_type != LINK_PPTP)
443
return (n % LINK_TABLE_IN_SIZE);
448
StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
449
u_short src_port, u_short dst_port, int link_type)
454
n += dst_addr.s_addr;
455
if (link_type != LINK_PPTP) {
461
return (n % LINK_TABLE_OUT_SIZE);
466
SeqDiff(u_long x, u_long y)
468
/* Return the difference between two TCP sequence numbers */
471
This function is encapsulated in case there are any unusual
472
arithmetic conditions that need to be considered.
475
return (ntohl(y) - ntohl(x));
481
AliasLog(char *str, const char *format, ...)
485
va_start(ap, format);
486
vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
491
AliasLog(FILE *stream, const char *format, ...)
496
va_start(ap, format);
497
vfprintf(stream, format, ap);
505
memset(buffer, 0, 1024);
506
va_start(args, format);
507
RTStrPrintfV(buffer, 1024, format, args);
509
/*make it grepable */
510
Log2(("NAT:ALIAS: %s\n", buffer));
516
ShowAliasStats(struct libalias *la)
519
LIBALIAS_LOCK_ASSERT(la);
520
/* Used for debugging */
522
int tot = la->icmpLinkCount + la->udpLinkCount +
523
la->tcpLinkCount + la->pptpLinkCount +
524
la->protoLinkCount + la->fragmentIdLinkCount +
525
la->fragmentPtrLinkCount;
527
AliasLog(la->logDesc,
528
"icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
534
la->fragmentIdLinkCount,
535
la->fragmentPtrLinkCount, tot);
537
AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
542
/* Internal routines for finding, deleting and adding links
545
GetNewPort() -- find and reserve new alias port number
546
GetSocket() -- try to allocate a socket for a given port
548
Link creation and deletion:
549
CleanupAliasData() - remove all link chains from lookup table
550
IncrementalCleanup() - look for stale links in a single chain
551
DeleteLink() - remove link
553
ReLink() - change link
556
FindLinkOut() - find link for outgoing packets
557
FindLinkIn() - find link for incoming packets
560
FindNewPortGroup() - find an available group of ports
563
/* Local prototypes */
564
static int GetNewPort(struct libalias *, struct alias_link *, int);
565
#ifndef NO_USE_SOCKETS
566
static u_short GetSocket(struct libalias *, u_short, int *, int);
568
static void CleanupAliasData(struct libalias *);
570
static void IncrementalCleanup(struct libalias *);
572
static void DeleteLink(struct alias_link *);
574
static struct alias_link *
575
AddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr,
576
u_short, u_short, int, int);
578
static struct alias_link *
579
ReLink(struct alias_link *,
580
struct in_addr, struct in_addr, struct in_addr,
581
u_short, u_short, int, int);
583
static struct alias_link *
584
FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
586
static struct alias_link *
587
FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
590
#define ALIAS_PORT_BASE 0x08000
591
#define ALIAS_PORT_MASK 0x07fff
592
#define ALIAS_PORT_MASK_EVEN 0x07ffe
593
#define GET_NEW_PORT_MAX_ATTEMPTS 20
595
#define GET_ALIAS_PORT -1
596
#define GET_ALIAS_ID GET_ALIAS_PORT
598
#define FIND_EVEN_ALIAS_BASE 1
600
/* GetNewPort() allocates port numbers. Note that if a port number
601
is already in use, that does not mean that it cannot be used by
602
another link concurrently. This is because GetNewPort() looks for
603
unused triplets: (dest addr, dest port, alias port). */
606
GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
613
LIBALIAS_LOCK_ASSERT(la);
615
Description of alias_port_param for GetNewPort(). When
616
this parameter is zero or positive, it precisely specifies
617
the port number. GetNewPort() will return this number
618
without check that it is in use.
620
When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
621
selected port number.
624
if (alias_port_param == GET_ALIAS_PORT) {
626
* The aliasing port is automatically selected by one of
629
max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
631
if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
633
* When the PKT_ALIAS_SAME_PORTS option is chosen,
634
* the first try will be the actual source port. If
635
* this is already in use, the remainder of the
636
* trials will be random.
638
port_net = lnk->src_port;
639
port_sys = ntohs(port_net);
641
/* First trial and all subsequent are random. */
642
port_sys = arc4random() & ALIAS_PORT_MASK;
643
port_sys += ALIAS_PORT_BASE;
644
port_net = htons(port_sys);
646
} else if (alias_port_param >= 0 && alias_port_param < 0x10000) {
647
lnk->alias_port = (u_short) alias_port_param;
650
#ifdef LIBALIAS_DEBUG
651
fprintf(stderr, "PacketAlias/GetNewPort(): ");
652
fprintf(stderr, "input parameter error\n");
658
/* Port number search */
659
for (i = 0; i < max_trials; i++) {
661
struct alias_link *search_result;
663
search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr,
664
lnk->dst_port, port_net,
667
if (search_result == NULL)
669
else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED)
670
&& (search_result->flags & LINK_PARTIALLY_SPECIFIED))
676
#ifndef NO_USE_SOCKETS
677
if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS)
678
&& (lnk->flags & LINK_PARTIALLY_SPECIFIED)
679
&& ((lnk->link_type == LINK_TCP) ||
680
(lnk->link_type == LINK_UDP))) {
681
if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) {
682
lnk->alias_port = port_net;
687
lnk->alias_port = port_net;
689
#ifndef NO_USE_SOCKETS
693
port_sys = arc4random() & ALIAS_PORT_MASK;
694
port_sys += ALIAS_PORT_BASE;
695
port_net = htons(port_sys);
698
#ifdef LIBALIAS_DEBUG
699
fprintf(stderr, "PacketAlias/GetnewPort(): ");
700
fprintf(stderr, "could not find free port\n");
706
#ifndef NO_USE_SOCKETS
708
GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
712
struct sockaddr_in sock_addr;
714
LIBALIAS_LOCK_ASSERT(la);
715
if (link_type == LINK_TCP)
716
sock = socket(AF_INET, SOCK_STREAM, 0);
717
else if (link_type == LINK_UDP)
718
sock = socket(AF_INET, SOCK_DGRAM, 0);
720
#ifdef LIBALIAS_DEBUG
721
fprintf(stderr, "PacketAlias/GetSocket(): ");
722
fprintf(stderr, "incorrect link type\n");
728
#ifdef LIBALIAS_DEBUG
729
fprintf(stderr, "PacketAlias/GetSocket(): ");
730
fprintf(stderr, "socket() error %d\n", *sockfd);
735
memset(&sock_addr, 0, sizeof(struct sockaddr_in));
736
sock_addr.sin_family = AF_INET;
737
sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
738
sock_addr.sin_port = port_net;
740
sock_addr.sin_len = sizeof(struct sockaddr_in);
745
(struct sockaddr *)&sock_addr,
758
/* FindNewPortGroup() returns a base port number for an available
759
range of contiguous port numbers. Note that if a port number
760
is already in use, that does not mean that it cannot be used by
761
another link concurrently. This is because FindNewPortGroup()
762
looks for unused triplets: (dest addr, dest port, alias port). */
765
FindNewPortGroup(struct libalias *la,
766
struct in_addr dst_addr,
767
struct in_addr alias_addr,
779
LIBALIAS_LOCK_ASSERT(la);
781
* Get link_type from protocol
786
link_type = LINK_UDP;
789
link_type = LINK_TCP;
797
* The aliasing port is automatically selected by one of two
800
max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
802
if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
804
* When the ALIAS_SAME_PORTS option is chosen, the first
805
* try will be the actual source port. If this is already
806
* in use, the remainder of the trials will be random.
808
port_sys = ntohs(src_port);
812
/* First trial and all subsequent are random. */
813
if (align == FIND_EVEN_ALIAS_BASE)
814
port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
816
port_sys = arc4random() & ALIAS_PORT_MASK;
818
port_sys += ALIAS_PORT_BASE;
821
/* Port number search */
822
for (i = 0; i < max_trials; i++) {
824
struct alias_link *search_result;
826
for (j = 0; j < port_count; j++)
827
if (0 != (search_result = FindLinkIn(la, dst_addr, alias_addr,
828
dst_port, htons(port_sys + j),
832
/* Found a good range, return base */
834
return (htons(port_sys));
836
/* Find a new base to try */
837
if (align == FIND_EVEN_ALIAS_BASE)
838
port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
840
port_sys = arc4random() & ALIAS_PORT_MASK;
842
port_sys += ALIAS_PORT_BASE;
845
#ifdef LIBALIAS_DEBUG
846
fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
847
fprintf(stderr, "could not find free port(s)\n");
854
CleanupAliasData(struct libalias *la)
856
struct alias_link *lnk;
859
LIBALIAS_LOCK_ASSERT(la);
860
for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) {
861
lnk = LIST_FIRST(&la->linkTableOut[i]);
862
while (lnk != NULL) {
863
struct alias_link *link_next = LIST_NEXT(lnk, list_out);
869
la->cleanupIndex = 0;
874
IncrementalCleanup(struct libalias *la)
876
struct alias_link *lnk, *lnk_tmp;
878
LIBALIAS_LOCK_ASSERT(la);
879
LIST_FOREACH_SAFE(lnk, &la->linkTableOut[la->cleanupIndex++],
881
if (la->timeStamp - lnk->timestamp > lnk->expire_time)
885
if (la->cleanupIndex == LINK_TABLE_OUT_SIZE)
886
la->cleanupIndex = 0;
890
DeleteLink(struct alias_link *lnk)
892
struct libalias *la = lnk->la;
895
LIBALIAS_LOCK_ASSERT(la);
896
/* Don't do anything if the link is marked permanent */
897
if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT)
901
/* Delete associated firewall hole, if any */
905
/* Free memory allocated for LSNAT server pool */
906
if (lnk->server != NULL) {
907
struct server *head, *curr, *next;
909
head = curr = lnk->server;
913
} while ((curr = next) != head);
915
/* Adjust output table pointers */
916
LIST_REMOVE(lnk, list_out);
918
/* Adjust input table pointers */
919
LIST_REMOVE(lnk, list_in);
920
#ifndef NO_USE_SOCKETS
921
/* Close socket, if one has been allocated */
922
if (lnk->sockfd != -1) {
924
closesocket(lnk->sockfd);
927
/* Link-type dependent cleanup */
928
switch (lnk->link_type) {
942
case LINK_FRAGMENT_ID:
943
la->fragmentIdLinkCount--;
945
case LINK_FRAGMENT_PTR:
946
la->fragmentPtrLinkCount--;
947
if (lnk->data.frag_ptr != NULL)
948
free(lnk->data.frag_ptr);
953
la->protoLinkCount--;
960
/* Write statistics, if logging enabled */
961
if (la->packetAliasMode & PKT_ALIAS_LOG) {
968
static struct alias_link *
969
AddLink(struct libalias *la, struct in_addr src_addr,
970
struct in_addr dst_addr,
971
struct in_addr alias_addr,
974
int alias_port_param, /* if less than zero, alias */
976
{ /* port will be automatically *//* chosen.
978
u_int start_point; /* zero, equal to alias port */
979
struct alias_link *lnk;
981
LIBALIAS_LOCK_ASSERT(la);
982
lnk = malloc(sizeof(struct alias_link));
984
/* Basic initialization */
986
lnk->src_addr = src_addr;
987
lnk->dst_addr = dst_addr;
988
lnk->alias_addr = alias_addr;
989
lnk->proxy_addr.s_addr = INADDR_ANY;
990
lnk->src_port = src_port;
991
lnk->dst_port = dst_port;
994
lnk->link_type = link_type;
995
#ifndef NO_USE_SOCKETS
1000
lnk->timestamp = la->timeStamp;
1002
/* Expiration time */
1003
switch (link_type) {
1005
lnk->expire_time = ICMP_EXPIRE_TIME;
1008
lnk->expire_time = UDP_EXPIRE_TIME;
1011
lnk->expire_time = TCP_EXPIRE_INITIAL;
1014
lnk->flags |= LINK_PERMANENT; /* no timeout. */
1016
case LINK_FRAGMENT_ID:
1017
lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME;
1019
case LINK_FRAGMENT_PTR:
1020
lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
1025
lnk->expire_time = PROTO_EXPIRE_TIME;
1029
/* Determine alias flags */
1030
if (dst_addr.s_addr == INADDR_ANY)
1031
lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
1033
lnk->flags |= LINK_UNKNOWN_DEST_PORT;
1035
/* Determine alias port */
1036
if (GetNewPort(la, lnk, alias_port_param) != 0) {
1040
/* Link-type dependent initialization */
1041
switch (link_type) {
1042
struct tcp_dat *aux_tcp;
1045
la->icmpLinkCount++;
1051
aux_tcp = malloc(sizeof(struct tcp_dat));
1052
if (aux_tcp != NULL) {
1056
aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
1057
aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
1058
aux_tcp->state.index = 0;
1059
aux_tcp->state.ack_modified = 0;
1060
for (i = 0; i < N_LINK_TCP_DATA; i++)
1061
aux_tcp->ack[i].active = 0;
1062
aux_tcp->fwhole = -1;
1063
lnk->data.tcp = aux_tcp;
1065
#ifdef LIBALIAS_DEBUG
1066
fprintf(stderr, "PacketAlias/AddLink: ");
1067
fprintf(stderr, " cannot allocate auxiliary TCP data\n");
1074
la->pptpLinkCount++;
1076
case LINK_FRAGMENT_ID:
1077
la->fragmentIdLinkCount++;
1079
case LINK_FRAGMENT_PTR:
1080
la->fragmentPtrLinkCount++;
1085
la->protoLinkCount++;
1089
/* Set up pointers for output lookup table */
1090
start_point = StartPointOut(src_addr, dst_addr,
1091
src_port, dst_port, link_type);
1092
LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out);
1094
/* Set up pointers for input lookup table */
1095
start_point = StartPointIn(alias_addr, lnk->alias_port, link_type);
1096
LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in);
1098
#ifdef LIBALIAS_DEBUG
1099
fprintf(stderr, "PacketAlias/AddLink(): ");
1100
fprintf(stderr, "malloc() call failed.\n");
1103
if (la->packetAliasMode & PKT_ALIAS_LOG) {
1109
static struct alias_link *
1110
ReLink(struct alias_link *old_lnk,
1111
struct in_addr src_addr,
1112
struct in_addr dst_addr,
1113
struct in_addr alias_addr,
1116
int alias_port_param, /* if less than zero, alias */
1118
{ /* port will be automatically *//* chosen.
1119
* If greater than */
1120
struct alias_link *new_lnk; /* zero, equal to alias port */
1121
struct libalias *la = old_lnk->la;
1123
LIBALIAS_LOCK_ASSERT(la);
1124
new_lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1125
src_port, dst_port, alias_port_param,
1128
if (new_lnk != NULL &&
1129
old_lnk->link_type == LINK_TCP &&
1130
old_lnk->data.tcp->fwhole > 0) {
1131
PunchFWHole(new_lnk);
1134
DeleteLink(old_lnk);
1138
static struct alias_link *
1139
_FindLinkOut(struct libalias *la, struct in_addr src_addr,
1140
struct in_addr dst_addr,
1144
int replace_partial_links)
1147
struct alias_link *lnk;
1149
LIBALIAS_LOCK_ASSERT(la);
1150
i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
1151
LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) {
1152
if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
1153
lnk->src_addr.s_addr == src_addr.s_addr &&
1154
lnk->src_port == src_port &&
1155
lnk->dst_port == dst_port &&
1156
lnk->link_type == link_type &&
1157
lnk->server == NULL) {
1158
lnk->timestamp = la->timeStamp;
1163
/* Search for partially specified links. */
1164
if (lnk == NULL && replace_partial_links) {
1165
if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
1166
lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0,
1169
lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port,
1170
dst_port, link_type, 0);
1173
(dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
1174
lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0,
1179
src_addr, dst_addr, lnk->alias_addr,
1180
src_port, dst_port, lnk->alias_port,
1187
static struct alias_link *
1188
FindLinkOut(struct libalias *la, struct in_addr src_addr,
1189
struct in_addr dst_addr,
1193
int replace_partial_links)
1195
struct alias_link *lnk;
1197
LIBALIAS_LOCK_ASSERT(la);
1198
lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port,
1199
link_type, replace_partial_links);
1203
* The following allows permanent links to be specified as
1204
* using the default source address (i.e. device interface
1205
* address) without knowing in advance what that address
1208
if (la->aliasAddress.s_addr != INADDR_ANY &&
1209
src_addr.s_addr == la->aliasAddress.s_addr) {
1210
lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port,
1211
link_type, replace_partial_links);
1218
static struct alias_link *
1219
_FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1220
struct in_addr alias_addr,
1224
int replace_partial_links)
1228
struct alias_link *lnk;
1229
struct alias_link *lnk_fully_specified;
1230
struct alias_link *lnk_unknown_all;
1231
struct alias_link *lnk_unknown_dst_addr;
1232
struct alias_link *lnk_unknown_dst_port;
1234
LIBALIAS_LOCK_ASSERT(la);
1235
/* Initialize pointers */
1236
lnk_fully_specified = NULL;
1237
lnk_unknown_all = NULL;
1238
lnk_unknown_dst_addr = NULL;
1239
lnk_unknown_dst_port = NULL;
1241
/* If either the dest addr or port is unknown, the search
1242
loop will have to know about this. */
1245
if (dst_addr.s_addr == INADDR_ANY)
1246
flags_in |= LINK_UNKNOWN_DEST_ADDR;
1248
flags_in |= LINK_UNKNOWN_DEST_PORT;
1251
start_point = StartPointIn(alias_addr, alias_port, link_type);
1252
LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) {
1255
flags = flags_in | lnk->flags;
1256
if (!(flags & LINK_PARTIALLY_SPECIFIED)) {
1257
if (lnk->alias_addr.s_addr == alias_addr.s_addr
1258
&& lnk->alias_port == alias_port
1259
&& lnk->dst_addr.s_addr == dst_addr.s_addr
1260
&& lnk->dst_port == dst_port
1261
&& lnk->link_type == link_type) {
1262
lnk_fully_specified = lnk;
1265
} else if ((flags & LINK_UNKNOWN_DEST_ADDR)
1266
&& (flags & LINK_UNKNOWN_DEST_PORT)) {
1267
if (lnk->alias_addr.s_addr == alias_addr.s_addr
1268
&& lnk->alias_port == alias_port
1269
&& lnk->link_type == link_type) {
1270
if (lnk_unknown_all == NULL)
1271
lnk_unknown_all = lnk;
1273
} else if (flags & LINK_UNKNOWN_DEST_ADDR) {
1274
if (lnk->alias_addr.s_addr == alias_addr.s_addr
1275
&& lnk->alias_port == alias_port
1276
&& lnk->link_type == link_type
1277
&& lnk->dst_port == dst_port) {
1278
if (lnk_unknown_dst_addr == NULL)
1279
lnk_unknown_dst_addr = lnk;
1281
} else if (flags & LINK_UNKNOWN_DEST_PORT) {
1282
if (lnk->alias_addr.s_addr == alias_addr.s_addr
1283
&& lnk->alias_port == alias_port
1284
&& lnk->link_type == link_type
1285
&& lnk->dst_addr.s_addr == dst_addr.s_addr) {
1286
if (lnk_unknown_dst_port == NULL)
1287
lnk_unknown_dst_port = lnk;
1294
if (lnk_fully_specified != NULL) {
1295
lnk_fully_specified->timestamp = la->timeStamp;
1296
lnk = lnk_fully_specified;
1297
} else if (lnk_unknown_dst_port != NULL)
1298
lnk = lnk_unknown_dst_port;
1299
else if (lnk_unknown_dst_addr != NULL)
1300
lnk = lnk_unknown_dst_addr;
1301
else if (lnk_unknown_all != NULL)
1302
lnk = lnk_unknown_all;
1306
if (replace_partial_links &&
1307
(lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) {
1308
struct in_addr src_addr;
1311
if (lnk->server != NULL) { /* LSNAT link */
1312
src_addr = lnk->server->addr;
1313
src_port = lnk->server->port;
1314
lnk->server = lnk->server->next;
1316
src_addr = lnk->src_addr;
1317
src_port = lnk->src_port;
1321
src_addr, dst_addr, alias_addr,
1322
src_port, dst_port, alias_port,
1328
static struct alias_link *
1329
FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1330
struct in_addr alias_addr,
1334
int replace_partial_links)
1336
struct alias_link *lnk;
1338
LIBALIAS_LOCK_ASSERT(la);
1339
lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port,
1340
link_type, replace_partial_links);
1344
* The following allows permanent links to be specified as
1345
* using the default aliasing address (i.e. device
1346
* interface address) without knowing in advance what that
1349
if (la->aliasAddress.s_addr != INADDR_ANY &&
1350
alias_addr.s_addr == la->aliasAddress.s_addr) {
1351
lnk = _FindLinkIn(la, dst_addr, la->nullAddress, dst_port, alias_port,
1352
link_type, replace_partial_links);
1361
/* External routines for finding/adding links
1363
-- "external" means outside alias_db.c, but within alias*.c --
1365
FindIcmpIn(), FindIcmpOut()
1366
FindFragmentIn1(), FindFragmentIn2()
1367
AddFragmentPtrLink(), FindFragmentPtr()
1368
FindProtoIn(), FindProtoOut()
1369
FindUdpTcpIn(), FindUdpTcpOut()
1370
AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1371
FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1372
FindOriginalAddress(), FindAliasAddress()
1374
(prototypes in alias_local.h)
1379
FindIcmpIn(struct libalias *la, struct in_addr dst_addr,
1380
struct in_addr alias_addr,
1384
struct alias_link *lnk;
1386
LIBALIAS_LOCK_ASSERT(la);
1387
lnk = FindLinkIn(la, dst_addr, alias_addr,
1388
NO_DEST_PORT, id_alias,
1390
if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1391
struct in_addr target_addr;
1393
target_addr = FindOriginalAddress(la, alias_addr);
1394
lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1395
id_alias, NO_DEST_PORT, id_alias,
1403
FindIcmpOut(struct libalias *la, struct in_addr src_addr,
1404
struct in_addr dst_addr,
1408
struct alias_link *lnk;
1410
LIBALIAS_LOCK_ASSERT(la);
1411
lnk = FindLinkOut(la, src_addr, dst_addr,
1414
if (lnk == NULL && create) {
1415
struct in_addr alias_addr;
1417
alias_addr = FindAliasAddress(la, src_addr);
1418
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1419
id, NO_DEST_PORT, GET_ALIAS_ID,
1427
FindFragmentIn1(struct libalias *la, struct in_addr dst_addr,
1428
struct in_addr alias_addr,
1431
struct alias_link *lnk;
1433
LIBALIAS_LOCK_ASSERT(la);
1434
lnk = FindLinkIn(la, dst_addr, alias_addr,
1435
NO_DEST_PORT, ip_id,
1436
LINK_FRAGMENT_ID, 0);
1439
lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr,
1440
NO_SRC_PORT, NO_DEST_PORT, ip_id,
1448
FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if
1450
struct in_addr alias_addr, /* is not found. */
1454
LIBALIAS_LOCK_ASSERT(la);
1455
return FindLinkIn(la, dst_addr, alias_addr,
1456
NO_DEST_PORT, ip_id,
1457
LINK_FRAGMENT_ID, 0);
1462
AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr,
1466
LIBALIAS_LOCK_ASSERT(la);
1467
return AddLink(la, la->nullAddress, dst_addr, la->nullAddress,
1468
NO_SRC_PORT, NO_DEST_PORT, ip_id,
1474
FindFragmentPtr(struct libalias *la, struct in_addr dst_addr,
1478
LIBALIAS_LOCK_ASSERT(la);
1479
return FindLinkIn(la, dst_addr, la->nullAddress,
1480
NO_DEST_PORT, ip_id,
1481
LINK_FRAGMENT_PTR, 0);
1486
FindProtoIn(struct libalias *la, struct in_addr dst_addr,
1487
struct in_addr alias_addr,
1490
struct alias_link *lnk;
1492
LIBALIAS_LOCK_ASSERT(la);
1493
lnk = FindLinkIn(la, dst_addr, alias_addr,
1497
if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1498
struct in_addr target_addr;
1500
target_addr = FindOriginalAddress(la, alias_addr);
1501
lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1502
NO_SRC_PORT, NO_DEST_PORT, 0,
1510
FindProtoOut(struct libalias *la, struct in_addr src_addr,
1511
struct in_addr dst_addr,
1514
struct alias_link *lnk;
1516
LIBALIAS_LOCK_ASSERT(la);
1517
lnk = FindLinkOut(la, src_addr, dst_addr,
1518
NO_SRC_PORT, NO_DEST_PORT,
1522
struct in_addr alias_addr;
1524
alias_addr = FindAliasAddress(la, src_addr);
1525
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1526
NO_SRC_PORT, NO_DEST_PORT, 0,
1534
FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr,
1535
struct in_addr alias_addr,
1542
struct alias_link *lnk;
1544
LIBALIAS_LOCK_ASSERT(la);
1547
link_type = LINK_UDP;
1550
link_type = LINK_TCP;
1557
lnk = FindLinkIn(la, dst_addr, alias_addr,
1558
dst_port, alias_port,
1561
if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1562
struct in_addr target_addr;
1564
target_addr = FindOriginalAddress(la, alias_addr);
1565
lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1566
alias_port, dst_port, alias_port,
1574
FindUdpTcpOut(struct libalias *la, struct in_addr src_addr,
1575
struct in_addr dst_addr,
1582
struct alias_link *lnk;
1584
LIBALIAS_LOCK_ASSERT(la);
1587
link_type = LINK_UDP;
1590
link_type = LINK_TCP;
1597
lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create);
1599
if (lnk == NULL && create) {
1600
struct in_addr alias_addr;
1602
alias_addr = FindAliasAddress(la, src_addr);
1603
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1604
src_port, dst_port, GET_ALIAS_PORT,
1612
AddPptp(struct libalias *la, struct in_addr src_addr,
1613
struct in_addr dst_addr,
1614
struct in_addr alias_addr,
1615
u_int16_t src_call_id)
1617
struct alias_link *lnk;
1619
LIBALIAS_LOCK_ASSERT(la);
1620
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1621
src_call_id, 0, GET_ALIAS_PORT,
1629
FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr,
1630
struct in_addr dst_addr,
1631
u_int16_t src_call_id)
1634
struct alias_link *lnk;
1636
LIBALIAS_LOCK_ASSERT(la);
1637
i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1638
LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1639
if (lnk->link_type == LINK_PPTP &&
1640
lnk->src_addr.s_addr == src_addr.s_addr &&
1641
lnk->dst_addr.s_addr == dst_addr.s_addr &&
1642
lnk->src_port == src_call_id)
1650
FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr,
1651
struct in_addr dst_addr,
1652
u_int16_t dst_call_id)
1655
struct alias_link *lnk;
1657
LIBALIAS_LOCK_ASSERT(la);
1658
i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
1659
LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
1660
if (lnk->link_type == LINK_PPTP &&
1661
lnk->src_addr.s_addr == src_addr.s_addr &&
1662
lnk->dst_addr.s_addr == dst_addr.s_addr &&
1663
lnk->dst_port == dst_call_id)
1671
FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr,
1672
struct in_addr alias_addr,
1673
u_int16_t dst_call_id)
1676
struct alias_link *lnk;
1678
LIBALIAS_LOCK_ASSERT(la);
1679
i = StartPointIn(alias_addr, 0, LINK_PPTP);
1680
LIST_FOREACH(lnk, &la->linkTableIn[i], list_in)
1681
if (lnk->link_type == LINK_PPTP &&
1682
lnk->dst_addr.s_addr == dst_addr.s_addr &&
1683
lnk->alias_addr.s_addr == alias_addr.s_addr &&
1684
lnk->dst_port == dst_call_id)
1692
FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr,
1693
struct in_addr alias_addr,
1694
u_int16_t alias_call_id)
1696
struct alias_link *lnk;
1698
LIBALIAS_LOCK_ASSERT(la);
1699
lnk = FindLinkIn(la, dst_addr, alias_addr,
1700
0 /* any */ , alias_call_id,
1709
FindRtspOut(struct libalias *la, struct in_addr src_addr,
1710
struct in_addr dst_addr,
1716
struct alias_link *lnk;
1718
LIBALIAS_LOCK_ASSERT(la);
1721
link_type = LINK_UDP;
1724
link_type = LINK_TCP;
1731
lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1);
1734
struct in_addr alias_addr;
1736
alias_addr = FindAliasAddress(la, src_addr);
1737
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1738
src_port, 0, alias_port,
1746
FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
1748
struct alias_link *lnk;
1750
LIBALIAS_LOCK_ASSERT(la);
1751
lnk = FindLinkIn(la, la->nullAddress, alias_addr,
1752
0, 0, LINK_ADDR, 0);
1754
la->newDefaultLink = 1;
1755
if (la->targetAddress.s_addr == INADDR_ANY)
1756
return (alias_addr);
1757
else if (la->targetAddress.s_addr == INADDR_NONE)
1758
return (la->aliasAddress.s_addr != INADDR_ANY) ?
1759
la->aliasAddress : alias_addr;
1761
return (la->targetAddress);
1763
if (lnk->server != NULL) { /* LSNAT link */
1764
struct in_addr src_addr;
1766
src_addr = lnk->server->addr;
1767
lnk->server = lnk->server->next;
1769
} else if (lnk->src_addr.s_addr == INADDR_ANY)
1770
return (la->aliasAddress.s_addr != INADDR_ANY) ?
1771
la->aliasAddress : alias_addr;
1773
return (lnk->src_addr);
1779
FindAliasAddress(struct libalias *la, struct in_addr original_addr)
1781
struct alias_link *lnk;
1783
LIBALIAS_LOCK_ASSERT(la);
1784
lnk = FindLinkOut(la, original_addr, la->nullAddress,
1785
0, 0, LINK_ADDR, 0);
1787
return (la->aliasAddress.s_addr != INADDR_ANY) ?
1788
la->aliasAddress : original_addr;
1790
if (lnk->alias_addr.s_addr == INADDR_ANY)
1791
return (la->aliasAddress.s_addr != INADDR_ANY) ?
1792
la->aliasAddress : original_addr;
1794
return (lnk->alias_addr);
1799
/* External routines for getting or changing link data
1800
(external to alias_db.c, but internal to alias*.c)
1802
SetFragmentData(), GetFragmentData()
1803
SetFragmentPtr(), GetFragmentPtr()
1804
SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1805
GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1806
GetOriginalPort(), GetAliasPort()
1807
SetAckModified(), GetAckModified()
1808
GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1809
SetProtocolFlags(), GetProtocolFlags()
1815
SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
1817
lnk->data.frag_addr = src_addr;
1822
GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
1824
*src_addr = lnk->data.frag_addr;
1829
SetFragmentPtr(struct alias_link *lnk, char *fptr)
1831
lnk->data.frag_ptr = fptr;
1836
GetFragmentPtr(struct alias_link *lnk, char **fptr)
1838
*fptr = lnk->data.frag_ptr;
1843
SetStateIn(struct alias_link *lnk, int state)
1845
/* TCP input state */
1847
case ALIAS_TCP_STATE_DISCONNECTED:
1848
if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED)
1849
lnk->expire_time = TCP_EXPIRE_DEAD;
1851
lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1853
case ALIAS_TCP_STATE_CONNECTED:
1854
if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED)
1855
lnk->expire_time = TCP_EXPIRE_CONNECTED;
1859
panic("libalias:SetStateIn() unknown state");
1864
lnk->data.tcp->state.in = state;
1869
SetStateOut(struct alias_link *lnk, int state)
1871
/* TCP output state */
1873
case ALIAS_TCP_STATE_DISCONNECTED:
1874
if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED)
1875
lnk->expire_time = TCP_EXPIRE_DEAD;
1877
lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1879
case ALIAS_TCP_STATE_CONNECTED:
1880
if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED)
1881
lnk->expire_time = TCP_EXPIRE_CONNECTED;
1885
panic("libalias:SetStateOut() unknown state");
1890
lnk->data.tcp->state.out = state;
1895
GetStateIn(struct alias_link *lnk)
1897
/* TCP input state */
1898
return (lnk->data.tcp->state.in);
1903
GetStateOut(struct alias_link *lnk)
1905
/* TCP output state */
1906
return (lnk->data.tcp->state.out);
1911
GetOriginalAddress(struct alias_link *lnk)
1913
if (lnk->src_addr.s_addr == INADDR_ANY)
1914
return (lnk->la->aliasAddress);
1916
return (lnk->src_addr);
1921
GetDestAddress(struct alias_link *lnk)
1923
return (lnk->dst_addr);
1928
GetAliasAddress(struct alias_link *lnk)
1930
if (lnk->alias_addr.s_addr == INADDR_ANY)
1931
return (lnk->la->aliasAddress);
1933
return (lnk->alias_addr);
1938
GetDefaultAliasAddress(struct libalias *la)
1941
LIBALIAS_LOCK_ASSERT(la);
1942
return (la->aliasAddress);
1947
SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
1950
LIBALIAS_LOCK_ASSERT(la);
1951
la->aliasAddress = alias_addr;
1956
GetOriginalPort(struct alias_link *lnk)
1958
return (lnk->src_port);
1963
GetAliasPort(struct alias_link *lnk)
1965
return (lnk->alias_port);
1970
GetDestPort(struct alias_link *lnk)
1972
return (lnk->dst_port);
1978
SetAckModified(struct alias_link *lnk)
1980
/* Indicate that ACK numbers have been modified in a TCP connection */
1981
lnk->data.tcp->state.ack_modified = 1;
1986
GetProxyAddress(struct alias_link *lnk)
1988
return (lnk->proxy_addr);
1993
SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
1995
lnk->proxy_addr = addr;
2000
GetProxyPort(struct alias_link *lnk)
2002
return (lnk->proxy_port);
2007
SetProxyPort(struct alias_link *lnk, u_short port)
2009
lnk->proxy_port = port;
2014
GetAckModified(struct alias_link *lnk)
2016
/* See if ACK numbers have been modified */
2017
return (lnk->data.tcp->state.ack_modified);
2022
GetDeltaAckIn(struct ip *pip, struct alias_link *lnk)
2025
Find out how much the ACK number has been altered for an incoming
2026
TCP packet. To do this, a circular list of ACK numbers where the TCP
2027
packet size was altered is searched.
2032
int delta, ack_diff_min;
2040
for (i = 0; i < N_LINK_TCP_DATA; i++) {
2041
struct ack_data_record x;
2043
x = lnk->data.tcp->ack[i];
2044
if (x.active == 1) {
2047
ack_diff = SeqDiff(x.ack_new, ack);
2048
if (ack_diff >= 0) {
2049
if (ack_diff_min >= 0) {
2050
if (ack_diff < ack_diff_min) {
2052
ack_diff_min = ack_diff;
2056
ack_diff_min = ack_diff;
2066
GetDeltaSeqOut(struct ip *pip, struct alias_link *lnk)
2069
Find out how much the sequence number has been altered for an outgoing
2070
TCP packet. To do this, a circular list of ACK numbers where the TCP
2071
packet size was altered is searched.
2076
int delta, seq_diff_min;
2084
for (i = 0; i < N_LINK_TCP_DATA; i++) {
2085
struct ack_data_record x;
2087
x = lnk->data.tcp->ack[i];
2088
if (x.active == 1) {
2091
seq_diff = SeqDiff(x.ack_old, seq);
2092
if (seq_diff >= 0) {
2093
if (seq_diff_min >= 0) {
2094
if (seq_diff < seq_diff_min) {
2096
seq_diff_min = seq_diff;
2100
seq_diff_min = seq_diff;
2110
AddSeq(struct ip *pip, struct alias_link *lnk, int delta)
2113
When a TCP packet has been altered in length, save this
2114
information in a circular list. If enough packets have
2115
been altered, then this list will begin to overwrite itself.
2119
struct ack_data_record x;
2120
int hlen, tlen, dlen;
2125
hlen = (pip->ip_hl + tc->th_off) << 2;
2126
tlen = ntohs(pip->ip_len);
2129
x.ack_old = htonl(ntohl(tc->th_seq) + dlen);
2130
x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta);
2134
i = lnk->data.tcp->state.index;
2135
lnk->data.tcp->ack[i] = x;
2138
if (i == N_LINK_TCP_DATA)
2139
lnk->data.tcp->state.index = 0;
2141
lnk->data.tcp->state.index = i;
2145
SetExpire(struct alias_link *lnk, int expire)
2148
lnk->flags &= ~LINK_PERMANENT;
2150
} else if (expire == -1) {
2151
lnk->flags |= LINK_PERMANENT;
2152
} else if (expire > 0) {
2153
lnk->expire_time = expire;
2155
#ifdef LIBALIAS_DEBUG
2156
fprintf(stderr, "PacketAlias/SetExpire(): ");
2157
fprintf(stderr, "error in expire parameter\n");
2163
ClearCheckNewLink(struct libalias *la)
2166
LIBALIAS_LOCK_ASSERT(la);
2167
la->newDefaultLink = 0;
2171
SetProtocolFlags(struct alias_link *lnk, int pflags)
2174
lnk->pflags = pflags;;
2178
GetProtocolFlags(struct alias_link *lnk)
2181
return (lnk->pflags);
2185
SetDestCallId(struct alias_link *lnk, u_int16_t cid)
2187
struct libalias *la = lnk->la;
2189
LIBALIAS_LOCK_ASSERT(la);
2190
la->deleteAllLinks = 1;
2191
ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr,
2192
lnk->src_port, cid, lnk->alias_port, lnk->link_type);
2193
la->deleteAllLinks = 0;
2197
/* Miscellaneous Functions
2200
InitPacketAliasLog()
2201
UninitPacketAliasLog()
2205
Whenever an outgoing or incoming packet is handled, HouseKeeping()
2206
is called to find and remove timed-out aliasing links. Logic exists
2207
to sweep through the entire table and linked list structure
2210
(prototype in alias_local.h)
2214
HouseKeeping(struct libalias *la)
2224
LIBALIAS_LOCK_ASSERT(la);
2226
* Save system time (seconds) in global variable timeStamp for use
2227
* by other functions. This is done so as not to unnecessarily
2228
* waste timeline by making system calls.
2232
la->timeStamp = time_uptime;
2234
gettimeofday(&tv, &tz);
2235
la->timeStamp = tv.tv_sec;
2238
la->timeStamp = la->curtime / 1000; /* NB: la->pData->curtime (msec) */
2241
/* Compute number of spokes (output table link chains) to cover */
2242
n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime);
2243
n /= ALIAS_CLEANUP_INTERVAL_SECS;
2245
/* Handle different cases */
2247
if (n > ALIAS_CLEANUP_MAX_SPOKES)
2248
n = ALIAS_CLEANUP_MAX_SPOKES;
2249
la->lastCleanupTime = la->timeStamp;
2250
for (i = 0; i < n; i++)
2251
IncrementalCleanup(la);
2253
#ifdef LIBALIAS_DEBUG
2254
fprintf(stderr, "PacketAlias/HouseKeeping(): ");
2255
fprintf(stderr, "something unexpected in time values\n");
2257
la->lastCleanupTime = la->timeStamp;
2261
/* Init the log file and enable logging */
2263
InitPacketAliasLog(struct libalias *la)
2266
LIBALIAS_LOCK_ASSERT(la);
2267
if (~la->packetAliasMode & PKT_ALIAS_LOG) {
2270
if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
2273
if ((la->logDesc = fopen("/var/log/alias.log", "w")))
2274
fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2277
return (ENOMEM); /* log initialization failed */
2279
Log2(("NAT: PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n"));
2280
la->logDesc = (void *)1; /* XXX: in vbox we don't use this param */
2282
la->packetAliasMode |= PKT_ALIAS_LOG;
2288
/* Close the log-file and disable logging. */
2290
UninitPacketAliasLog(struct libalias *la)
2293
LIBALIAS_LOCK_ASSERT(la);
2299
fclose(la->logDesc);
2304
la->packetAliasMode &= ~PKT_ALIAS_LOG;
2307
/* Outside world interfaces
2309
-- "outside world" means other than alias*.c routines --
2311
PacketAliasRedirectPort()
2312
PacketAliasAddServer()
2313
PacketAliasRedirectProto()
2314
PacketAliasRedirectAddr()
2315
PacketAliasRedirectDynamic()
2316
PacketAliasRedirectDelete()
2317
PacketAliasSetAddress()
2320
PacketAliasSetMode()
2322
(prototypes in alias.h)
2325
/* Redirection from a specific public addr:port to a
2326
private addr:port */
2328
LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port,
2329
struct in_addr dst_addr, u_short dst_port,
2330
struct in_addr alias_addr, u_short alias_port,
2334
struct alias_link *lnk;
2339
link_type = LINK_UDP;
2342
link_type = LINK_TCP;
2345
#ifdef LIBALIAS_DEBUG
2346
fprintf(stderr, "PacketAliasRedirectPort(): ");
2347
fprintf(stderr, "only TCP and UDP protocols allowed\n");
2353
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2354
src_port, dst_port, alias_port,
2358
lnk->flags |= LINK_PERMANENT;
2360
#ifdef LIBALIAS_DEBUG
2362
fprintf(stderr, "PacketAliasRedirectPort(): "
2363
"call to AddLink() failed\n");
2368
LIBALIAS_UNLOCK(la);
2372
/* Add server to the pool of servers */
2374
LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
2376
struct server *server;
2382
server = malloc(sizeof(struct server));
2384
if (server != NULL) {
2385
struct server *head;
2387
server->addr = addr;
2388
server->port = port;
2392
server->next = server;
2396
for (s = head; s->next != head; s = s->next);
2398
server->next = head;
2400
lnk->server = server;
2405
LIBALIAS_UNLOCK(la);
2409
/* Redirect packets of a given IP protocol from a specific
2410
public address to a private address */
2412
LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr,
2413
struct in_addr dst_addr,
2414
struct in_addr alias_addr,
2417
struct alias_link *lnk;
2420
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2421
NO_SRC_PORT, NO_DEST_PORT, 0,
2425
lnk->flags |= LINK_PERMANENT;
2427
#ifdef LIBALIAS_DEBUG
2429
fprintf(stderr, "PacketAliasRedirectProto(): "
2430
"call to AddLink() failed\n");
2434
LIBALIAS_UNLOCK(la);
2438
/* Static address translation */
2440
LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr,
2441
struct in_addr alias_addr)
2443
struct alias_link *lnk;
2446
lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
2451
lnk->flags |= LINK_PERMANENT;
2453
#ifdef LIBALIAS_DEBUG
2455
fprintf(stderr, "PacketAliasRedirectAddr(): "
2456
"call to AddLink() failed\n");
2460
LIBALIAS_UNLOCK(la);
2465
/* Mark the aliasing link dynamic */
2467
LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
2474
if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
2477
lnk->flags &= ~LINK_PERMANENT;
2480
LIBALIAS_UNLOCK(la);
2486
LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
2488
/* This is a dangerous function to put in the API,
2489
because an invalid pointer can crash the program. */
2492
la->deleteAllLinks = 1;
2494
la->deleteAllLinks = 0;
2495
LIBALIAS_UNLOCK(la);
2500
LibAliasSetAddress(struct libalias *la, struct in_addr addr)
2504
if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2505
&& la->aliasAddress.s_addr != addr.s_addr)
2506
CleanupAliasData(la);
2508
la->aliasAddress = addr;
2509
LIBALIAS_UNLOCK(la);
2514
LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2518
la->targetAddress = target_addr;
2519
LIBALIAS_UNLOCK(la);
2527
while (!LIST_EMPTY(&instancehead))
2528
LibAliasUninit(LIST_FIRST(&instancehead));
2534
LibAliasInit(struct libalias *la)
2536
LibAliasInit(PNATState pData, struct libalias *la)
2548
la = calloc(sizeof *la, 1);
2553
#ifndef _KERNEL /* kernel cleans up on module unload */
2554
if (LIST_EMPTY(&instancehead))
2558
LIST_INSERT_HEAD(&instancehead, la, instancelist);
2562
la->timeStamp = time_uptime;
2563
la->lastCleanupTime = time_uptime;
2565
gettimeofday(&tv, &tz);
2566
la->timeStamp = tv.tv_sec;
2567
la->lastCleanupTime = tv.tv_sec;
2571
la->timeStamp = la->curtime / 1000; /* NB: la->pData->curtime (msec) */
2572
la->lastCleanupTime = la->timeStamp;
2575
for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
2576
LIST_INIT(&la->linkTableOut[i]);
2577
for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
2578
LIST_INIT(&la->linkTableIn[i]);
2579
LIBALIAS_LOCK_INIT(la);
2583
la->deleteAllLinks = 1;
2584
CleanupAliasData(la);
2585
la->deleteAllLinks = 0;
2588
la->aliasAddress.s_addr = INADDR_ANY;
2589
la->targetAddress.s_addr = INADDR_ANY;
2591
la->icmpLinkCount = 0;
2592
la->udpLinkCount = 0;
2593
la->tcpLinkCount = 0;
2594
la->pptpLinkCount = 0;
2595
la->protoLinkCount = 0;
2596
la->fragmentIdLinkCount = 0;
2597
la->fragmentPtrLinkCount = 0;
2600
la->cleanupIndex = 0;
2602
la->packetAliasMode = PKT_ALIAS_SAME_PORTS
2603
#ifndef NO_USE_SOCKETS
2604
| PKT_ALIAS_USE_SOCKETS
2606
| PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2608
la->fireWallFD = -1;
2611
LibAliasRefreshModules();
2613
LIBALIAS_UNLOCK(la);
2618
LibAliasUninit(struct libalias *la)
2622
la->deleteAllLinks = 1;
2623
CleanupAliasData(la);
2624
la->deleteAllLinks = 0;
2625
UninitPacketAliasLog(la);
2629
LIST_REMOVE(la, instancelist);
2630
LIBALIAS_UNLOCK(la);
2631
LIBALIAS_LOCK_DESTROY(la);
2635
/* Change mode for some operations */
2638
struct libalias *la,
2639
unsigned int flags, /* Which state to bring flags to */
2640
unsigned int mask /* Mask of which flags to affect (use 0 to
2641
* do a probe for flag values) */
2647
/* Enable logging? */
2648
if (flags & mask & PKT_ALIAS_LOG) {
2650
if (InitPacketAliasLog(la) == ENOMEM)
2653
/* _Disable_ logging? */
2654
if (~flags & mask & PKT_ALIAS_LOG) {
2655
UninitPacketAliasLog(la);
2658
/* Start punching holes in the firewall? */
2659
if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2662
/* Stop punching holes in the firewall? */
2663
if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2668
/* Other flags can be set/cleared without special action */
2669
la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2670
res = la->packetAliasMode;
2672
LIBALIAS_UNLOCK(la);
2678
LibAliasCheckNewLink(struct libalias *la)
2683
res = la->newDefaultLink;
2684
LIBALIAS_UNLOCK(la);
2692
Code to support firewall punching. This shouldn't really be in this
2693
file, but making variables global is evil too.
2696
/* Firewall include files */
2698
#include <netinet/ip_fw.h>
2703
* helper function, updates the pointer to cmd with the length
2704
* of the current command, and also cleans up the first word of
2705
* the new command in case it has been clobbered before.
2708
next_cmd(ipfw_insn * cmd)
2711
bzero(cmd, sizeof(*cmd));
2716
* A function to fill simple commands of size 1.
2717
* Existing flags are preserved.
2720
fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2721
int flags, u_int16_t arg)
2723
cmd->opcode = opcode;
2724
cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2726
return next_cmd(cmd);
2730
fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2732
ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1;
2734
cmd->addr.s_addr = addr;
2735
return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2739
fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2741
ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1;
2743
cmd->ports[0] = cmd->ports[1] = port;
2744
return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2748
fill_rule(void *buf, int bufsize, int rulenum,
2749
enum ipfw_opcodes action, int proto,
2750
struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
2752
struct ip_fw *rule = (struct ip_fw *)buf;
2753
ipfw_insn *cmd = (ipfw_insn *) rule->cmd;
2755
bzero(buf, bufsize);
2756
rule->rulenum = rulenum;
2758
cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto);
2759
cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr);
2760
cmd = fill_one_port(cmd, O_IP_SRCPORT, sp);
2761
cmd = fill_ip(cmd, O_IP_DST, da.s_addr);
2762
cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
2764
rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2765
cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
2767
rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2769
return ((char *)cmd - (char *)buf);
2772
static void ClearAllFWHoles(struct libalias *la);
2775
#define fw_setfield(la, field, num) \
2777
(field)[(num) - la->fireWallBaseNum] = 1; \
2778
} /*lint -save -e717 */ while(0)/* lint -restore */
2780
#define fw_clrfield(la, field, num) \
2782
(field)[(num) - la->fireWallBaseNum] = 0; \
2783
} /*lint -save -e717 */ while(0)/* lint -restore */
2785
#define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2788
InitPunchFW(struct libalias *la)
2791
LIBALIAS_LOCK_ASSERT(la);
2792
la->fireWallField = malloc(la->fireWallNumNums);
2793
if (la->fireWallField) {
2794
memset(la->fireWallField, 0, la->fireWallNumNums);
2795
if (la->fireWallFD < 0) {
2796
la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2798
ClearAllFWHoles(la);
2799
la->fireWallActiveNum = la->fireWallBaseNum;
2804
UninitPunchFW(struct libalias *la)
2807
LIBALIAS_LOCK_ASSERT(la);
2808
ClearAllFWHoles(la);
2809
if (la->fireWallFD >= 0)
2810
closesocket(la->fireWallFD);
2811
la->fireWallFD = -1;
2812
if (la->fireWallField)
2813
free(la->fireWallField);
2814
la->fireWallField = NULL;
2815
la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2818
/* Make a certain link go through the firewall */
2820
PunchFWHole(struct alias_link *lnk)
2822
struct libalias *la;
2823
int r; /* Result code */
2824
struct ip_fw rule; /* On-the-fly built rule */
2825
int fwhole; /* Where to punch hole */
2827
LIBALIAS_LOCK_ASSERT(la);
2830
/* Don't do anything unless we are asked to */
2831
if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2832
la->fireWallFD < 0 ||
2833
lnk->link_type != LINK_TCP)
2836
memset(&rule, 0, sizeof rule);
2840
/* Find empty slot */
2841
for (fwhole = la->fireWallActiveNum;
2842
fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2843
fw_tstfield(la, la->fireWallField, fwhole);
2845
if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2846
for (fwhole = la->fireWallBaseNum;
2847
fwhole < la->fireWallActiveNum &&
2848
fw_tstfield(la, la->fireWallField, fwhole);
2850
if (fwhole == la->fireWallActiveNum) {
2851
/* No rule point empty - we can't punch more holes. */
2852
la->fireWallActiveNum = la->fireWallBaseNum;
2853
#ifdef LIBALIAS_DEBUG
2854
fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2859
/* Start next search at next position */
2860
la->fireWallActiveNum = fwhole + 1;
2863
* generate two rules of the form
2865
* add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2866
* accept tcp from DAddr DPort to OAddr OPort
2868
if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2869
u_int32_t rulebuf[255];
2872
i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2873
O_ACCEPT, IPPROTO_TCP,
2874
GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
2875
GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
2876
r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2878
err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2880
i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2881
O_ACCEPT, IPPROTO_TCP,
2882
GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
2883
GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
2884
r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2886
err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2889
/* Indicate hole applied */
2890
lnk->data.tcp->fwhole = fwhole;
2891
fw_setfield(la, la->fireWallField, fwhole);
2894
/* Remove a hole in a firewall associated with a particular alias
2895
lnk. Calling this too often is harmless. */
2897
ClearFWHole(struct alias_link *lnk)
2899
struct libalias *la;
2901
LIBALIAS_LOCK_ASSERT(la);
2903
if (lnk->link_type == LINK_TCP) {
2904
int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall
2911
memset(&rule, 0, sizeof rule); /* useless for ipfw2 */
2912
while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL,
2913
&fwhole, sizeof fwhole));
2914
fw_clrfield(la, la->fireWallField, fwhole);
2915
lnk->data.tcp->fwhole = -1;
2919
/* Clear out the entire range dedicated to firewall holes. */
2921
ClearAllFWHoles(struct libalias *la)
2923
struct ip_fw rule; /* On-the-fly built rule */
2926
LIBALIAS_LOCK_ASSERT(la);
2927
if (la->fireWallFD < 0)
2930
memset(&rule, 0, sizeof rule);
2931
for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2934
while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2936
/* XXX: third arg correct here ? /phk */
2937
memset(la->fireWallField, 0, la->fireWallNumNums);
2943
LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2953
la->fireWallBaseNum = base;
2954
la->fireWallNumNums = num;
2956
LIBALIAS_UNLOCK(la);
2960
LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2964
la->skinnyPort = port;
2965
LIBALIAS_UNLOCK(la);