~ubuntu-branches/ubuntu/trusty/virtualbox-lts-xenial/trusty-updates

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Network/slirp/libalias/alias_db.c

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2016-02-23 14:28:26 UTC
  • Revision ID: package-import@ubuntu.com-20160223142826-bdu69el2z6wa2a44
Tags: upstream-4.3.36-dfsg
ImportĀ upstreamĀ versionĀ 4.3.36-dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
185
static      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
 
 
266
struct 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
 
 
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 */
 
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 */
 
285
struct 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
 
 
292
struct server {         /* LSNAT server pool (circular list) */
 
293
    struct in_addr  addr;
 
294
    u_short     port;
 
295
    struct server  *next;
 
296
};
 
297
 
 
298
struct 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
 
357
static void finishoff(void);
 
358
#endif
 
359
 
 
360
/* Kernel module definition. */
 
361
#ifdef  _KERNEL
 
362
MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing");
 
363
 
 
364
MODULE_VERSION(libalias, 1);
 
365
 
 
366
static int
 
367
alias_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
 
 
389
static moduledata_t alias_mod = {
 
390
       "alias", alias_mod_handler, NULL
 
391
};
 
392
 
 
393
DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
 
394
#endif
 
395
 
 
396
/* Internal utility routines (used only in alias_db.c)
 
397
 
 
398
Lookup 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
 
 
404
Miscellaneous:
 
405
    SeqDiff()                -- difference between two TCP sequences
 
406
    ShowAliasStats()         -- send alias statistics to a monitor file
 
407
*/
 
408
 
 
409
 
 
410
/* Local prototypes */
 
411
static u_int    StartPointIn(struct in_addr, u_short, int);
 
412
 
 
413
static      u_int
 
414
StartPointOut(struct in_addr, struct in_addr,
 
415
    u_short, u_short, int);
 
416
 
 
417
static int  SeqDiff(u_long, u_long);
 
418
 
 
419
#ifndef NO_FW_PUNCH
 
420
/* Firewall control */
 
421
static void InitPunchFW(struct libalias *);
 
422
static void UninitPunchFW(struct libalias *);
 
423
static void ClearFWHole(struct alias_link *);
 
424
 
 
425
#endif
 
426
 
 
427
/* Log file control */
 
428
static void ShowAliasStats(struct libalias *);
 
429
static int  InitPacketAliasLog(struct libalias *);
 
430
static void UninitPacketAliasLog(struct libalias *);
 
431
 
 
432
static      u_int
 
433
StartPointIn(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
 
 
447
static      u_int
 
448
StartPointOut(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
 
 
465
static int
 
466
SeqDiff(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
 
 
480
static void
 
481
AliasLog(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
 
490
static void
 
491
AliasLog(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
 
 
515
static void
 
516
ShowAliasStats(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
 
 
544
Port Allocation:
 
545
    GetNewPort()             -- find and reserve new alias port number
 
546
    GetSocket()              -- try to allocate a socket for a given port
 
547
 
 
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
 
552
    AddLink()               - add link
 
553
    ReLink()                - change link
 
554
 
 
555
Link search:
 
556
    FindLinkOut()           - find link for outgoing packets
 
557
    FindLinkIn()            - find link for incoming packets
 
558
 
 
559
Port search:
 
560
    FindNewPortGroup()      - find an available group of ports
 
561
*/
 
562
 
 
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);
 
567
#endif
 
568
static void CleanupAliasData(struct libalias *);
 
569
 
 
570
static void IncrementalCleanup(struct libalias *);
 
571
 
 
572
static void DeleteLink(struct alias_link *);
 
573
 
 
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);
 
577
 
 
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);
 
582
 
 
583
static struct alias_link *
 
584
        FindLinkOut   (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
 
585
 
 
586
static 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
 
 
605
static int
 
606
GetNewPort(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
 
707
static      u_short
 
708
GetSocket(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
 
 
764
int
 
765
FindNewPortGroup(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
 
 
853
static void
 
854
CleanupAliasData(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
 
 
873
static void
 
874
IncrementalCleanup(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
 
 
889
static void
 
890
DeleteLink(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
 
 
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,
 
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
 
 
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,
 
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
 
 
1138
static 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
 
 
1187
static struct alias_link *
 
1188
FindLinkOut(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
 
 
1218
static 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
 
 
1328
static struct alias_link *
 
1329
FindLinkIn(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
 
 
1378
struct alias_link *
 
1379
FindIcmpIn(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
 
 
1402
struct alias_link *
 
1403
FindIcmpOut(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
 
 
1426
struct alias_link *
 
1427
FindFragmentIn1(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
 
 
1447
struct alias_link *
 
1448
FindFragmentIn2(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
 
 
1461
struct alias_link *
 
1462
AddFragmentPtrLink(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
 
 
1473
struct alias_link *
 
1474
FindFragmentPtr(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
 
 
1485
struct alias_link *
 
1486
FindProtoIn(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
 
 
1509
struct alias_link *
 
1510
FindProtoOut(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
 
 
1533
struct alias_link *
 
1534
FindUdpTcpIn(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
 
 
1573
struct alias_link *
 
1574
FindUdpTcpOut(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
 
 
1611
struct alias_link *
 
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)
 
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
 
 
1628
struct alias_link *
 
1629
FindPptpOutByCallId(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
 
 
1649
struct alias_link *
 
1650
FindPptpOutByPeerCallId(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
 
 
1670
struct alias_link *
 
1671
FindPptpInByCallId(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
 
 
1691
struct alias_link *
 
1692
FindPptpInByPeerCallId(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
 
 
1708
struct alias_link *
 
1709
FindRtspOut(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
 
 
1745
struct in_addr
 
1746
FindOriginalAddress(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
 
 
1778
struct in_addr
 
1779
FindAliasAddress(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
 
 
1814
void
 
1815
SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
 
1816
{
 
1817
    lnk->data.frag_addr = src_addr;
 
1818
}
 
1819
 
 
1820
 
 
1821
void
 
1822
GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
 
1823
{
 
1824
    *src_addr = lnk->data.frag_addr;
 
1825
}
 
1826
 
 
1827
 
 
1828
void
 
1829
SetFragmentPtr(struct alias_link *lnk, char *fptr)
 
1830
{
 
1831
    lnk->data.frag_ptr = fptr;
 
1832
}
 
1833
 
 
1834
 
 
1835
void
 
1836
GetFragmentPtr(struct alias_link *lnk, char **fptr)
 
1837
{
 
1838
    *fptr = lnk->data.frag_ptr;
 
1839
}
 
1840
 
 
1841
 
 
1842
void
 
1843
SetStateIn(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
 
 
1868
void
 
1869
SetStateOut(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
 
 
1894
int
 
1895
GetStateIn(struct alias_link *lnk)
 
1896
{
 
1897
    /* TCP input state */
 
1898
    return (lnk->data.tcp->state.in);
 
1899
}
 
1900
 
 
1901
 
 
1902
int
 
1903
GetStateOut(struct alias_link *lnk)
 
1904
{
 
1905
    /* TCP output state */
 
1906
    return (lnk->data.tcp->state.out);
 
1907
}
 
1908
 
 
1909
 
 
1910
struct in_addr
 
1911
GetOriginalAddress(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
 
 
1920
struct in_addr
 
1921
GetDestAddress(struct alias_link *lnk)
 
1922
{
 
1923
    return (lnk->dst_addr);
 
1924
}
 
1925
 
 
1926
 
 
1927
struct in_addr
 
1928
GetAliasAddress(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
 
 
1937
struct in_addr
 
1938
GetDefaultAliasAddress(struct libalias *la)
 
1939
{
 
1940
 
 
1941
    LIBALIAS_LOCK_ASSERT(la);
 
1942
    return (la->aliasAddress);
 
1943
}
 
1944
 
 
1945
 
 
1946
void
 
1947
SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
 
1948
{
 
1949
 
 
1950
    LIBALIAS_LOCK_ASSERT(la);
 
1951
    la->aliasAddress = alias_addr;
 
1952
}
 
1953
 
 
1954
 
 
1955
u_short
 
1956
GetOriginalPort(struct alias_link *lnk)
 
1957
{
 
1958
    return (lnk->src_port);
 
1959
}
 
1960
 
 
1961
 
 
1962
u_short
 
1963
GetAliasPort(struct alias_link *lnk)
 
1964
{
 
1965
    return (lnk->alias_port);
 
1966
}
 
1967
 
 
1968
#ifndef NO_FW_PUNCH
 
1969
static      u_short
 
1970
GetDestPort(struct alias_link *lnk)
 
1971
{
 
1972
    return (lnk->dst_port);
 
1973
}
 
1974
 
 
1975
#endif
 
1976
 
 
1977
void
 
1978
SetAckModified(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
 
 
1985
struct in_addr
 
1986
GetProxyAddress(struct alias_link *lnk)
 
1987
{
 
1988
    return (lnk->proxy_addr);
 
1989
}
 
1990
 
 
1991
 
 
1992
void
 
1993
SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
 
1994
{
 
1995
    lnk->proxy_addr = addr;
 
1996
}
 
1997
 
 
1998
 
 
1999
u_short
 
2000
GetProxyPort(struct alias_link *lnk)
 
2001
{
 
2002
    return (lnk->proxy_port);
 
2003
}
 
2004
 
 
2005
 
 
2006
void
 
2007
SetProxyPort(struct alias_link *lnk, u_short port)
 
2008
{
 
2009
    lnk->proxy_port = port;
 
2010
}
 
2011
 
 
2012
 
 
2013
int
 
2014
GetAckModified(struct alias_link *lnk)
 
2015
{
 
2016
/* See if ACK numbers have been modified */
 
2017
    return (lnk->data.tcp->state.ack_modified);
 
2018
}
 
2019
 
 
2020
 
 
2021
int
 
2022
GetDeltaAckIn(struct ip *pip, struct alias_link *lnk)
 
2023
{
 
2024
/*
 
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.
 
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
 
 
2065
int
 
2066
GetDeltaSeqOut(struct ip *pip, struct alias_link *lnk)
 
2067
{
 
2068
/*
 
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.
 
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
 
 
2109
void
 
2110
AddSeq(struct ip *pip, struct alias_link *lnk, int delta)
 
2111
{
 
2112
/*
 
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.
 
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
 
 
2144
void
 
2145
SetExpire(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
 
 
2162
void
 
2163
ClearCheckNewLink(struct libalias *la)
 
2164
{
 
2165
 
 
2166
    LIBALIAS_LOCK_ASSERT(la);
 
2167
    la->newDefaultLink = 0;
 
2168
}
 
2169
 
 
2170
void
 
2171
SetProtocolFlags(struct alias_link *lnk, int pflags)
 
2172
{
 
2173
 
 
2174
    lnk->pflags = pflags;;
 
2175
}
 
2176
 
 
2177
int
 
2178
GetProtocolFlags(struct alias_link *lnk)
 
2179
{
 
2180
 
 
2181
    return (lnk->pflags);
 
2182
}
 
2183
 
 
2184
void
 
2185
SetDestCallId(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
 
 
2213
void
 
2214
HouseKeeping(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 */
 
2262
static int
 
2263
InitPacketAliasLog(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 *)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. */
 
2289
static void
 
2290
UninitPacketAliasLog(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 */
 
2327
struct alias_link *
 
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,
 
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
 
 
2367
getout:
 
2368
    LIBALIAS_UNLOCK(la);
 
2369
    return (lnk);
 
2370
}
 
2371
 
 
2372
/* Add server to the pool of servers */
 
2373
int
 
2374
LibAliasAddServer(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 */
 
2411
struct alias_link *
 
2412
LibAliasRedirectProto(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 */
 
2439
struct alias_link *
 
2440
LibAliasRedirectAddr(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 */
 
2466
int
 
2467
LibAliasRedirectDynamic(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
 
 
2485
void
 
2486
LibAliasRedirectDelete(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
 
 
2499
void
 
2500
LibAliasSetAddress(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
 
 
2513
void
 
2514
LibAliasSetTarget(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
 
2523
static void
 
2524
finishoff(void)
 
2525
{
 
2526
 
 
2527
    while (!LIST_EMPTY(&instancehead))
 
2528
        LibAliasUninit(LIST_FIRST(&instancehead));
 
2529
}
 
2530
#endif
 
2531
 
 
2532
struct libalias *
 
2533
#ifndef VBOX
 
2534
LibAliasInit(struct libalias *la)
 
2535
#else
 
2536
LibAliasInit(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
 
 
2617
void
 
2618
LibAliasUninit(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 */
 
2636
unsigned int
 
2637
LibAliasSetMode(
 
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;
 
2671
getout:
 
2672
    LIBALIAS_UNLOCK(la);
 
2673
    return (res);
 
2674
}
 
2675
 
 
2676
 
 
2677
int
 
2678
LibAliasCheckNewLink(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
 */
 
2707
static ipfw_insn *
 
2708
next_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
 */
 
2719
static ipfw_insn *
 
2720
fill_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
 
 
2729
static ipfw_insn *
 
2730
fill_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
 
 
2738
static ipfw_insn *
 
2739
fill_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
 
 
2747
static int
 
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)
 
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
 
 
2772
static void ClearAllFWHoles(struct libalias *la);
 
2773
 
 
2774
 
 
2775
#define fw_setfield(la, field, num)                         \
 
2776
do {                                                    \
 
2777
    (field)[(num) - la->fireWallBaseNum] = 1;               \
 
2778
} /*lint -save -e717 */ while(0)/* lint -restore */
 
2779
 
 
2780
#define fw_clrfield(la, field, num)                         \
 
2781
do {                                                    \
 
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
 
 
2787
static void
 
2788
InitPunchFW(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
 
 
2803
static void
 
2804
UninitPunchFW(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 */
 
2819
void
 
2820
PunchFWHole(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. */
 
2896
static void
 
2897
ClearFWHole(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. */
 
2920
static void
 
2921
ClearAllFWHoles(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
 
 
2942
void
 
2943
LibAliasSetFWBase(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
 
 
2959
void
 
2960
LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
 
2961
{
 
2962
 
 
2963
    LIBALIAS_LOCK(la);
 
2964
    la->skinnyPort = port;
 
2965
    LIBALIAS_UNLOCK(la);
 
2966
}