alias_db.c revision cc1f04cacf4e128369e1c266a035adcb1da68767
/*-
* Copyright (c) 2001 Charles Mott <cm@linktel.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef VBOX
__FBSDID("$FreeBSD: src/sys/netinet/libalias/alias_db.c,v 1.71.2.2.4.1 2009/04/15 03:14:26 kensmith Exp $");
#endif
/*
Alias_db.c encapsulates all data structures used for storing
packet aliasing data. Other parts of the aliasing software
access data through functions provided in this file.
Data storage is based on the notion of a "link", which is
TCP stream connections. A link stores the original source
and destination addresses. For UDP and TCP, it also stores
source and destination port numbers, as well as an alias
port number. Links are also used to store information about
fragments.
There is a facility for sweeping through and deleting old
links as new packets are sent through. A simple timeout is
used for ICMP and UDP links. TCP links are left alone unless
there is an incomplete connection, in which case the link
can be deleted after a certain amount of time.
Initial version: August, 1996 (cjm)
Version 1.4: September 16, 1996 (cjm)
Facility for handling incoming links added.
Version 1.6: September 18, 1996 (cjm)
ICMP data handling simplified.
Version 1.7: January 9, 1997 (cjm)
Fragment handling simplified.
Saves pointers for unresolved fragments.
Permits links for unspecified remote ports
or unspecified remote addresses.
Fixed bug which did not properly zero port
table entries after a link was deleted.
Cleaned up some obsolete comments.
Version 1.8: January 14, 1997 (cjm)
Fixed data type error in StartPoint().
(This error did not exist prior to v1.7
and was discovered and fixed by Ari Suutari)
Version 1.9: February 1, 1997
Optionally, connections initiated from packet aliasing host
machine will will not have their port number aliased unless it
conflicts with an aliasing port already being used. (cjm)
All options earlier being #ifdef'ed are now available through
a new interface, SetPacketAliasMode(). This allows run time
control (which is now available in PPP+pktAlias through the
'alias' keyword). (ee)
Added ability to create an alias port without
either destination address or port specified.
port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
Removed K&R style function headers
and general cleanup. (ee)
Added packetAliasMode to replace compiler #defines's (ee)
Allocates sockets for partially specified
ports if ALIAS_USE_SOCKETS defined. (cjm)
Version 2.0: March, 1997
SetAliasAddress() will now clean up alias links
if the aliasing address is changed. (cjm)
PacketAliasPermanentLink() function added to support permanent
links. (J. Fortes suggested the need for this.)
Examples:
(192.168.0.2, port 21) <-> alias port 3604, known dest addr
unknown dest port
These permanent links allow for incoming connections to
machines on the local network. They can be given with a
user-chosen amount of specificity, with increasing specificity
meaning more security. (cjm)
Quite a bit of rework to the basic engine. The portTable[]
array, which kept track of which ports were in use was replaced
SetExpire() function added. (cjm)
DeleteLink() no longer frees memory association with a pointer
to a fragment (this bug was first recognized by E. Eklund in
v1.9).
Version 2.1: May, 1997 (cjm)
Packet aliasing engine reworked so that it can handle
multiple external addresses rather than just a single
host address.
PacketAliasRedirectPort() and PacketAliasRedirectAddr()
added to the API. The first function is a more generalized
version of PacketAliasPermanentLink(). The second function
implements static network address translation.
Version 3.2: July, 2000 (salander and satoh)
Added FindNewPortGroup to get contiguous range of port values.
Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
link but not actually add one.
Added FindRtspOut, which is closely derived from FindUdpTcpOut,
except that the alias port (from FindNewPortGroup) is provided
as input.
See HISTORY file for additional revisions.
*/
#ifndef VBOX
#ifdef _KERNEL
#else
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#endif
#ifdef _KERNEL
#else
#include "alias.h"
#include "alias_local.h"
#include "alias_mod.h"
#endif
#else /* !VBOX */
# include "alias.h"
# include "alias_local.h"
# include "alias_mod.h"
# include <slirp.h>
#endif /* VBOX */
#ifndef VBOX
#endif
/*
Constants (note: constants are also defined
near relevant functions or structs)
*/
/* Parameters used for cleanup of expired links */
/* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */
#define ALIAS_CLEANUP_INTERVAL_SECS 64
/* Timeouts (in seconds) for different link types */
#define ICMP_EXPIRE_TIME 60
#define UDP_EXPIRE_TIME 60
#define PROTO_EXPIRE_TIME 60
#define FRAGMENT_ID_EXPIRE_TIME 10
#define FRAGMENT_PTR_EXPIRE_TIME 30
/* TCP link expire time for different cases */
/* When the link has been used and closed - minimal grace time to
allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
#ifndef TCP_EXPIRE_DEAD
#define TCP_EXPIRE_DEAD 10
#endif
/* When the link has been used and closed on one side - the other side
is allowed to still send data */
#ifndef TCP_EXPIRE_SINGLEDEAD
#define TCP_EXPIRE_SINGLEDEAD 90
#endif
/* When the link isn't yet up */
#ifndef TCP_EXPIRE_INITIAL
#define TCP_EXPIRE_INITIAL 300
#endif
/* When the link is up */
#ifndef TCP_EXPIRE_CONNECTED
#define TCP_EXPIRE_CONNECTED 86400
#endif
/* Dummy port number codes used for FindLinkIn/Out() and AddLink().
These constants can be anything except zero, which indicates an
unknown port number. */
#define NO_DEST_PORT 1
#define NO_SRC_PORT 1
/* Data Structures
The fundamental data structure used in this program is
"struct alias_link". Whenever a TCP connection is made,
a UDP datagram is sent out, or an ICMP echo request is made,
a link record is made (if it has not already been created).
echo request, the source port is treated as being equivalent
with the 16-bit ID number of the ICMP packet.
The link record also can store some auxiliary data. For
TCP connections that have had sequence and acknowledgment
modifications, data space is available to track these changes.
A state field is used to keep track in changes to the TCP
connection state. ID numbers of fragments can also be
stored in the auxiliary space. Pointers to unresolved
fragments can also be stored.
The link records support two independent chainings. Lookup
tables for input and out tables hold the initial pointers
the link chains. On input, the lookup table indexes on alias
port and link type. On output, the lookup table indexes on
source address, destination address, source port, destination
port and link type.
*/
struct ack_data_record { /* used to save changes to ACK/sequence
* numbers */
int delta;
int active;
};
struct tcp_state { /* Information about TCP connection */
int in; /* State for outside -> inside */
int out; /* State for inside -> outside */
int index; /* Index to ACK data array */
int ack_modified; /* Indicates whether ACK and
* sequence numbers */
/* been modified */
};
* saved for a modified TCP stream */
struct tcp_dat {
int fwhole; /* Which firewall record is used for this
* hole? */
};
struct server { /* LSNAT server pool (circular list) */
};
struct alias_link { /* Main data structure */
struct in_addr alias_addr;
struct in_addr proxy_addr;
int link_type; /* Type of link: TCP, UDP, ICMP,
* proto, frag */
/* values for link_type */
#define LINK_ICMP IPPROTO_ICMP
#define LINK_UDP IPPROTO_UDP
#define LINK_TCP IPPROTO_TCP
int flags; /* indicates special characteristics */
int pflags; /* protocol-specific flags */
/* flag bits */
#define LINK_UNKNOWN_DEST_PORT 0x01
#define LINK_UNKNOWN_DEST_ADDR 0x02
#define LINK_PERMANENT 0x04
#define LINK_UNFIREWALLED 0x08
#ifndef VBOX
int timestamp; /* Time link was last accessed */
int expire_time; /* Expire time for link */
#else
unsigned int timestamp; /* Time link was last accessed */
unsigned int expire_time; /* Expire time for link */
#endif
#ifndef NO_USE_SOCKETS
# ifndef VBOX
/*
* in VBox we do not use host's sockets here, which are managed
* inside slirp. yes we have to create new sockets here but latter
* managment and deletion are in repsponsible of Slirp.
*/
int sockfd; /* socket descriptor */
# endif
#endif
* pointers for */
* lookup tables */
union { /* Auxiliary data */
char *frag_ptr;
} data;
};
/* Clean up procedure. */
#ifndef VBOX
static void finishoff(void);
#endif
/* Kernel module definition. */
#ifdef _KERNEL
static int
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
break;
case MOD_QUIESCE:
case MOD_UNLOAD:
finishoff();
error = 0;
break;
default:
}
return (error);
}
static moduledata_t alias_mod = {
};
#endif
/* Internal utility routines (used only in alias_db.c)
Lookup table starting points:
StartPointIn() -- link table initial search point for
incoming packets
StartPointOut() -- link table initial search point for
outgoing packets
Miscellaneous:
SeqDiff() -- difference between two TCP sequences
ShowAliasStats() -- send alias statistics to a monitor file
*/
/* Local prototypes */
static u_int
#ifndef NO_FW_PUNCH
/* Firewall control */
static void InitPunchFW(struct libalias *);
static void UninitPunchFW(struct libalias *);
static void ClearFWHole(struct alias_link *);
#endif
/* Log file control */
static void ShowAliasStats(struct libalias *);
static int InitPacketAliasLog(struct libalias *);
static void UninitPacketAliasLog(struct libalias *);
static u_int
int link_type)
{
u_int n;
n = alias_addr.s_addr;
n += alias_port;
n += link_type;
return (n % LINK_TABLE_IN_SIZE);
}
static u_int
{
u_int n;
n += src_port;
n += dst_port;
}
n += link_type;
return (n % LINK_TABLE_OUT_SIZE);
}
static int
{
/* Return the difference between two TCP sequence numbers */
/*
This function is encapsulated in case there are any unusual
arithmetic conditions that need to be considered.
*/
}
#ifdef _KERNEL
static void
{
}
#else
static void
{
# ifndef VBOX
# else
char buffer[1024];
/*make it grepable */
# endif
}
#endif
static void
{
/* Used for debugging */
"icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
#ifndef _KERNEL
#endif
}
}
/* Internal routines for finding, deleting and adding links
Port Allocation:
GetNewPort() -- find and reserve new alias port number
GetSocket() -- try to allocate a socket for a given port
Link creation and deletion:
CleanupAliasData() - remove all link chains from lookup table
IncrementalCleanup() - look for stale links in a single chain
DeleteLink() - remove link
AddLink() - add link
ReLink() - change link
Link search:
FindLinkOut() - find link for outgoing packets
FindLinkIn() - find link for incoming packets
Port search:
FindNewPortGroup() - find an available group of ports
*/
/* Local prototypes */
#ifndef NO_USE_SOCKETS
#endif
static void CleanupAliasData(struct libalias *);
static void IncrementalCleanup(struct libalias *);
static void DeleteLink(struct alias_link *);
static struct alias_link *
static struct alias_link *
ReLink(struct alias_link *,
static struct alias_link *
static struct alias_link *
#define ALIAS_PORT_BASE 0x08000
#define ALIAS_PORT_MASK 0x07fff
#define ALIAS_PORT_MASK_EVEN 0x07ffe
#define GET_NEW_PORT_MAX_ATTEMPTS 20
#define GET_ALIAS_PORT -1
#define GET_ALIAS_ID GET_ALIAS_PORT
#define FIND_EVEN_ALIAS_BASE 1
/* GetNewPort() allocates port numbers. Note that if a port number
is already in use, that does not mean that it cannot be used by
another link concurrently. This is because GetNewPort() looks for
unused triplets: (dest addr, dest port, alias port). */
static int
{
int i;
int max_trials;
/*
Description of alias_port_param for GetNewPort(). When
this parameter is zero or positive, it precisely specifies
the port number. GetNewPort() will return this number
without check that it is in use.
When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
selected port number.
*/
if (alias_port_param == GET_ALIAS_PORT) {
/*
* The aliasing port is automatically selected by one of
* two methods below:
*/
/*
* When the PKT_ALIAS_SAME_PORTS option is chosen,
* the first try will be the actual source port. If
* this is already in use, the remainder of the
* trials will be random.
*/
} else {
/* First trial and all subsequent are random. */
}
return (0);
} else {
#ifdef LIBALIAS_DEBUG
#endif
return (-1);
}
/* Port number search */
for (i = 0; i < max_trials; i++) {
int go_ahead;
struct alias_link *search_result;
if (search_result == NULL)
go_ahead = 1;
go_ahead = 1;
else
go_ahead = 0;
if (go_ahead) {
#ifndef NO_USE_SOCKETS
#ifndef VBOX
#else
#endif
return (0);
}
} else {
#endif
return (0);
#ifndef NO_USE_SOCKETS
}
#endif
}
}
#ifdef LIBALIAS_DEBUG
#endif
return (-1);
}
#ifndef NO_USE_SOCKETS
static u_short
{
int err;
int sock;
struct sockaddr_in sock_addr;
#ifdef VBOX
int opt = 1;
int status = 0;
#endif
#ifdef VBOX
{
return 0;
}
#endif
else {
#ifdef LIBALIAS_DEBUG
#endif
#ifdef VBOX
#endif
return (0);
}
if (sock < 0) {
#ifdef LIBALIAS_DEBUG
# ifndef VBOX
# else
# endif
#endif
return (0);
}
#ifdef VBOX
fd_nonblock(so->s);
#endif
#ifdef RT_OS_DARWIN
#endif
sizeof(sock_addr));
if (err == 0) {
#ifdef VBOX
{
closesocket(so->s);
return 0;
}
{
}
{
}
else {
Assert(!"Shouldn't be here");
}
#else
#endif
return (1);
} else {
#ifdef VBOX
if (sock > 0)
/* socket wasn't enqueued so we shouldn't use sofree */
#else
#endif
return (0);
}
}
#endif
/* FindNewPortGroup() returns a base port number for an available
range of contiguous port numbers. Note that if a port number
is already in use, that does not mean that it cannot be used by
another link concurrently. This is because FindNewPortGroup()
looks for unused triplets: (dest addr, dest port, alias port). */
int
struct in_addr alias_addr,
{
int i, j;
int max_trials;
int link_type;
/*
* Get link_type from protocol
*/
switch (proto) {
case IPPROTO_UDP:
break;
case IPPROTO_TCP:
break;
default:
return (0);
break;
}
/*
* The aliasing port is automatically selected by one of two
* methods below:
*/
/*
* When the ALIAS_SAME_PORTS option is chosen, the first
* try will be the actual source port. If this is already
* in use, the remainder of the trials will be random.
*/
} else {
/* First trial and all subsequent are random. */
if (align == FIND_EVEN_ALIAS_BASE)
else
}
/* Port number search */
for (i = 0; i < max_trials; i++) {
struct alias_link *search_result;
for (j = 0; j < port_count; j++)
link_type, 0)))
break;
/* Found a good range, return base */
if (j == port_count)
/* Find a new base to try */
if (align == FIND_EVEN_ALIAS_BASE)
else
}
#ifdef LIBALIAS_DEBUG
#endif
return (0);
}
static void
{
struct alias_link *lnk;
int i;
for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) {
}
}
la->cleanupIndex = 0;
}
static void
{
#ifndef VBOX
#else
/* libalias counts time in seconds while slirp in millis */
#endif
}
la->cleanupIndex = 0;
}
static void
{
/* Don't do anything if the link is marked permanent */
return;
#ifndef NO_FW_PUNCH
/* Delete associated firewall hole, if any */
#endif
/* Free memory allocated for LSNAT server pool */
do {
}
/* Adjust output table pointers */
/* Adjust input table pointers */
#ifndef NO_USE_SOCKETS
/* Close socket, if one has been allocated */
# ifndef VBOX
}
# else
/* Slirp will close the socket in its own way */
# endif
#endif
/* Link-type dependent cleanup */
case LINK_ICMP:
la->icmpLinkCount--;
break;
case LINK_UDP:
la->udpLinkCount--;
break;
case LINK_TCP:
la->tcpLinkCount--;
break;
case LINK_PPTP:
la->pptpLinkCount--;
break;
case LINK_FRAGMENT_ID:
break;
case LINK_FRAGMENT_PTR:
break;
case LINK_ADDR:
break;
default:
la->protoLinkCount--;
break;
}
/* Free memory */
/* Write statistics, if logging enabled */
}
}
static struct alias_link *
struct in_addr alias_addr,
int alias_port_param, /* if less than zero, alias */
int link_type)
{ /* port will be automatically *//* chosen.
* If greater than */
struct alias_link *lnk;
/* Basic initialization */
lnk->proxy_port = 0;
#ifndef NO_USE_SOCKETS
# ifndef VBOX
# endif
#endif
/* Expiration time */
switch (link_type) {
case LINK_ICMP:
break;
case LINK_UDP:
break;
case LINK_TCP:
break;
case LINK_PPTP:
break;
case LINK_FRAGMENT_ID:
break;
case LINK_FRAGMENT_PTR:
break;
case LINK_ADDR:
break;
default:
break;
}
/* Determine alias flags */
if (dst_port == 0)
/* Determine alias port */
return (NULL);
}
/* Link-type dependent initialization */
switch (link_type) {
case LINK_ICMP:
la->icmpLinkCount++;
break;
case LINK_UDP:
la->udpLinkCount++;
break;
case LINK_TCP:
int i;
la->tcpLinkCount++;
for (i = 0; i < N_LINK_TCP_DATA; i++)
} else {
#ifdef LIBALIAS_DEBUG
#endif
return (NULL);
}
break;
case LINK_PPTP:
la->pptpLinkCount++;
break;
case LINK_FRAGMENT_ID:
break;
case LINK_FRAGMENT_PTR:
break;
case LINK_ADDR:
break;
default:
la->protoLinkCount++;
break;
}
/* Set up pointers for output lookup table */
/* Set up pointers for input lookup table */
} else {
#ifdef LIBALIAS_DEBUG
#endif
}
}
return (lnk);
}
static struct alias_link *
struct in_addr alias_addr,
int alias_port_param, /* if less than zero, alias */
int link_type)
{ /* port will be automatically *//* chosen.
* If greater than */
#ifndef NO_FW_PUNCH
}
#endif
return (new_lnk);
}
static struct alias_link *
int link_type,
{
u_int i;
struct alias_link *lnk;
break;
}
}
/* Search for partially specified links. */
link_type, 0);
}
link_type, 0);
}
}
}
return (lnk);
}
static struct alias_link *
int link_type,
{
struct alias_link *lnk;
/*
* The following allows permanent links to be specified as
* using the default source address (i.e. device interface
* address) without knowing in advance what that address
* is.
*/
}
}
return (lnk);
}
static struct alias_link *
struct in_addr alias_addr,
int link_type,
{
int flags_in;
struct alias_link *lnk;
struct alias_link *lnk_fully_specified;
struct alias_link *lnk_unknown_all;
struct alias_link *lnk_unknown_dst_addr;
struct alias_link *lnk_unknown_dst_port;
/* Initialize pointers */
/* If either the dest addr or port is unknown, the search
loop will have to know about this. */
flags_in = 0;
if (dst_port == 0)
/* Search loop */
int flags;
if (!(flags & LINK_PARTIALLY_SPECIFIED)) {
break;
}
} else if ((flags & LINK_UNKNOWN_DEST_ADDR)
&& (flags & LINK_UNKNOWN_DEST_PORT)) {
if (lnk_unknown_all == NULL)
}
} else if (flags & LINK_UNKNOWN_DEST_ADDR) {
if (lnk_unknown_dst_addr == NULL)
}
} else if (flags & LINK_UNKNOWN_DEST_PORT) {
if (lnk_unknown_dst_port == NULL)
}
}
}
if (lnk_fully_specified != NULL) {
} else if (lnk_unknown_dst_port != NULL)
else if (lnk_unknown_dst_addr != NULL)
else if (lnk_unknown_all != NULL)
else
return (NULL);
if (replace_partial_links &&
} else {
}
}
return (lnk);
}
static struct alias_link *
struct in_addr alias_addr,
int link_type,
{
struct alias_link *lnk;
/*
* The following allows permanent links to be specified as
* using the default aliasing address (i.e. device
* interface address) without knowing in advance what that
* address is.
*/
}
}
return (lnk);
}
-- "external" means outside alias_db.c, but within alias*.c --
FindIcmpIn(), FindIcmpOut()
FindFragmentIn1(), FindFragmentIn2()
AddFragmentPtrLink(), FindFragmentPtr()
FindProtoIn(), FindProtoOut()
FindUdpTcpIn(), FindUdpTcpOut()
AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
FindOriginalAddress(), FindAliasAddress()
(prototypes in alias_local.h)
*/
struct alias_link *
struct in_addr alias_addr,
int create)
{
struct alias_link *lnk;
LINK_ICMP, 0);
struct in_addr target_addr;
}
return (lnk);
}
struct alias_link *
int create)
{
struct alias_link *lnk;
LINK_ICMP, 0);
struct in_addr alias_addr;
}
return (lnk);
}
struct alias_link *
struct in_addr alias_addr,
{
struct alias_link *lnk;
LINK_FRAGMENT_ID, 0);
}
return (lnk);
}
struct alias_link *
* one */
{
LINK_FRAGMENT_ID, 0);
}
struct alias_link *
{
}
struct alias_link *
{
LINK_FRAGMENT_PTR, 0);
}
struct alias_link *
struct in_addr alias_addr,
{
struct alias_link *lnk;
NO_DEST_PORT, 0,
proto, 1);
struct in_addr target_addr;
NO_SRC_PORT, NO_DEST_PORT, 0,
proto);
}
return (lnk);
}
struct alias_link *
{
struct alias_link *lnk;
proto, 1);
struct in_addr alias_addr;
NO_SRC_PORT, NO_DEST_PORT, 0,
proto);
}
return (lnk);
}
struct alias_link *
struct in_addr alias_addr,
int create)
{
int link_type;
struct alias_link *lnk;
switch (proto) {
case IPPROTO_UDP:
break;
case IPPROTO_TCP:
break;
default:
return (NULL);
break;
}
struct in_addr target_addr;
}
return (lnk);
}
struct alias_link *
int create)
{
int link_type;
struct alias_link *lnk;
switch (proto) {
case IPPROTO_UDP:
break;
case IPPROTO_TCP:
break;
default:
return (NULL);
break;
}
struct in_addr alias_addr;
}
return (lnk);
}
struct alias_link *
struct in_addr alias_addr,
{
struct alias_link *lnk;
return (lnk);
}
struct alias_link *
{
u_int i;
struct alias_link *lnk;
break;
return (lnk);
}
struct alias_link *
{
u_int i;
struct alias_link *lnk;
break;
return (lnk);
}
struct alias_link *
struct in_addr alias_addr,
{
u_int i;
struct alias_link *lnk;
break;
return (lnk);
}
struct alias_link *
struct in_addr alias_addr,
{
struct alias_link *lnk;
0 /* any */ , alias_call_id,
LINK_PPTP, 0);
return (lnk);
}
struct alias_link *
{
int link_type;
struct alias_link *lnk;
switch (proto) {
case IPPROTO_UDP:
break;
case IPPROTO_TCP:
break;
default:
return (NULL);
break;
}
struct in_addr alias_addr;
src_port, 0, alias_port,
}
return (lnk);
}
struct in_addr
{
struct alias_link *lnk;
0, 0, LINK_ADDR, 0);
return (alias_addr);
else
return (la->targetAddress);
} else {
return (src_addr);
else
}
}
struct in_addr
{
struct alias_link *lnk;
0, 0, LINK_ADDR, 0);
} else {
else
return (lnk->alias_addr);
}
}
/* External routines for getting or changing link data
(external to alias_db.c, but internal to alias*.c)
SetFragmentData(), GetFragmentData()
SetFragmentPtr(), GetFragmentPtr()
SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
GetOriginalPort(), GetAliasPort()
SetAckModified(), GetAckModified()
GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
SetProtocolFlags(), GetProtocolFlags()
SetDestCallId()
*/
void
{
}
void
{
}
void
{
}
void
{
}
void
{
/* TCP input state */
switch (state) {
else
break;
break;
default:
#ifdef _KERNEL
panic("libalias:SetStateIn() unknown state");
#else
abort();
#endif
}
}
void
{
/* TCP output state */
switch (state) {
else
break;
break;
default:
#ifdef _KERNEL
panic("libalias:SetStateOut() unknown state");
#else
abort();
#endif
}
}
int
{
/* TCP input state */
}
int
{
/* TCP output state */
}
struct in_addr
{
else
}
struct in_addr
{
}
struct in_addr
{
else
return (lnk->alias_addr);
}
struct in_addr
{
return (la->aliasAddress);
}
void
{
}
{
}
{
return (lnk->alias_port);
}
#ifndef NO_FW_PUNCH
static u_short
{
}
#endif
void
{
/* Indicate that ACK numbers have been modified in a TCP connection */
}
struct in_addr
{
return (lnk->proxy_addr);
}
void
{
}
{
return (lnk->proxy_port);
}
void
{
}
int
{
/* See if ACK numbers have been modified */
}
int
{
/*
Find out how much the ACK number has been altered for an incoming
TCP packet. To do this, a circular list of ACK numbers where the TCP
packet size was altered is searched.
*/
int i;
int delta, ack_diff_min;
delta = 0;
ack_diff_min = -1;
for (i = 0; i < N_LINK_TCP_DATA; i++) {
struct ack_data_record x;
if (x.active == 1) {
int ack_diff;
if (ack_diff >= 0) {
if (ack_diff_min >= 0) {
if (ack_diff < ack_diff_min) {
}
} else {
}
}
}
}
return (delta);
}
int
{
/*
Find out how much the sequence number has been altered for an outgoing
TCP packet. To do this, a circular list of ACK numbers where the TCP
packet size was altered is searched.
*/
int i;
int delta, seq_diff_min;
delta = 0;
seq_diff_min = -1;
for (i = 0; i < N_LINK_TCP_DATA; i++) {
struct ack_data_record x;
if (x.active == 1) {
int seq_diff;
if (seq_diff >= 0) {
if (seq_diff_min >= 0) {
if (seq_diff < seq_diff_min) {
}
} else {
}
}
}
}
return (delta);
}
void
{
/*
When a TCP packet has been altered in length, save this
information in a circular list. If enough packets have
been altered, then this list will begin to overwrite itself.
*/
struct ack_data_record x;
int i;
x.active = 1;
i++;
if (i == N_LINK_TCP_DATA)
else
}
void
{
if (expire == 0) {
} else if (expire == -1) {
} else if (expire > 0) {
} else {
#ifdef LIBALIAS_DEBUG
#endif
}
}
void
{
la->newDefaultLink = 0;
}
void
{
}
int
{
}
void
{
la->deleteAllLinks = 0;
}
/* Miscellaneous Functions
HouseKeeping()
InitPacketAliasLog()
UninitPacketAliasLog()
*/
/*
Whenever an outgoing or incoming packet is handled, HouseKeeping()
is called to find and remove timed-out aliasing links. Logic exists
to sweep through the entire table and linked list structure
every 60 seconds.
(prototype in alias_local.h)
*/
void
{
int i, n;
#ifndef VBOX
#ifndef _KERNEL
#endif
/*
* Save system time (seconds) in global variable timeStamp for use
* by other functions. This is done so as not to unnecessarily
* waste timeline by making system calls.
*/
#ifdef _KERNEL
#else
#endif
#else /* !VBOX */
#endif
/* Compute number of spokes (output table link chains) to cover */
#ifndef VBOX
#else
#endif
/* Handle different cases */
if (n > 0) {
if (n > ALIAS_CLEANUP_MAX_SPOKES)
for (i = 0; i < n; i++)
} else if (n < 0) {
#ifdef LIBALIAS_DEBUG
#endif
}
}
/* Init the log file and enable logging */
static int
{
#ifndef VBOX
#ifdef _KERNEL
;
#else
#endif
else
return (ENOMEM); /* log initialization failed */
#else
Log2(("NAT: PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n"));
#endif
}
return (1);
}
/* Close the log-file and disable logging. */
static void
{
#ifndef VBOX
#ifdef _KERNEL
#else
#endif
#endif /* !VBOX */
}
}
/* Outside world interfaces
-- "outside world" means other than alias*.c routines --
PacketAliasRedirectPort()
PacketAliasAddServer()
PacketAliasRedirectProto()
PacketAliasRedirectAddr()
PacketAliasRedirectDynamic()
PacketAliasRedirectDelete()
PacketAliasSetAddress()
PacketAliasInit()
PacketAliasUninit()
PacketAliasSetMode()
(prototypes in alias.h)
*/
/* Redirection from a specific public addr:port to a
private addr:port */
struct alias_link *
{
int link_type;
struct alias_link *lnk;
switch (proto) {
case IPPROTO_UDP:
break;
case IPPROTO_TCP:
break;
default:
#ifdef LIBALIAS_DEBUG
#endif
goto getout;
}
}
#ifdef LIBALIAS_DEBUG
else {
"call to AddLink() failed\n");
}
#endif
return (lnk);
}
/* Add server to the pool of servers */
int
{
int res;
(void)la;
else {
struct server *s;
}
res = 0;
} else
res = -1;
return (res);
}
/* Redirect packets of a given IP protocol from a specific
public address to a private address */
struct alias_link *
struct in_addr alias_addr,
{
struct alias_link *lnk;
NO_SRC_PORT, NO_DEST_PORT, 0,
proto);
}
#ifdef LIBALIAS_DEBUG
else {
"call to AddLink() failed\n");
}
#endif
return (lnk);
}
/* Static address translation */
struct alias_link *
struct in_addr alias_addr)
{
struct alias_link *lnk;
0, 0, 0,
}
#ifdef LIBALIAS_DEBUG
else {
"call to AddLink() failed\n");
}
#endif
return (lnk);
}
/* Mark the aliasing link dynamic */
int
{
int res;
(void)la;
res = -1;
else {
res = 0;
}
return (res);
}
void
{
/* This is a dangerous function to put in the API,
because an invalid pointer can crash the program. */
la->deleteAllLinks = 0;
}
void
{
}
void
{
}
#ifndef VBOX
static void
finishoff(void)
{
while (!LIST_EMPTY(&instancehead))
}
#endif
struct libalias *
#ifndef VBOX
#else
#endif
{
int i;
#ifndef VBOX
#ifndef _KERNEL
#endif
#endif /* !VBOX */
return (la);
#ifndef VBOX
#ifndef _KERNEL /* kernel cleans up on module unload */
if (LIST_EMPTY(&instancehead))
#endif
#endif /*!VBOX*/
#ifndef VBOX
#ifdef _KERNEL
#else
#endif
#else /* !VBOX */
#endif /* VBOX */
for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
} else {
la->deleteAllLinks = 0;
}
la->icmpLinkCount = 0;
la->udpLinkCount = 0;
la->tcpLinkCount = 0;
la->pptpLinkCount = 0;
la->protoLinkCount = 0;
la->fragmentIdLinkCount = 0;
la->fragmentPtrLinkCount = 0;
la->cleanupIndex = 0;
#ifndef NO_USE_SOCKETS
#endif
#ifndef NO_FW_PUNCH
#endif
#ifndef _KERNEL
#endif
return (la);
}
void
{
la->deleteAllLinks = 0;
#ifndef NO_FW_PUNCH
#endif
}
/* Change mode for some operations */
unsigned int
unsigned int flags, /* Which state to bring flags to */
unsigned int mask /* Mask of which flags to affect (use 0 to
* do a probe for flag values) */
)
{
int res = -1;
/* Enable logging? */
/* Do the enable */
goto getout;
} else
/* _Disable_ logging? */
}
#ifndef NO_FW_PUNCH
/* Start punching holes in the firewall? */
} else
/* Stop punching holes in the firewall? */
}
#endif
return (res);
}
int
{
int res;
return (res);
}
#ifndef NO_FW_PUNCH
/*****************
Code to support firewall punching. This shouldn't really be in this
file, but making variables global is evil too.
****************/
/* Firewall include files */
#include <string.h>
#include <err.h>
/*
* helper function, updates the pointer to cmd with the length
* of the current command, and also cleans up the first word of
* the new command in case it has been clobbered before.
*/
static ipfw_insn *
{
return (cmd);
}
/*
* A function to fill simple commands of size 1.
* Existing flags are preserved.
*/
static ipfw_insn *
{
}
static ipfw_insn *
{
}
static ipfw_insn *
{
}
static int
{
}
do { \
} /*lint -save -e717 */ while(0)/* lint -restore */
do { \
} /*lint -save -e717 */ while(0)/* lint -restore */
static void
{
if (la->fireWallField) {
if (la->fireWallFD < 0) {
}
}
}
static void
{
if (la->fireWallFD >= 0)
if (la->fireWallField)
}
/* Make a certain link go through the firewall */
void
{
int r; /* Result code */
int fwhole; /* Where to punch hole */
/* Don't do anything unless we are asked to */
la->fireWallFD < 0 ||
return;
/** Build rule **/
/* Find empty slot */
fwhole++);
fwhole++);
/* No rule point empty - we can't punch more holes. */
#ifdef LIBALIAS_DEBUG
#endif
return;
}
}
/* Start next search at next position */
/*
* generate two rules of the form
*
* add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
* accept tcp from DAddr DPort to OAddr OPort
*/
int i;
if (r)
if (r)
}
/* Indicate hole applied */
}
/* Remove a hole in a firewall associated with a particular alias
lnk. Calling this too often is harmless. */
static void
{
* hole? */
if (fwhole < 0)
return;
}
}
/* Clear out the entire range dedicated to firewall holes. */
static void
{
int i;
if (la->fireWallFD < 0)
return;
int r = i;
}
/* XXX: third arg correct here ? /phk */
}
#endif
void
{
#ifndef NO_FW_PUNCH
#endif
}
void
{
}