VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/libalias/alias_db.c

Last change on this file was 63014, checked in by vboxsync, 8 years ago

slirp: warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 76.9 KB
Line 
1/*-
2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 */
26
27#ifndef VBOX
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 $");
30#endif
31
32/*
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.
36
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
43 fragments.
44
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.
50
51
52 Initial version: August, 1996 (cjm)
53
54 Version 1.4: September 16, 1996 (cjm)
55 Facility for handling incoming links added.
56
57 Version 1.6: September 18, 1996 (cjm)
58 ICMP data handling simplified.
59
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.
68
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)
73
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)
78
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)
83
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)
87
88 Removed K&R style function headers
89 and general cleanup. (ee)
90
91 Added packetAliasMode to replace compiler #defines's (ee)
92
93 Allocates sockets for partially specified
94 ports if ALIAS_USE_SOCKETS defined. (cjm)
95
96 Version 2.0: March, 1997
97 SetAliasAddress() will now clean up alias links
98 if the aliasing address is changed. (cjm)
99
100 PacketAliasPermanentLink() function added to support permanent
101 links. (J. Fortes suggested the need for this.)
102 Examples:
103
104 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
105
106 (192.168.0.2, port 21) <-> alias port 3604, known dest addr
107 unknown dest port
108
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)
113
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)
117
118 SetExpire() function added. (cjm)
119
120 DeleteLink() no longer frees memory association with a pointer
121 to a fragment (this bug was first recognized by E. Eklund in
122 v1.9).
123
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
127 host address.
128
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.
133
134 Version 3.2: July, 2000 (salander and satoh)
135 Added FindNewPortGroup to get contiguous range of port values.
136
137 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
138 link but not actually add one.
139
140 Added FindRtspOut, which is closely derived from FindUdpTcpOut,
141 except that the alias port (from FindNewPortGroup) is provided
142 as input.
143
144 See HISTORY file for additional revisions.
145*/
146
147#ifndef VBOX
148#ifdef _KERNEL
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>
154#else
155#include <stdarg.h>
156#include <stdlib.h>
157#include <stdio.h>
158#include <sys/errno.h>
159#include <sys/time.h>
160#include <unistd.h>
161#endif
162
163#include <sys/socket.h>
164#include <netinet/tcp.h>
165
166#ifdef _KERNEL
167#include <netinet/libalias/alias.h>
168#include <netinet/libalias/alias_local.h>
169#include <netinet/libalias/alias_mod.h>
170#include <net/if.h>
171#else
172#include "alias.h"
173#include "alias_local.h"
174#include "alias_mod.h"
175#endif
176#else /* VBOX */
177# include <iprt/assert.h>
178# include "alias.h"
179# include "alias_local.h"
180# include "alias_mod.h"
181# include <slirp.h>
182#endif /* VBOX */
183
184#ifndef VBOX
185static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
186#endif
187
188
189/*
190 Constants (note: constants are also defined
191 near relevant functions or structs)
192*/
193
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)
198
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
205
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
211#endif
212
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
217#endif
218
219/* When the link isn't yet up */
220#ifndef TCP_EXPIRE_INITIAL
221#define TCP_EXPIRE_INITIAL 300
222#endif
223
224/* When the link is up */
225#ifndef TCP_EXPIRE_CONNECTED
226#define TCP_EXPIRE_CONNECTED 86400
227#endif
228
229
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. */
233
234#define NO_DEST_PORT 1
235#define NO_SRC_PORT 1
236
237
238
239/* Data Structures
240
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.
249
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.
257
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
263 port and link type.
264*/
265
266struct ack_data_record { /* used to save changes to ACK/sequence
267 * numbers */
268 u_long ack_old;
269 u_long ack_new;
270 int delta;
271 int active;
272};
273
274struct 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 */
280 /* been modified */
281};
282
283#define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes
284 * saved for a modified TCP stream */
285struct tcp_dat {
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
289 * hole? */
290};
291
292struct server { /* LSNAT server pool (circular list) */
293 struct in_addr addr;
294 u_short port;
295 struct server *next;
296};
297
298struct alias_link { /* Main data structure */
299 struct libalias *la;
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;
304 u_short src_port;
305 u_short dst_port;
306 u_short alias_port;
307 u_short proxy_port;
308 struct server *server;
309
310 int link_type; /* Type of link: TCP, UDP, ICMP,
311 * proto, frag */
312
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)
321
322 int flags; /* indicates special characteristics */
323 int pflags; /* protocol-specific flags */
324
325/* flag bits */
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 */
330#ifndef VBOX
331# define LINK_UNFIREWALLED 0x08 /* This macro definition isn't used in this revision of libalias */
332
333 int timestamp; /* Time link was last accessed */
334 int expire_time; /* Expire time for link */
335#else /* VBOX */
336 unsigned int timestamp; /* Time link was last accessed */
337 unsigned int expire_time; /* Expire time for link */
338#endif
339
340#ifndef NO_USE_SOCKETS
341 int sockfd; /* socket descriptor */
342#endif
343 LIST_ENTRY (alias_link) list_out; /* Linked list of
344 * pointers for */
345 LIST_ENTRY (alias_link) list_in; /* input and output
346 * lookup tables */
347
348 union { /* Auxiliary data */
349 char *frag_ptr;
350 struct in_addr frag_addr;
351 struct tcp_dat *tcp;
352 } data;
353};
354
355/* Clean up procedure. */
356#ifndef VBOX
357static void finishoff(void);
358#endif
359
360/* Kernel module definition. */
361#ifdef _KERNEL
362MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing");
363
364MODULE_VERSION(libalias, 1);
365
366static int
367alias_mod_handler(module_t mod, int type, void *data)
368{
369 int error;
370
371 switch (type) {
372 case MOD_LOAD:
373 error = 0;
374 handler_chain_init();
375 break;
376 case MOD_QUIESCE:
377 case MOD_UNLOAD:
378 handler_chain_destroy();
379 finishoff();
380 error = 0;
381 break;
382 default:
383 error = EINVAL;
384 }
385
386 return (error);
387}
388
389static moduledata_t alias_mod = {
390 "alias", alias_mod_handler, NULL
391};
392
393DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
394#endif
395
396/* Internal utility routines (used only in alias_db.c)
397
398Lookup table starting points:
399 StartPointIn() -- link table initial search point for
400 incoming packets
401 StartPointOut() -- link table initial search point for
402 outgoing packets
403
404Miscellaneous:
405 SeqDiff() -- difference between two TCP sequences
406 ShowAliasStats() -- send alias statistics to a monitor file
407*/
408
409
410/* Local prototypes */
411static u_int StartPointIn(struct in_addr, u_short, int);
412
413static u_int
414StartPointOut(struct in_addr, struct in_addr,
415 u_short, u_short, int);
416
417static int SeqDiff(u_long, u_long);
418
419#ifndef NO_FW_PUNCH
420/* Firewall control */
421static void InitPunchFW(struct libalias *);
422static void UninitPunchFW(struct libalias *);
423static void ClearFWHole(struct alias_link *);
424
425#endif
426
427/* Log file control */
428static void ShowAliasStats(struct libalias *);
429static int InitPacketAliasLog(struct libalias *);
430static void UninitPacketAliasLog(struct libalias *);
431
432static u_int
433StartPointIn(struct in_addr alias_addr,
434 u_short alias_port,
435 int link_type)
436{
437 u_int n;
438
439 n = alias_addr.s_addr;
440 if (link_type != LINK_PPTP)
441 n += alias_port;
442 n += link_type;
443 return (n % LINK_TABLE_IN_SIZE);
444}
445
446
447static u_int
448StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
449 u_short src_port, u_short dst_port, int link_type)
450{
451 u_int n;
452
453 n = src_addr.s_addr;
454 n += dst_addr.s_addr;
455 if (link_type != LINK_PPTP) {
456 n += src_port;
457 n += dst_port;
458 }
459 n += link_type;
460
461 return (n % LINK_TABLE_OUT_SIZE);
462}
463
464
465static int
466SeqDiff(u_long x, u_long y)
467{
468/* Return the difference between two TCP sequence numbers */
469
470/*
471 This function is encapsulated in case there are any unusual
472 arithmetic conditions that need to be considered.
473*/
474
475 return (ntohl(y) - ntohl(x));
476}
477
478#ifdef _KERNEL
479
480static void
481AliasLog(char *str, const char *format, ...)
482{
483 va_list ap;
484
485 va_start(ap, format);
486 vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
487 va_end(ap);
488}
489#else
490static void
491AliasLog(FILE *stream, const char *format, ...)
492{
493# ifndef VBOX
494 va_list ap;
495
496 va_start(ap, format);
497 vfprintf(stream, format, ap);
498 va_end(ap);
499 fflush(stream);
500# else
501
502 va_list args;
503 char buffer[1024];
504 NOREF(stream);
505 memset(buffer, 0, 1024);
506 va_start(args, format);
507 RTStrPrintfV(buffer, 1024, format, args);
508 va_end(args);
509 /*make it grepable */
510 Log2(("NAT:ALIAS: %s\n", buffer));
511# endif
512}
513#endif
514
515static void
516ShowAliasStats(struct libalias *la)
517{
518
519 LIBALIAS_LOCK_ASSERT(la);
520/* Used for debugging */
521 if (la->logDesc) {
522 int tot = la->icmpLinkCount + la->udpLinkCount +
523 la->tcpLinkCount + la->pptpLinkCount +
524 la->protoLinkCount + la->fragmentIdLinkCount +
525 la->fragmentPtrLinkCount;
526
527 AliasLog(la->logDesc,
528 "icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
529 la->icmpLinkCount,
530 la->udpLinkCount,
531 la->tcpLinkCount,
532 la->pptpLinkCount,
533 la->protoLinkCount,
534 la->fragmentIdLinkCount,
535 la->fragmentPtrLinkCount, tot);
536#ifndef _KERNEL
537 AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
538#endif
539 }
540}
541
542/* Internal routines for finding, deleting and adding links
543
544Port Allocation:
545 GetNewPort() -- find and reserve new alias port number
546 GetSocket() -- try to allocate a socket for a given port
547
548Link 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
552 AddLink() - add link
553 ReLink() - change link
554
555Link search:
556 FindLinkOut() - find link for outgoing packets
557 FindLinkIn() - find link for incoming packets
558
559Port search:
560 FindNewPortGroup() - find an available group of ports
561*/
562
563/* Local prototypes */
564static int GetNewPort(struct libalias *, struct alias_link *, int);
565#ifndef NO_USE_SOCKETS
566static u_short GetSocket(struct libalias *, u_short, int *, int);
567#endif
568static void CleanupAliasData(struct libalias *);
569
570static void IncrementalCleanup(struct libalias *);
571
572static void DeleteLink(struct alias_link *);
573
574static struct alias_link *
575AddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr,
576 u_short, u_short, int, int);
577
578static struct alias_link *
579ReLink(struct alias_link *,
580 struct in_addr, struct in_addr, struct in_addr,
581 u_short, u_short, int, int);
582
583static struct alias_link *
584 FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
585
586static struct alias_link *
587 FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
588
589
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
594
595#define GET_ALIAS_PORT -1
596#define GET_ALIAS_ID GET_ALIAS_PORT
597
598#define FIND_EVEN_ALIAS_BASE 1
599
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). */
604
605static int
606GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
607{
608 int i;
609 int max_trials;
610 u_short port_sys;
611 u_short port_net;
612
613 LIBALIAS_LOCK_ASSERT(la);
614/*
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.
619
620 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
621 selected port number.
622*/
623
624 if (alias_port_param == GET_ALIAS_PORT) {
625 /*
626 * The aliasing port is automatically selected by one of
627 * two methods below:
628 */
629 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
630
631 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
632 /*
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.
637 */
638 port_net = lnk->src_port;
639 port_sys = ntohs(port_net);
640 } else {
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);
645 }
646 } else if (alias_port_param >= 0 && alias_port_param < 0x10000) {
647 lnk->alias_port = (u_short) alias_port_param;
648 return (0);
649 } else {
650#ifdef LIBALIAS_DEBUG
651 fprintf(stderr, "PacketAlias/GetNewPort(): ");
652 fprintf(stderr, "input parameter error\n");
653#endif
654 return (-1);
655 }
656
657
658/* Port number search */
659 for (i = 0; i < max_trials; i++) {
660 int go_ahead;
661 struct alias_link *search_result;
662
663 search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr,
664 lnk->dst_port, port_net,
665 lnk->link_type, 0);
666
667 if (search_result == NULL)
668 go_ahead = 1;
669 else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED)
670 && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
671 go_ahead = 1;
672 else
673 go_ahead = 0;
674
675 if (go_ahead) {
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;
683 return (0);
684 }
685 } else {
686#endif
687 lnk->alias_port = port_net;
688 return (0);
689#ifndef NO_USE_SOCKETS
690 }
691#endif
692 }
693 port_sys = arc4random() & ALIAS_PORT_MASK;
694 port_sys += ALIAS_PORT_BASE;
695 port_net = htons(port_sys);
696 }
697
698#ifdef LIBALIAS_DEBUG
699 fprintf(stderr, "PacketAlias/GetnewPort(): ");
700 fprintf(stderr, "could not find free port\n");
701#endif
702
703 return (-1);
704}
705
706#ifndef NO_USE_SOCKETS
707static u_short
708GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
709{
710 int err;
711 int sock;
712 struct sockaddr_in sock_addr;
713
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);
719 else {
720#ifdef LIBALIAS_DEBUG
721 fprintf(stderr, "PacketAlias/GetSocket(): ");
722 fprintf(stderr, "incorrect link type\n");
723#endif
724 return (0);
725 }
726
727 if (sock < 0) {
728#ifdef LIBALIAS_DEBUG
729 fprintf(stderr, "PacketAlias/GetSocket(): ");
730 fprintf(stderr, "socket() error %d\n", *sockfd);
731#endif
732 return (0);
733 }
734
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;
739#ifdef RT_OS_DARWIN
740 sock_addr.sin_len = sizeof(struct sockaddr_in);
741#endif
742
743
744 err = bind(sock,
745 (struct sockaddr *)&sock_addr,
746 sizeof(sock_addr));
747 if (err == 0) {
748 la->sockCount++;
749 *sockfd = sock;
750 return (1);
751 } else {
752 closesocket(sock);
753 return (0);
754 }
755}
756#endif
757
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). */
763
764int
765FindNewPortGroup(struct libalias *la,
766 struct in_addr dst_addr,
767 struct in_addr alias_addr,
768 u_short src_port,
769 u_short dst_port,
770 u_short port_count,
771 u_char proto,
772 u_char align)
773{
774 int i, j;
775 int max_trials;
776 u_short port_sys;
777 int link_type;
778
779 LIBALIAS_LOCK_ASSERT(la);
780 /*
781 * Get link_type from protocol
782 */
783
784 switch (proto) {
785 case IPPROTO_UDP:
786 link_type = LINK_UDP;
787 break;
788 case IPPROTO_TCP:
789 link_type = LINK_TCP;
790 break;
791 default:
792 return (0);
793 break;
794 }
795
796 /*
797 * The aliasing port is automatically selected by one of two
798 * methods below:
799 */
800 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
801
802 if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
803 /*
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.
807 */
808 port_sys = ntohs(src_port);
809
810 } else {
811
812 /* First trial and all subsequent are random. */
813 if (align == FIND_EVEN_ALIAS_BASE)
814 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
815 else
816 port_sys = arc4random() & ALIAS_PORT_MASK;
817
818 port_sys += ALIAS_PORT_BASE;
819 }
820
821/* Port number search */
822 for (i = 0; i < max_trials; i++) {
823
824 struct alias_link *search_result;
825
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),
829 link_type, 0)))
830 break;
831
832 /* Found a good range, return base */
833 if (j == port_count)
834 return (htons(port_sys));
835
836 /* Find a new base to try */
837 if (align == FIND_EVEN_ALIAS_BASE)
838 port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
839 else
840 port_sys = arc4random() & ALIAS_PORT_MASK;
841
842 port_sys += ALIAS_PORT_BASE;
843 }
844
845#ifdef LIBALIAS_DEBUG
846 fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
847 fprintf(stderr, "could not find free port(s)\n");
848#endif
849
850 return (0);
851}
852
853static void
854CleanupAliasData(struct libalias *la)
855{
856 struct alias_link *lnk;
857 int i;
858
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);
864 DeleteLink(lnk);
865 lnk = link_next;
866 }
867 }
868
869 la->cleanupIndex = 0;
870}
871
872
873static void
874IncrementalCleanup(struct libalias *la)
875{
876 struct alias_link *lnk, *lnk_tmp;
877
878 LIBALIAS_LOCK_ASSERT(la);
879 LIST_FOREACH_SAFE(lnk, &la->linkTableOut[la->cleanupIndex++],
880 list_out, lnk_tmp) {
881 if (la->timeStamp - lnk->timestamp > lnk->expire_time)
882 DeleteLink(lnk);
883 }
884
885 if (la->cleanupIndex == LINK_TABLE_OUT_SIZE)
886 la->cleanupIndex = 0;
887}
888
889static void
890DeleteLink(struct alias_link *lnk)
891{
892 struct libalias *la = lnk->la;
893 LogFlowFuncEnter();
894
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)
898 return;
899
900#ifndef NO_FW_PUNCH
901/* Delete associated firewall hole, if any */
902 ClearFWHole(lnk);
903#endif
904
905/* Free memory allocated for LSNAT server pool */
906 if (lnk->server != NULL) {
907 struct server *head, *curr, *next;
908
909 head = curr = lnk->server;
910 do {
911 next = curr->next;
912 free(curr);
913 } while ((curr = next) != head);
914 }
915/* Adjust output table pointers */
916 LIST_REMOVE(lnk, list_out);
917
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) {
923 la->sockCount--;
924 closesocket(lnk->sockfd);
925 }
926#endif
927/* Link-type dependent cleanup */
928 switch (lnk->link_type) {
929 case LINK_ICMP:
930 la->icmpLinkCount--;
931 break;
932 case LINK_UDP:
933 la->udpLinkCount--;
934 break;
935 case LINK_TCP:
936 la->tcpLinkCount--;
937 free(lnk->data.tcp);
938 break;
939 case LINK_PPTP:
940 la->pptpLinkCount--;
941 break;
942 case LINK_FRAGMENT_ID:
943 la->fragmentIdLinkCount--;
944 break;
945 case LINK_FRAGMENT_PTR:
946 la->fragmentPtrLinkCount--;
947 if (lnk->data.frag_ptr != NULL)
948 free(lnk->data.frag_ptr);
949 break;
950 case LINK_ADDR:
951 break;
952 default:
953 la->protoLinkCount--;
954 break;
955 }
956
957/* Free memory */
958 free(lnk);
959
960/* Write statistics, if logging enabled */
961 if (la->packetAliasMode & PKT_ALIAS_LOG) {
962 ShowAliasStats(la);
963 }
964 LogFlowFuncLeave();
965}
966
967
968static struct alias_link *
969AddLink(struct libalias *la, struct in_addr src_addr,
970 struct in_addr dst_addr,
971 struct in_addr alias_addr,
972 u_short src_port,
973 u_short dst_port,
974 int alias_port_param, /* if less than zero, alias */
975 int link_type)
976{ /* port will be automatically *//* chosen.
977 * If greater than */
978 u_int start_point; /* zero, equal to alias port */
979 struct alias_link *lnk;
980
981 LIBALIAS_LOCK_ASSERT(la);
982 lnk = malloc(sizeof(struct alias_link));
983 if (lnk != NULL) {
984 /* Basic initialization */
985 lnk->la = la;
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;
992 lnk->proxy_port = 0;
993 lnk->server = NULL;
994 lnk->link_type = link_type;
995#ifndef NO_USE_SOCKETS
996 lnk->sockfd = -1;
997#endif
998 lnk->flags = 0;
999 lnk->pflags = 0;
1000 lnk->timestamp = la->timeStamp;
1001
1002 /* Expiration time */
1003 switch (link_type) {
1004 case LINK_ICMP:
1005 lnk->expire_time = ICMP_EXPIRE_TIME;
1006 break;
1007 case LINK_UDP:
1008 lnk->expire_time = UDP_EXPIRE_TIME;
1009 break;
1010 case LINK_TCP:
1011 lnk->expire_time = TCP_EXPIRE_INITIAL;
1012 break;
1013 case LINK_PPTP:
1014 lnk->flags |= LINK_PERMANENT; /* no timeout. */
1015 break;
1016 case LINK_FRAGMENT_ID:
1017 lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME;
1018 break;
1019 case LINK_FRAGMENT_PTR:
1020 lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
1021 break;
1022 case LINK_ADDR:
1023 break;
1024 default:
1025 lnk->expire_time = PROTO_EXPIRE_TIME;
1026 break;
1027 }
1028
1029 /* Determine alias flags */
1030 if (dst_addr.s_addr == INADDR_ANY)
1031 lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
1032 if (dst_port == 0)
1033 lnk->flags |= LINK_UNKNOWN_DEST_PORT;
1034
1035 /* Determine alias port */
1036 if (GetNewPort(la, lnk, alias_port_param) != 0) {
1037 free(lnk);
1038 return (NULL);
1039 }
1040 /* Link-type dependent initialization */
1041 switch (link_type) {
1042 struct tcp_dat *aux_tcp;
1043
1044 case LINK_ICMP:
1045 la->icmpLinkCount++;
1046 break;
1047 case LINK_UDP:
1048 la->udpLinkCount++;
1049 break;
1050 case LINK_TCP:
1051 aux_tcp = malloc(sizeof(struct tcp_dat));
1052 if (aux_tcp != NULL) {
1053 int i;
1054
1055 la->tcpLinkCount++;
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;
1064 } else {
1065#ifdef LIBALIAS_DEBUG
1066 fprintf(stderr, "PacketAlias/AddLink: ");
1067 fprintf(stderr, " cannot allocate auxiliary TCP data\n");
1068#endif
1069 free(lnk);
1070 return (NULL);
1071 }
1072 break;
1073 case LINK_PPTP:
1074 la->pptpLinkCount++;
1075 break;
1076 case LINK_FRAGMENT_ID:
1077 la->fragmentIdLinkCount++;
1078 break;
1079 case LINK_FRAGMENT_PTR:
1080 la->fragmentPtrLinkCount++;
1081 break;
1082 case LINK_ADDR:
1083 break;
1084 default:
1085 la->protoLinkCount++;
1086 break;
1087 }
1088
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);
1093
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);
1097 } else {
1098#ifdef LIBALIAS_DEBUG
1099 fprintf(stderr, "PacketAlias/AddLink(): ");
1100 fprintf(stderr, "malloc() call failed.\n");
1101#endif
1102 }
1103 if (la->packetAliasMode & PKT_ALIAS_LOG) {
1104 ShowAliasStats(la);
1105 }
1106 return (lnk);
1107}
1108
1109static struct alias_link *
1110ReLink(struct alias_link *old_lnk,
1111 struct in_addr src_addr,
1112 struct in_addr dst_addr,
1113 struct in_addr alias_addr,
1114 u_short src_port,
1115 u_short dst_port,
1116 int alias_port_param, /* if less than zero, alias */
1117 int link_type)
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;
1122
1123 LIBALIAS_LOCK_ASSERT(la);
1124 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1125 src_port, dst_port, alias_port_param,
1126 link_type);
1127#ifndef NO_FW_PUNCH
1128 if (new_lnk != NULL &&
1129 old_lnk->link_type == LINK_TCP &&
1130 old_lnk->data.tcp->fwhole > 0) {
1131 PunchFWHole(new_lnk);
1132 }
1133#endif
1134 DeleteLink(old_lnk);
1135 return (new_lnk);
1136}
1137
1138static struct alias_link *
1139_FindLinkOut(struct libalias *la, struct in_addr src_addr,
1140 struct in_addr dst_addr,
1141 u_short src_port,
1142 u_short dst_port,
1143 int link_type,
1144 int replace_partial_links)
1145{
1146 u_int i;
1147 struct alias_link *lnk;
1148
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;
1159 break;
1160 }
1161 }
1162
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,
1167 link_type, 0);
1168 if (lnk == NULL)
1169 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port,
1170 dst_port, link_type, 0);
1171 }
1172 if (lnk == NULL &&
1173 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
1174 lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0,
1175 link_type, 0);
1176 }
1177 if (lnk != NULL) {
1178 lnk = ReLink(lnk,
1179 src_addr, dst_addr, lnk->alias_addr,
1180 src_port, dst_port, lnk->alias_port,
1181 link_type);
1182 }
1183 }
1184 return (lnk);
1185}
1186
1187static struct alias_link *
1188FindLinkOut(struct libalias *la, struct in_addr src_addr,
1189 struct in_addr dst_addr,
1190 u_short src_port,
1191 u_short dst_port,
1192 int link_type,
1193 int replace_partial_links)
1194{
1195 struct alias_link *lnk;
1196
1197 LIBALIAS_LOCK_ASSERT(la);
1198 lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port,
1199 link_type, replace_partial_links);
1200
1201 if (lnk == NULL) {
1202 /*
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
1206 * is.
1207 */
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);
1212 }
1213 }
1214 return (lnk);
1215}
1216
1217
1218static struct alias_link *
1219_FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1220 struct in_addr alias_addr,
1221 u_short dst_port,
1222 u_short alias_port,
1223 int link_type,
1224 int replace_partial_links)
1225{
1226 int flags_in;
1227 u_int start_point;
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;
1233
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;
1240
1241/* If either the dest addr or port is unknown, the search
1242 loop will have to know about this. */
1243
1244 flags_in = 0;
1245 if (dst_addr.s_addr == INADDR_ANY)
1246 flags_in |= LINK_UNKNOWN_DEST_ADDR;
1247 if (dst_port == 0)
1248 flags_in |= LINK_UNKNOWN_DEST_PORT;
1249
1250/* Search loop */
1251 start_point = StartPointIn(alias_addr, alias_port, link_type);
1252 LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) {
1253 int flags;
1254
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;
1263 break;
1264 }
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;
1272 }
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;
1280 }
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;
1288 }
1289 }
1290 }
1291
1292
1293
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;
1303 else
1304 return (NULL);
1305
1306 if (replace_partial_links &&
1307 (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) {
1308 struct in_addr src_addr;
1309 u_short src_port;
1310
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;
1315 } else {
1316 src_addr = lnk->src_addr;
1317 src_port = lnk->src_port;
1318 }
1319
1320 lnk = ReLink(lnk,
1321 src_addr, dst_addr, alias_addr,
1322 src_port, dst_port, alias_port,
1323 link_type);
1324 }
1325 return (lnk);
1326}
1327
1328static struct alias_link *
1329FindLinkIn(struct libalias *la, struct in_addr dst_addr,
1330 struct in_addr alias_addr,
1331 u_short dst_port,
1332 u_short alias_port,
1333 int link_type,
1334 int replace_partial_links)
1335{
1336 struct alias_link *lnk;
1337
1338 LIBALIAS_LOCK_ASSERT(la);
1339 lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port,
1340 link_type, replace_partial_links);
1341
1342 if (lnk == NULL) {
1343 /*
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
1347 * address is.
1348 */
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);
1353 }
1354 }
1355 return (lnk);
1356}
1357
1358
1359
1360
1361/* External routines for finding/adding links
1362
1363-- "external" means outside alias_db.c, but within alias*.c --
1364
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()
1373
1374(prototypes in alias_local.h)
1375*/
1376
1377
1378struct alias_link *
1379FindIcmpIn(struct libalias *la, struct in_addr dst_addr,
1380 struct in_addr alias_addr,
1381 u_short id_alias,
1382 int create)
1383{
1384 struct alias_link *lnk;
1385
1386 LIBALIAS_LOCK_ASSERT(la);
1387 lnk = FindLinkIn(la, dst_addr, alias_addr,
1388 NO_DEST_PORT, id_alias,
1389 LINK_ICMP, 0);
1390 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1391 struct in_addr target_addr;
1392
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,
1396 LINK_ICMP);
1397 }
1398 return (lnk);
1399}
1400
1401
1402struct alias_link *
1403FindIcmpOut(struct libalias *la, struct in_addr src_addr,
1404 struct in_addr dst_addr,
1405 u_short id,
1406 int create)
1407{
1408 struct alias_link *lnk;
1409
1410 LIBALIAS_LOCK_ASSERT(la);
1411 lnk = FindLinkOut(la, src_addr, dst_addr,
1412 id, NO_DEST_PORT,
1413 LINK_ICMP, 0);
1414 if (lnk == NULL && create) {
1415 struct in_addr alias_addr;
1416
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,
1420 LINK_ICMP);
1421 }
1422 return (lnk);
1423}
1424
1425
1426struct alias_link *
1427FindFragmentIn1(struct libalias *la, struct in_addr dst_addr,
1428 struct in_addr alias_addr,
1429 u_short ip_id)
1430{
1431 struct alias_link *lnk;
1432
1433 LIBALIAS_LOCK_ASSERT(la);
1434 lnk = FindLinkIn(la, dst_addr, alias_addr,
1435 NO_DEST_PORT, ip_id,
1436 LINK_FRAGMENT_ID, 0);
1437
1438 if (lnk == NULL) {
1439 lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr,
1440 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1441 LINK_FRAGMENT_ID);
1442 }
1443 return (lnk);
1444}
1445
1446
1447struct alias_link *
1448FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if
1449 * one */
1450 struct in_addr alias_addr, /* is not found. */
1451 u_short ip_id)
1452{
1453
1454 LIBALIAS_LOCK_ASSERT(la);
1455 return FindLinkIn(la, dst_addr, alias_addr,
1456 NO_DEST_PORT, ip_id,
1457 LINK_FRAGMENT_ID, 0);
1458}
1459
1460
1461struct alias_link *
1462AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr,
1463 u_short ip_id)
1464{
1465
1466 LIBALIAS_LOCK_ASSERT(la);
1467 return AddLink(la, la->nullAddress, dst_addr, la->nullAddress,
1468 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1469 LINK_FRAGMENT_PTR);
1470}
1471
1472
1473struct alias_link *
1474FindFragmentPtr(struct libalias *la, struct in_addr dst_addr,
1475 u_short ip_id)
1476{
1477
1478 LIBALIAS_LOCK_ASSERT(la);
1479 return FindLinkIn(la, dst_addr, la->nullAddress,
1480 NO_DEST_PORT, ip_id,
1481 LINK_FRAGMENT_PTR, 0);
1482}
1483
1484
1485struct alias_link *
1486FindProtoIn(struct libalias *la, struct in_addr dst_addr,
1487 struct in_addr alias_addr,
1488 u_char proto)
1489{
1490 struct alias_link *lnk;
1491
1492 LIBALIAS_LOCK_ASSERT(la);
1493 lnk = FindLinkIn(la, dst_addr, alias_addr,
1494 NO_DEST_PORT, 0,
1495 proto, 1);
1496
1497 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1498 struct in_addr target_addr;
1499
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,
1503 proto);
1504 }
1505 return (lnk);
1506}
1507
1508
1509struct alias_link *
1510FindProtoOut(struct libalias *la, struct in_addr src_addr,
1511 struct in_addr dst_addr,
1512 u_char proto)
1513{
1514 struct alias_link *lnk;
1515
1516 LIBALIAS_LOCK_ASSERT(la);
1517 lnk = FindLinkOut(la, src_addr, dst_addr,
1518 NO_SRC_PORT, NO_DEST_PORT,
1519 proto, 1);
1520
1521 if (lnk == NULL) {
1522 struct in_addr alias_addr;
1523
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,
1527 proto);
1528 }
1529 return (lnk);
1530}
1531
1532
1533struct alias_link *
1534FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr,
1535 struct in_addr alias_addr,
1536 u_short dst_port,
1537 u_short alias_port,
1538 u_char proto,
1539 int create)
1540{
1541 int link_type;
1542 struct alias_link *lnk;
1543
1544 LIBALIAS_LOCK_ASSERT(la);
1545 switch (proto) {
1546 case IPPROTO_UDP:
1547 link_type = LINK_UDP;
1548 break;
1549 case IPPROTO_TCP:
1550 link_type = LINK_TCP;
1551 break;
1552 default:
1553 return (NULL);
1554 break;
1555 }
1556
1557 lnk = FindLinkIn(la, dst_addr, alias_addr,
1558 dst_port, alias_port,
1559 link_type, create);
1560
1561 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1562 struct in_addr target_addr;
1563
1564 target_addr = FindOriginalAddress(la, alias_addr);
1565 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1566 alias_port, dst_port, alias_port,
1567 link_type);
1568 }
1569 return (lnk);
1570}
1571
1572
1573struct alias_link *
1574FindUdpTcpOut(struct libalias *la, struct in_addr src_addr,
1575 struct in_addr dst_addr,
1576 u_short src_port,
1577 u_short dst_port,
1578 u_char proto,
1579 int create)
1580{
1581 int link_type;
1582 struct alias_link *lnk;
1583
1584 LIBALIAS_LOCK_ASSERT(la);
1585 switch (proto) {
1586 case IPPROTO_UDP:
1587 link_type = LINK_UDP;
1588 break;
1589 case IPPROTO_TCP:
1590 link_type = LINK_TCP;
1591 break;
1592 default:
1593 return (NULL);
1594 break;
1595 }
1596
1597 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create);
1598
1599 if (lnk == NULL && create) {
1600 struct in_addr alias_addr;
1601
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,
1605 link_type);
1606 }
1607 return (lnk);
1608}
1609
1610
1611struct alias_link *
1612AddPptp(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)
1616{
1617 struct alias_link *lnk;
1618
1619 LIBALIAS_LOCK_ASSERT(la);
1620 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1621 src_call_id, 0, GET_ALIAS_PORT,
1622 LINK_PPTP);
1623
1624 return (lnk);
1625}
1626
1627
1628struct alias_link *
1629FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr,
1630 struct in_addr dst_addr,
1631 u_int16_t src_call_id)
1632{
1633 u_int i;
1634 struct alias_link *lnk;
1635
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)
1643 break;
1644
1645 return (lnk);
1646}
1647
1648
1649struct alias_link *
1650FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr,
1651 struct in_addr dst_addr,
1652 u_int16_t dst_call_id)
1653{
1654 u_int i;
1655 struct alias_link *lnk;
1656
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)
1664 break;
1665
1666 return (lnk);
1667}
1668
1669
1670struct alias_link *
1671FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr,
1672 struct in_addr alias_addr,
1673 u_int16_t dst_call_id)
1674{
1675 u_int i;
1676 struct alias_link *lnk;
1677
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)
1685 break;
1686
1687 return (lnk);
1688}
1689
1690
1691struct alias_link *
1692FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr,
1693 struct in_addr alias_addr,
1694 u_int16_t alias_call_id)
1695{
1696 struct alias_link *lnk;
1697
1698 LIBALIAS_LOCK_ASSERT(la);
1699 lnk = FindLinkIn(la, dst_addr, alias_addr,
1700 0 /* any */ , alias_call_id,
1701 LINK_PPTP, 0);
1702
1703
1704 return (lnk);
1705}
1706
1707
1708struct alias_link *
1709FindRtspOut(struct libalias *la, struct in_addr src_addr,
1710 struct in_addr dst_addr,
1711 u_short src_port,
1712 u_short alias_port,
1713 u_char proto)
1714{
1715 int link_type;
1716 struct alias_link *lnk;
1717
1718 LIBALIAS_LOCK_ASSERT(la);
1719 switch (proto) {
1720 case IPPROTO_UDP:
1721 link_type = LINK_UDP;
1722 break;
1723 case IPPROTO_TCP:
1724 link_type = LINK_TCP;
1725 break;
1726 default:
1727 return (NULL);
1728 break;
1729 }
1730
1731 lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1);
1732
1733 if (lnk == NULL) {
1734 struct in_addr alias_addr;
1735
1736 alias_addr = FindAliasAddress(la, src_addr);
1737 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1738 src_port, 0, alias_port,
1739 link_type);
1740 }
1741 return (lnk);
1742}
1743
1744
1745struct in_addr
1746FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
1747{
1748 struct alias_link *lnk;
1749
1750 LIBALIAS_LOCK_ASSERT(la);
1751 lnk = FindLinkIn(la, la->nullAddress, alias_addr,
1752 0, 0, LINK_ADDR, 0);
1753 if (lnk == NULL) {
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;
1760 else
1761 return (la->targetAddress);
1762 } else {
1763 if (lnk->server != NULL) { /* LSNAT link */
1764 struct in_addr src_addr;
1765
1766 src_addr = lnk->server->addr;
1767 lnk->server = lnk->server->next;
1768 return (src_addr);
1769 } else if (lnk->src_addr.s_addr == INADDR_ANY)
1770 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1771 la->aliasAddress : alias_addr;
1772 else
1773 return (lnk->src_addr);
1774 }
1775}
1776
1777
1778struct in_addr
1779FindAliasAddress(struct libalias *la, struct in_addr original_addr)
1780{
1781 struct alias_link *lnk;
1782
1783 LIBALIAS_LOCK_ASSERT(la);
1784 lnk = FindLinkOut(la, original_addr, la->nullAddress,
1785 0, 0, LINK_ADDR, 0);
1786 if (lnk == NULL) {
1787 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1788 la->aliasAddress : original_addr;
1789 } else {
1790 if (lnk->alias_addr.s_addr == INADDR_ANY)
1791 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1792 la->aliasAddress : original_addr;
1793 else
1794 return (lnk->alias_addr);
1795 }
1796}
1797
1798
1799/* External routines for getting or changing link data
1800 (external to alias_db.c, but internal to alias*.c)
1801
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()
1810 SetDestCallId()
1811*/
1812
1813
1814void
1815SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
1816{
1817 lnk->data.frag_addr = src_addr;
1818}
1819
1820
1821void
1822GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
1823{
1824 *src_addr = lnk->data.frag_addr;
1825}
1826
1827
1828void
1829SetFragmentPtr(struct alias_link *lnk, char *fptr)
1830{
1831 lnk->data.frag_ptr = fptr;
1832}
1833
1834
1835void
1836GetFragmentPtr(struct alias_link *lnk, char **fptr)
1837{
1838 *fptr = lnk->data.frag_ptr;
1839}
1840
1841
1842void
1843SetStateIn(struct alias_link *lnk, int state)
1844{
1845 /* TCP input state */
1846 switch (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;
1850 else
1851 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1852 break;
1853 case ALIAS_TCP_STATE_CONNECTED:
1854 if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED)
1855 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1856 break;
1857 default:
1858#ifdef _KERNEL
1859 panic("libalias:SetStateIn() unknown state");
1860#else
1861 abort();
1862#endif
1863 }
1864 lnk->data.tcp->state.in = state;
1865}
1866
1867
1868void
1869SetStateOut(struct alias_link *lnk, int state)
1870{
1871 /* TCP output state */
1872 switch (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;
1876 else
1877 lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
1878 break;
1879 case ALIAS_TCP_STATE_CONNECTED:
1880 if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED)
1881 lnk->expire_time = TCP_EXPIRE_CONNECTED;
1882 break;
1883 default:
1884#ifdef _KERNEL
1885 panic("libalias:SetStateOut() unknown state");
1886#else
1887 abort();
1888#endif
1889 }
1890 lnk->data.tcp->state.out = state;
1891}
1892
1893
1894int
1895GetStateIn(struct alias_link *lnk)
1896{
1897 /* TCP input state */
1898 return (lnk->data.tcp->state.in);
1899}
1900
1901
1902int
1903GetStateOut(struct alias_link *lnk)
1904{
1905 /* TCP output state */
1906 return (lnk->data.tcp->state.out);
1907}
1908
1909
1910struct in_addr
1911GetOriginalAddress(struct alias_link *lnk)
1912{
1913 if (lnk->src_addr.s_addr == INADDR_ANY)
1914 return (lnk->la->aliasAddress);
1915 else
1916 return (lnk->src_addr);
1917}
1918
1919
1920struct in_addr
1921GetDestAddress(struct alias_link *lnk)
1922{
1923 return (lnk->dst_addr);
1924}
1925
1926
1927struct in_addr
1928GetAliasAddress(struct alias_link *lnk)
1929{
1930 if (lnk->alias_addr.s_addr == INADDR_ANY)
1931 return (lnk->la->aliasAddress);
1932 else
1933 return (lnk->alias_addr);
1934}
1935
1936
1937struct in_addr
1938GetDefaultAliasAddress(struct libalias *la)
1939{
1940
1941 LIBALIAS_LOCK_ASSERT(la);
1942 return (la->aliasAddress);
1943}
1944
1945
1946void
1947SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
1948{
1949
1950 LIBALIAS_LOCK_ASSERT(la);
1951 la->aliasAddress = alias_addr;
1952}
1953
1954
1955u_short
1956GetOriginalPort(struct alias_link *lnk)
1957{
1958 return (lnk->src_port);
1959}
1960
1961
1962u_short
1963GetAliasPort(struct alias_link *lnk)
1964{
1965 return (lnk->alias_port);
1966}
1967
1968#ifndef NO_FW_PUNCH
1969static u_short
1970GetDestPort(struct alias_link *lnk)
1971{
1972 return (lnk->dst_port);
1973}
1974
1975#endif
1976
1977void
1978SetAckModified(struct alias_link *lnk)
1979{
1980/* Indicate that ACK numbers have been modified in a TCP connection */
1981 lnk->data.tcp->state.ack_modified = 1;
1982}
1983
1984
1985struct in_addr
1986GetProxyAddress(struct alias_link *lnk)
1987{
1988 return (lnk->proxy_addr);
1989}
1990
1991
1992void
1993SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
1994{
1995 lnk->proxy_addr = addr;
1996}
1997
1998
1999u_short
2000GetProxyPort(struct alias_link *lnk)
2001{
2002 return (lnk->proxy_port);
2003}
2004
2005
2006void
2007SetProxyPort(struct alias_link *lnk, u_short port)
2008{
2009 lnk->proxy_port = port;
2010}
2011
2012
2013int
2014GetAckModified(struct alias_link *lnk)
2015{
2016/* See if ACK numbers have been modified */
2017 return (lnk->data.tcp->state.ack_modified);
2018}
2019
2020
2021int
2022GetDeltaAckIn(struct ip *pip, struct alias_link *lnk)
2023{
2024/*
2025Find out how much the ACK number has been altered for an incoming
2026TCP packet. To do this, a circular list of ACK numbers where the TCP
2027packet size was altered is searched.
2028*/
2029
2030 int i;
2031 struct tcphdr *tc;
2032 int delta, ack_diff_min;
2033 u_long ack;
2034
2035 tc = ip_next(pip);
2036 ack = tc->th_ack;
2037
2038 delta = 0;
2039 ack_diff_min = -1;
2040 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2041 struct ack_data_record x;
2042
2043 x = lnk->data.tcp->ack[i];
2044 if (x.active == 1) {
2045 int ack_diff;
2046
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) {
2051 delta = x.delta;
2052 ack_diff_min = ack_diff;
2053 }
2054 } else {
2055 delta = x.delta;
2056 ack_diff_min = ack_diff;
2057 }
2058 }
2059 }
2060 }
2061 return (delta);
2062}
2063
2064
2065int
2066GetDeltaSeqOut(struct ip *pip, struct alias_link *lnk)
2067{
2068/*
2069Find out how much the sequence number has been altered for an outgoing
2070TCP packet. To do this, a circular list of ACK numbers where the TCP
2071packet size was altered is searched.
2072*/
2073
2074 int i;
2075 struct tcphdr *tc;
2076 int delta, seq_diff_min;
2077 u_long seq;
2078
2079 tc = ip_next(pip);
2080 seq = tc->th_seq;
2081
2082 delta = 0;
2083 seq_diff_min = -1;
2084 for (i = 0; i < N_LINK_TCP_DATA; i++) {
2085 struct ack_data_record x;
2086
2087 x = lnk->data.tcp->ack[i];
2088 if (x.active == 1) {
2089 int seq_diff;
2090
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) {
2095 delta = x.delta;
2096 seq_diff_min = seq_diff;
2097 }
2098 } else {
2099 delta = x.delta;
2100 seq_diff_min = seq_diff;
2101 }
2102 }
2103 }
2104 }
2105 return (delta);
2106}
2107
2108
2109void
2110AddSeq(struct ip *pip, struct alias_link *lnk, int delta)
2111{
2112/*
2113When a TCP packet has been altered in length, save this
2114information in a circular list. If enough packets have
2115been altered, then this list will begin to overwrite itself.
2116*/
2117
2118 struct tcphdr *tc;
2119 struct ack_data_record x;
2120 int hlen, tlen, dlen;
2121 int i;
2122
2123 tc = ip_next(pip);
2124
2125 hlen = (pip->ip_hl + tc->th_off) << 2;
2126 tlen = ntohs(pip->ip_len);
2127 dlen = tlen - hlen;
2128
2129 x.ack_old = htonl(ntohl(tc->th_seq) + dlen);
2130 x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta);
2131 x.delta = delta;
2132 x.active = 1;
2133
2134 i = lnk->data.tcp->state.index;
2135 lnk->data.tcp->ack[i] = x;
2136
2137 i++;
2138 if (i == N_LINK_TCP_DATA)
2139 lnk->data.tcp->state.index = 0;
2140 else
2141 lnk->data.tcp->state.index = i;
2142}
2143
2144void
2145SetExpire(struct alias_link *lnk, int expire)
2146{
2147 if (expire == 0) {
2148 lnk->flags &= ~LINK_PERMANENT;
2149 DeleteLink(lnk);
2150 } else if (expire == -1) {
2151 lnk->flags |= LINK_PERMANENT;
2152 } else if (expire > 0) {
2153 lnk->expire_time = expire;
2154 } else {
2155#ifdef LIBALIAS_DEBUG
2156 fprintf(stderr, "PacketAlias/SetExpire(): ");
2157 fprintf(stderr, "error in expire parameter\n");
2158#endif
2159 }
2160}
2161
2162void
2163ClearCheckNewLink(struct libalias *la)
2164{
2165
2166 LIBALIAS_LOCK_ASSERT(la);
2167 la->newDefaultLink = 0;
2168}
2169
2170void
2171SetProtocolFlags(struct alias_link *lnk, int pflags)
2172{
2173
2174 lnk->pflags = pflags;;
2175}
2176
2177int
2178GetProtocolFlags(struct alias_link *lnk)
2179{
2180
2181 return (lnk->pflags);
2182}
2183
2184void
2185SetDestCallId(struct alias_link *lnk, u_int16_t cid)
2186{
2187 struct libalias *la = lnk->la;
2188
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;
2194}
2195
2196
2197/* Miscellaneous Functions
2198
2199 HouseKeeping()
2200 InitPacketAliasLog()
2201 UninitPacketAliasLog()
2202*/
2203
2204/*
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
2208 every 60 seconds.
2209
2210 (prototype in alias_local.h)
2211*/
2212
2213void
2214HouseKeeping(struct libalias *la)
2215{
2216 int i, n;
2217#ifndef VBOX
2218#ifndef _KERNEL
2219 struct timeval tv;
2220 struct timezone tz;
2221#endif
2222#endif /* !VBOX */
2223
2224 LIBALIAS_LOCK_ASSERT(la);
2225 /*
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.
2229 */
2230#ifndef VBOX
2231#ifdef _KERNEL
2232 la->timeStamp = time_uptime;
2233#else
2234 gettimeofday(&tv, &tz);
2235 la->timeStamp = tv.tv_sec;
2236#endif
2237#else /* VBOX */
2238 la->timeStamp = la->curtime / 1000; /* NB: la->pData->curtime (msec) */
2239#endif
2240
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;
2244
2245 /* Handle different cases */
2246 if (n > 0) {
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);
2252 } else if (n < 0) {
2253#ifdef LIBALIAS_DEBUG
2254 fprintf(stderr, "PacketAlias/HouseKeeping(): ");
2255 fprintf(stderr, "something unexpected in time values\n");
2256#endif
2257 la->lastCleanupTime = la->timeStamp;
2258 }
2259}
2260
2261/* Init the log file and enable logging */
2262static int
2263InitPacketAliasLog(struct libalias *la)
2264{
2265
2266 LIBALIAS_LOCK_ASSERT(la);
2267 if (~la->packetAliasMode & PKT_ALIAS_LOG) {
2268#ifndef VBOX
2269#ifdef _KERNEL
2270 if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
2271 ;
2272#else
2273 if ((la->logDesc = fopen("/var/log/alias.log", "w")))
2274 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2275#endif
2276 else
2277 return (ENOMEM); /* log initialization failed */
2278#else
2279 Log2(("NAT: PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n"));
2280 la->logDesc = (void *)(uintptr_t)1; /* XXX: in vbox we don't use this param */
2281#endif
2282 la->packetAliasMode |= PKT_ALIAS_LOG;
2283 }
2284
2285 return (1);
2286}
2287
2288/* Close the log-file and disable logging. */
2289static void
2290UninitPacketAliasLog(struct libalias *la)
2291{
2292
2293 LIBALIAS_LOCK_ASSERT(la);
2294 if (la->logDesc) {
2295#ifndef VBOX
2296#ifdef _KERNEL
2297 free(la->logDesc);
2298#else
2299 fclose(la->logDesc);
2300#endif
2301#endif /* !VBOX */
2302 la->logDesc = NULL;
2303 }
2304 la->packetAliasMode &= ~PKT_ALIAS_LOG;
2305}
2306
2307/* Outside world interfaces
2308
2309-- "outside world" means other than alias*.c routines --
2310
2311 PacketAliasRedirectPort()
2312 PacketAliasAddServer()
2313 PacketAliasRedirectProto()
2314 PacketAliasRedirectAddr()
2315 PacketAliasRedirectDynamic()
2316 PacketAliasRedirectDelete()
2317 PacketAliasSetAddress()
2318 PacketAliasInit()
2319 PacketAliasUninit()
2320 PacketAliasSetMode()
2321
2322(prototypes in alias.h)
2323*/
2324
2325/* Redirection from a specific public addr:port to a
2326 private addr:port */
2327struct alias_link *
2328LibAliasRedirectPort(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,
2331 u_char proto)
2332{
2333 int link_type;
2334 struct alias_link *lnk;
2335
2336 LIBALIAS_LOCK(la);
2337 switch (proto) {
2338 case IPPROTO_UDP:
2339 link_type = LINK_UDP;
2340 break;
2341 case IPPROTO_TCP:
2342 link_type = LINK_TCP;
2343 break;
2344 default:
2345#ifdef LIBALIAS_DEBUG
2346 fprintf(stderr, "PacketAliasRedirectPort(): ");
2347 fprintf(stderr, "only TCP and UDP protocols allowed\n");
2348#endif
2349 lnk = NULL;
2350 goto getout;
2351 }
2352
2353 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2354 src_port, dst_port, alias_port,
2355 link_type);
2356
2357 if (lnk != NULL) {
2358 lnk->flags |= LINK_PERMANENT;
2359 }
2360#ifdef LIBALIAS_DEBUG
2361 else {
2362 fprintf(stderr, "PacketAliasRedirectPort(): "
2363 "call to AddLink() failed\n");
2364 }
2365#endif
2366
2367getout:
2368 LIBALIAS_UNLOCK(la);
2369 return (lnk);
2370}
2371
2372/* Add server to the pool of servers */
2373int
2374LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
2375{
2376 struct server *server;
2377 int res;
2378
2379 LIBALIAS_LOCK(la);
2380 (void)la;
2381
2382 server = malloc(sizeof(struct server));
2383
2384 if (server != NULL) {
2385 struct server *head;
2386
2387 server->addr = addr;
2388 server->port = port;
2389
2390 head = lnk->server;
2391 if (head == NULL)
2392 server->next = server;
2393 else {
2394 struct server *s;
2395
2396 for (s = head; s->next != head; s = s->next);
2397 s->next = server;
2398 server->next = head;
2399 }
2400 lnk->server = server;
2401 res = 0;
2402 } else
2403 res = -1;
2404
2405 LIBALIAS_UNLOCK(la);
2406 return (res);
2407}
2408
2409/* Redirect packets of a given IP protocol from a specific
2410 public address to a private address */
2411struct alias_link *
2412LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr,
2413 struct in_addr dst_addr,
2414 struct in_addr alias_addr,
2415 u_char proto)
2416{
2417 struct alias_link *lnk;
2418
2419 LIBALIAS_LOCK(la);
2420 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
2421 NO_SRC_PORT, NO_DEST_PORT, 0,
2422 proto);
2423
2424 if (lnk != NULL) {
2425 lnk->flags |= LINK_PERMANENT;
2426 }
2427#ifdef LIBALIAS_DEBUG
2428 else {
2429 fprintf(stderr, "PacketAliasRedirectProto(): "
2430 "call to AddLink() failed\n");
2431 }
2432#endif
2433
2434 LIBALIAS_UNLOCK(la);
2435 return (lnk);
2436}
2437
2438/* Static address translation */
2439struct alias_link *
2440LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr,
2441 struct in_addr alias_addr)
2442{
2443 struct alias_link *lnk;
2444
2445 LIBALIAS_LOCK(la);
2446 lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
2447 0, 0, 0,
2448 LINK_ADDR);
2449
2450 if (lnk != NULL) {
2451 lnk->flags |= LINK_PERMANENT;
2452 }
2453#ifdef LIBALIAS_DEBUG
2454 else {
2455 fprintf(stderr, "PacketAliasRedirectAddr(): "
2456 "call to AddLink() failed\n");
2457 }
2458#endif
2459
2460 LIBALIAS_UNLOCK(la);
2461 return (lnk);
2462}
2463
2464
2465/* Mark the aliasing link dynamic */
2466int
2467LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
2468{
2469 int res;
2470
2471 LIBALIAS_LOCK(la);
2472 (void)la;
2473
2474 if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
2475 res = -1;
2476 else {
2477 lnk->flags &= ~LINK_PERMANENT;
2478 res = 0;
2479 }
2480 LIBALIAS_UNLOCK(la);
2481 return (res);
2482}
2483
2484
2485void
2486LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
2487{
2488/* This is a dangerous function to put in the API,
2489 because an invalid pointer can crash the program. */
2490
2491 LIBALIAS_LOCK(la);
2492 la->deleteAllLinks = 1;
2493 DeleteLink(lnk);
2494 la->deleteAllLinks = 0;
2495 LIBALIAS_UNLOCK(la);
2496}
2497
2498
2499void
2500LibAliasSetAddress(struct libalias *la, struct in_addr addr)
2501{
2502
2503 LIBALIAS_LOCK(la);
2504 if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2505 && la->aliasAddress.s_addr != addr.s_addr)
2506 CleanupAliasData(la);
2507
2508 la->aliasAddress = addr;
2509 LIBALIAS_UNLOCK(la);
2510}
2511
2512
2513void
2514LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2515{
2516
2517 LIBALIAS_LOCK(la);
2518 la->targetAddress = target_addr;
2519 LIBALIAS_UNLOCK(la);
2520}
2521
2522#ifndef VBOX
2523static void
2524finishoff(void)
2525{
2526
2527 while (!LIST_EMPTY(&instancehead))
2528 LibAliasUninit(LIST_FIRST(&instancehead));
2529}
2530#endif
2531
2532struct libalias *
2533#ifndef VBOX
2534LibAliasInit(struct libalias *la)
2535#else
2536LibAliasInit(PNATState pData, struct libalias *la)
2537#endif
2538{
2539 int i;
2540#ifndef VBOX
2541#ifndef _KERNEL
2542 struct timeval tv;
2543 struct timezone tz;
2544#endif
2545#endif /* !VBOX */
2546
2547 if (la == NULL) {
2548 la = calloc(sizeof *la, 1);
2549 if (la == NULL)
2550 return (la);
2551
2552#ifndef VBOX
2553#ifndef _KERNEL /* kernel cleans up on module unload */
2554 if (LIST_EMPTY(&instancehead))
2555 atexit(finishoff);
2556#endif
2557#endif /* !VBOX */
2558 LIST_INSERT_HEAD(&instancehead, la, instancelist);
2559
2560#ifndef VBOX
2561#ifdef _KERNEL
2562 la->timeStamp = time_uptime;
2563 la->lastCleanupTime = time_uptime;
2564#else
2565 gettimeofday(&tv, &tz);
2566 la->timeStamp = tv.tv_sec;
2567 la->lastCleanupTime = tv.tv_sec;
2568#endif
2569#else /* VBOX */
2570 la->pData = pData;
2571 la->timeStamp = la->curtime / 1000; /* NB: la->pData->curtime (msec) */
2572 la->lastCleanupTime = la->timeStamp;
2573#endif /* VBOX */
2574
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);
2580 LIBALIAS_LOCK(la);
2581 } else {
2582 LIBALIAS_LOCK(la);
2583 la->deleteAllLinks = 1;
2584 CleanupAliasData(la);
2585 la->deleteAllLinks = 0;
2586 }
2587
2588 la->aliasAddress.s_addr = INADDR_ANY;
2589 la->targetAddress.s_addr = INADDR_ANY;
2590
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;
2598 la->sockCount = 0;
2599
2600 la->cleanupIndex = 0;
2601
2602 la->packetAliasMode = PKT_ALIAS_SAME_PORTS
2603#ifndef NO_USE_SOCKETS
2604 | PKT_ALIAS_USE_SOCKETS
2605#endif
2606 | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2607#ifndef NO_FW_PUNCH
2608 la->fireWallFD = -1;
2609#endif
2610#ifndef _KERNEL
2611 LibAliasRefreshModules();
2612#endif
2613 LIBALIAS_UNLOCK(la);
2614 return (la);
2615}
2616
2617void
2618LibAliasUninit(struct libalias *la)
2619{
2620
2621 LIBALIAS_LOCK(la);
2622 la->deleteAllLinks = 1;
2623 CleanupAliasData(la);
2624 la->deleteAllLinks = 0;
2625 UninitPacketAliasLog(la);
2626#ifndef NO_FW_PUNCH
2627 UninitPunchFW(la);
2628#endif
2629 LIST_REMOVE(la, instancelist);
2630 LIBALIAS_UNLOCK(la);
2631 LIBALIAS_LOCK_DESTROY(la);
2632 free(la);
2633}
2634
2635/* Change mode for some operations */
2636unsigned int
2637LibAliasSetMode(
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) */
2642)
2643{
2644 int res = -1;
2645
2646 LIBALIAS_LOCK(la);
2647/* Enable logging? */
2648 if (flags & mask & PKT_ALIAS_LOG) {
2649 /* Do the enable */
2650 if (InitPacketAliasLog(la) == ENOMEM)
2651 goto getout;
2652 } else
2653/* _Disable_ logging? */
2654 if (~flags & mask & PKT_ALIAS_LOG) {
2655 UninitPacketAliasLog(la);
2656 }
2657#ifndef NO_FW_PUNCH
2658/* Start punching holes in the firewall? */
2659 if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2660 InitPunchFW(la);
2661 } else
2662/* Stop punching holes in the firewall? */
2663 if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2664 UninitPunchFW(la);
2665 }
2666#endif
2667
2668/* Other flags can be set/cleared without special action */
2669 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2670 res = la->packetAliasMode;
2671getout:
2672 LIBALIAS_UNLOCK(la);
2673 return (res);
2674}
2675
2676
2677int
2678LibAliasCheckNewLink(struct libalias *la)
2679{
2680 int res;
2681
2682 LIBALIAS_LOCK(la);
2683 res = la->newDefaultLink;
2684 LIBALIAS_UNLOCK(la);
2685 return (res);
2686}
2687
2688
2689#ifndef NO_FW_PUNCH
2690
2691/*****************
2692 Code to support firewall punching. This shouldn't really be in this
2693 file, but making variables global is evil too.
2694 ****************/
2695
2696/* Firewall include files */
2697#include <net/if.h>
2698#include <netinet/ip_fw.h>
2699#include <string.h>
2700#include <err.h>
2701
2702/*
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.
2706 */
2707static ipfw_insn *
2708next_cmd(ipfw_insn * cmd)
2709{
2710 cmd += F_LEN(cmd);
2711 bzero(cmd, sizeof(*cmd));
2712 return (cmd);
2713}
2714
2715/*
2716 * A function to fill simple commands of size 1.
2717 * Existing flags are preserved.
2718 */
2719static ipfw_insn *
2720fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2721 int flags, u_int16_t arg)
2722{
2723 cmd->opcode = opcode;
2724 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2725 cmd->arg1 = arg;
2726 return next_cmd(cmd);
2727}
2728
2729static ipfw_insn *
2730fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2731{
2732 ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1;
2733
2734 cmd->addr.s_addr = addr;
2735 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2736}
2737
2738static ipfw_insn *
2739fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2740{
2741 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1;
2742
2743 cmd->ports[0] = cmd->ports[1] = port;
2744 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2745}
2746
2747static int
2748fill_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)
2751{
2752 struct ip_fw *rule = (struct ip_fw *)buf;
2753 ipfw_insn *cmd = (ipfw_insn *) rule->cmd;
2754
2755 bzero(buf, bufsize);
2756 rule->rulenum = rulenum;
2757
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);
2763
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);
2766
2767 rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
2768
2769 return ((char *)cmd - (char *)buf);
2770}
2771
2772static void ClearAllFWHoles(struct libalias *la);
2773
2774
2775#define fw_setfield(la, field, num) \
2776do { \
2777 (field)[(num) - la->fireWallBaseNum] = 1; \
2778} /*lint -save -e717 */ while(0)/* lint -restore */
2779
2780#define fw_clrfield(la, field, num) \
2781do { \
2782 (field)[(num) - la->fireWallBaseNum] = 0; \
2783} /*lint -save -e717 */ while(0)/* lint -restore */
2784
2785#define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum])
2786
2787static void
2788InitPunchFW(struct libalias *la)
2789{
2790
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);
2797 }
2798 ClearAllFWHoles(la);
2799 la->fireWallActiveNum = la->fireWallBaseNum;
2800 }
2801}
2802
2803static void
2804UninitPunchFW(struct libalias *la)
2805{
2806
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;
2816}
2817
2818/* Make a certain link go through the firewall */
2819void
2820PunchFWHole(struct alias_link *lnk)
2821{
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 */
2826
2827 LIBALIAS_LOCK_ASSERT(la);
2828 la = lnk->la;
2829
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)
2834 return;
2835
2836 memset(&rule, 0, sizeof rule);
2837
2838/** Build rule **/
2839
2840 /* Find empty slot */
2841 for (fwhole = la->fireWallActiveNum;
2842 fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2843 fw_tstfield(la, la->fireWallField, fwhole);
2844 fwhole++);
2845 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2846 for (fwhole = la->fireWallBaseNum;
2847 fwhole < la->fireWallActiveNum &&
2848 fw_tstfield(la, la->fireWallField, fwhole);
2849 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");
2855#endif
2856 return;
2857 }
2858 }
2859 /* Start next search at next position */
2860 la->fireWallActiveNum = fwhole + 1;
2861
2862 /*
2863 * generate two rules of the form
2864 *
2865 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2866 * accept tcp from DAddr DPort to OAddr OPort
2867 */
2868 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2869 u_int32_t rulebuf[255];
2870 int i;
2871
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);
2877 if (r)
2878 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2879
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);
2885 if (r)
2886 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2887 }
2888
2889/* Indicate hole applied */
2890 lnk->data.tcp->fwhole = fwhole;
2891 fw_setfield(la, la->fireWallField, fwhole);
2892}
2893
2894/* Remove a hole in a firewall associated with a particular alias
2895 lnk. Calling this too often is harmless. */
2896static void
2897ClearFWHole(struct alias_link *lnk)
2898{
2899 struct libalias *la;
2900
2901 LIBALIAS_LOCK_ASSERT(la);
2902 la = lnk->la;
2903 if (lnk->link_type == LINK_TCP) {
2904 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall
2905 * hole? */
2906 struct ip_fw rule;
2907
2908 if (fwhole < 0)
2909 return;
2910
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;
2916 }
2917}
2918
2919/* Clear out the entire range dedicated to firewall holes. */
2920static void
2921ClearAllFWHoles(struct libalias *la)
2922{
2923 struct ip_fw rule; /* On-the-fly built rule */
2924 int i;
2925
2926 LIBALIAS_LOCK_ASSERT(la);
2927 if (la->fireWallFD < 0)
2928 return;
2929
2930 memset(&rule, 0, sizeof rule);
2931 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2932 int r = i;
2933
2934 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2935 }
2936 /* XXX: third arg correct here ? /phk */
2937 memset(la->fireWallField, 0, la->fireWallNumNums);
2938}
2939
2940#endif
2941
2942void
2943LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2944{
2945
2946#ifdef VBOX
2947 NOREF(la);
2948 NOREF(base);
2949 NOREF(num);
2950#endif
2951 LIBALIAS_LOCK(la);
2952#ifndef NO_FW_PUNCH
2953 la->fireWallBaseNum = base;
2954 la->fireWallNumNums = num;
2955#endif
2956 LIBALIAS_UNLOCK(la);
2957}
2958
2959void
2960LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2961{
2962
2963 LIBALIAS_LOCK(la);
2964 la->skinnyPort = port;
2965 LIBALIAS_UNLOCK(la);
2966}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use