MFC: Add support for the libalias redirect functionality.
Submitted by: Vadim Goncharov <vadim_nuclight@mail.ru>
This commit is contained in:
parent
6195cc13a0
commit
28e6df5f37
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 6, 2005
|
||||
.Dd March 1, 2008
|
||||
.Dt NG_NAT 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -42,7 +42,6 @@ A
|
||||
node uses
|
||||
.Xr libalias 3
|
||||
engine for packet aliasing.
|
||||
At this moment it supports only the basic functionality of the library.
|
||||
.Sh HOOKS
|
||||
This node type has two hooks:
|
||||
.Bl -tag -width indent
|
||||
@ -81,7 +80,194 @@ struct ng_nat_mode {
|
||||
Configure target address for a node.
|
||||
When an incoming packet not associated with any pre-existing aliasing
|
||||
link arrives at the host machine, it will be sent to the specified address.
|
||||
.It Dv NGM_NAT_REDIRECT_PORT Pq Li redirectport
|
||||
Redirect incoming connections arriving to given port(s) to
|
||||
another host and port(s).
|
||||
The following
|
||||
.Vt "struct ng_nat_redirect_port"
|
||||
must be supplied as argument.
|
||||
.Bd -literal
|
||||
#define NG_NAT_DESC_LENGTH 64
|
||||
struct ng_nat_redirect_port {
|
||||
struct in_addr local_addr;
|
||||
struct in_addr alias_addr;
|
||||
struct in_addr remote_addr;
|
||||
uint16_t local_port;
|
||||
uint16_t alias_port;
|
||||
uint16_t remote_port;
|
||||
uint8_t proto;
|
||||
char description[NG_NAT_DESC_LENGTH];
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Redirection is assigned an unique ID which is returned as
|
||||
response to this message, and
|
||||
information about redirection added to
|
||||
list of static redirects which later can be retrieved by
|
||||
.Dv NGM_NAT_LIST_REDIRECTS
|
||||
message.
|
||||
.It Dv NGM_NAT_REDIRECT_ADDR Pq Li redirectaddr
|
||||
Redirect traffic for public IP address to a machine on the
|
||||
local network.
|
||||
This function is known as
|
||||
.Em static NAT .
|
||||
The following
|
||||
.Vt "struct ng_nat_redirect_addr"
|
||||
must be supplied as argument.
|
||||
.Bd -literal
|
||||
struct ng_nat_redirect_addr {
|
||||
struct in_addr local_addr;
|
||||
struct in_addr alias_addr;
|
||||
char description[NG_NAT_DESC_LENGTH];
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Unique ID for this redirection is returned as response to this message.
|
||||
.It Dv NGM_NAT_REDIRECT_PROTO Pq Li redirectproto
|
||||
Redirect incoming IP packets of protocol
|
||||
.Va proto
|
||||
(see
|
||||
.Xr protocols 5 )
|
||||
to a machine on the local network.
|
||||
The following
|
||||
.Vt "struct ng_nat_redirect_proto"
|
||||
must be supplied as argument.
|
||||
.Bd -literal
|
||||
struct ng_nat_redirect_proto {
|
||||
struct in_addr local_addr;
|
||||
struct in_addr alias_addr;
|
||||
struct in_addr remote_addr;
|
||||
uint8_t proto;
|
||||
char description[NG_NAT_DESC_LENGTH];
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Unique ID for this redirection is returned as response to this message.
|
||||
.It Dv NGM_NAT_REDIRECT_DYNAMIC Pq Li redirectdynamic
|
||||
Mark redirection with specified ID as dynamic, i.e., it will serve
|
||||
for exactly one next connection and then will be automatically
|
||||
deleted from internal links table.
|
||||
Only fully specified links can be made dynamic.
|
||||
The redirection with this ID is also immediately deleted from
|
||||
user-visible list of static redirects (available through
|
||||
.Dv NGM_NAT_LIST_REDIRECTS
|
||||
message).
|
||||
.It Dv NGM_NAT_REDIRECT_DELETE Pq Li redirectdelete
|
||||
Delete redirection with specified ID (currently active
|
||||
connections are not affected).
|
||||
.It Dv NGM_NAT_ADD_SERVER Pq Li addserver
|
||||
Add another server to a pool.
|
||||
This is used to transparently offload network load on a single server
|
||||
and distribute the load across a pool of servers, also known as
|
||||
.Em LSNAT
|
||||
(RFC 2391).
|
||||
The following
|
||||
.Vt "struct ng_nat_add_server"
|
||||
must be supplied as argument.
|
||||
.Bd -literal
|
||||
struct ng_nat_add_server {
|
||||
uint32_t id;
|
||||
struct in_addr addr;
|
||||
uint16_t port;
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
First, the redirection is set up by
|
||||
.Dv NGM_NAT_REDIRECT_PORT
|
||||
or
|
||||
.Dv NGM_NAT_REDIRECT_ADDR .
|
||||
Then, ID of that redirection is used in multiple
|
||||
.Dv NGM_NAT_ADD_SERVER
|
||||
messages to add necessary number of servers.
|
||||
For redirections created by
|
||||
.Dv NGM_NAT_REDIRECT_ADDR ,
|
||||
the
|
||||
.Va port
|
||||
is ignored and could have any value.
|
||||
Original redirection's parameters
|
||||
.Va local_addr
|
||||
and
|
||||
.Va local_port
|
||||
are also ignored after
|
||||
.Dv NGM_NAT_ADD_SERVER
|
||||
was used (they are effectively replaced by server pool).
|
||||
.It Dv NGM_NAT_LIST_REDIRECTS Pq Li listredirects
|
||||
Return list of configured static redirects as
|
||||
.Vt "struct ng_nat_list_redirects".
|
||||
.Bd -literal
|
||||
struct ng_nat_listrdrs_entry {
|
||||
uint32_t id; /* Anything except zero */
|
||||
struct in_addr local_addr;
|
||||
struct in_addr alias_addr;
|
||||
struct in_addr remote_addr;
|
||||
uint16_t local_port;
|
||||
uint16_t alias_port;
|
||||
uint16_t remote_port;
|
||||
uint16_t proto; /* Valid proto or NG_NAT_REDIRPROTO_ADDR */
|
||||
uint16_t lsnat; /* LSNAT servers count */
|
||||
char description[NG_NAT_DESC_LENGTH];
|
||||
};
|
||||
struct ng_nat_list_redirects {
|
||||
uint32_t total_count;
|
||||
struct ng_nat_listrdrs_entry redirects[];
|
||||
};
|
||||
#define NG_NAT_REDIRPROTO_ADDR (IPPROTO_MAX + 3)
|
||||
.Ed
|
||||
.Pp
|
||||
Entries of the
|
||||
.Va redirects
|
||||
array returned in the unified format for all redirect types.
|
||||
Ports are meaningful only if protocol is either TCP or UDP
|
||||
and
|
||||
.Em static NAT
|
||||
redirection (created by
|
||||
.Dv NGM_NAT_REDIRECT_ADDR )
|
||||
is indicated by
|
||||
.Va proto
|
||||
set to
|
||||
.Dv NG_NAT_REDIRPROTO_ADDR .
|
||||
If
|
||||
.Va lsnat
|
||||
servers counter is greater than zero, then
|
||||
.Va local_addr
|
||||
and
|
||||
.Va local_port
|
||||
are also meaningless.
|
||||
.It Dv NGM_NAT_PROXY_RULE Pq Li proxyrule
|
||||
Specify a transparent proxying rule (string must be
|
||||
supplied as argument).
|
||||
See
|
||||
.Xr libalias 3
|
||||
for details.
|
||||
.El
|
||||
.Pp
|
||||
In all redirection messages
|
||||
.Va local_addr
|
||||
and
|
||||
.Va local_port
|
||||
mean address and port of target machine in the internal network,
|
||||
respectively.
|
||||
If
|
||||
.Va alias_addr
|
||||
is zero, then default aliasing address (set by
|
||||
.Dv NGM_NAT_SET_IPADDR )
|
||||
is used.
|
||||
Connections can also be restricted to be accepted only
|
||||
from specific external machines by using non-zero
|
||||
.Va remote_addr
|
||||
and/or
|
||||
.Va remote_port .
|
||||
Each redirection assigned an ID which can be later used for
|
||||
redirection manipulation on individual basis (e.g., removal).
|
||||
This ID guaranteed to be unique until the node shuts down
|
||||
(it will not be reused after deletion), and is returned to
|
||||
user after making each new redirection or can be found in
|
||||
the stored list of all redirections.
|
||||
The
|
||||
.Va description
|
||||
passed to and from node unchanged, together with ID providing
|
||||
a way for several entities to concurrently manipulate
|
||||
redirections in automated way.
|
||||
.Sh SHUTDOWN
|
||||
This node shuts down upon receipt of a
|
||||
.Dv NGM_SHUTDOWN
|
||||
|
@ -65,7 +65,85 @@ static const struct ng_parse_struct_field ng_nat_mode_fields[]
|
||||
= NG_NAT_MODE_INFO;
|
||||
static const struct ng_parse_type ng_nat_mode_type = {
|
||||
&ng_parse_struct_type,
|
||||
ng_nat_mode_fields
|
||||
&ng_nat_mode_fields
|
||||
};
|
||||
|
||||
/* Parse type for 'description' field in structs. */
|
||||
static const struct ng_parse_fixedstring_info ng_nat_description_info
|
||||
= { NG_NAT_DESC_LENGTH };
|
||||
static const struct ng_parse_type ng_nat_description_type = {
|
||||
&ng_parse_fixedstring_type,
|
||||
&ng_nat_description_info
|
||||
};
|
||||
|
||||
/* Parse type for struct ng_nat_redirect_port. */
|
||||
static const struct ng_parse_struct_field ng_nat_redirect_port_fields[]
|
||||
= NG_NAT_REDIRECT_PORT_TYPE_INFO(&ng_nat_description_type);
|
||||
static const struct ng_parse_type ng_nat_redirect_port_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_nat_redirect_port_fields
|
||||
};
|
||||
|
||||
/* Parse type for struct ng_nat_redirect_addr. */
|
||||
static const struct ng_parse_struct_field ng_nat_redirect_addr_fields[]
|
||||
= NG_NAT_REDIRECT_ADDR_TYPE_INFO(&ng_nat_description_type);
|
||||
static const struct ng_parse_type ng_nat_redirect_addr_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_nat_redirect_addr_fields
|
||||
};
|
||||
|
||||
/* Parse type for struct ng_nat_redirect_proto. */
|
||||
static const struct ng_parse_struct_field ng_nat_redirect_proto_fields[]
|
||||
= NG_NAT_REDIRECT_PROTO_TYPE_INFO(&ng_nat_description_type);
|
||||
static const struct ng_parse_type ng_nat_redirect_proto_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_nat_redirect_proto_fields
|
||||
};
|
||||
|
||||
/* Parse type for struct ng_nat_add_server. */
|
||||
static const struct ng_parse_struct_field ng_nat_add_server_fields[]
|
||||
= NG_NAT_ADD_SERVER_TYPE_INFO;
|
||||
static const struct ng_parse_type ng_nat_add_server_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_nat_add_server_fields
|
||||
};
|
||||
|
||||
/* Parse type for one struct ng_nat_listrdrs_entry. */
|
||||
static const struct ng_parse_struct_field ng_nat_listrdrs_entry_fields[]
|
||||
= NG_NAT_LISTRDRS_ENTRY_TYPE_INFO(&ng_nat_description_type);
|
||||
static const struct ng_parse_type ng_nat_listrdrs_entry_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_nat_listrdrs_entry_fields
|
||||
};
|
||||
|
||||
/* Parse type for 'redirects' array in struct ng_nat_list_redirects. */
|
||||
static int
|
||||
ng_nat_listrdrs_ary_getLength(const struct ng_parse_type *type,
|
||||
const u_char *start, const u_char *buf)
|
||||
{
|
||||
const struct ng_nat_list_redirects *lr;
|
||||
|
||||
lr = (const struct ng_nat_list_redirects *)
|
||||
(buf - offsetof(struct ng_nat_list_redirects, redirects));
|
||||
return lr->total_count;
|
||||
}
|
||||
|
||||
static const struct ng_parse_array_info ng_nat_listrdrs_ary_info = {
|
||||
&ng_nat_listrdrs_entry_type,
|
||||
&ng_nat_listrdrs_ary_getLength,
|
||||
NULL
|
||||
};
|
||||
static const struct ng_parse_type ng_nat_listrdrs_ary_type = {
|
||||
&ng_parse_array_type,
|
||||
&ng_nat_listrdrs_ary_info
|
||||
};
|
||||
|
||||
/* Parse type for struct ng_nat_list_redirects. */
|
||||
static const struct ng_parse_struct_field ng_nat_list_redirects_fields[]
|
||||
= NG_NAT_LIST_REDIRECTS_TYPE_INFO(&ng_nat_listrdrs_ary_type);
|
||||
static const struct ng_parse_type ng_nat_list_redirects_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_nat_list_redirects_fields
|
||||
};
|
||||
|
||||
/* List of commands and how to convert arguments to/from ASCII. */
|
||||
@ -91,6 +169,62 @@ static const struct ng_cmdlist ng_nat_cmdlist[] = {
|
||||
&ng_parse_ipaddr_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_NAT_COOKIE,
|
||||
NGM_NAT_REDIRECT_PORT,
|
||||
"redirectport",
|
||||
&ng_nat_redirect_port_type,
|
||||
&ng_parse_uint32_type
|
||||
},
|
||||
{
|
||||
NGM_NAT_COOKIE,
|
||||
NGM_NAT_REDIRECT_ADDR,
|
||||
"redirectaddr",
|
||||
&ng_nat_redirect_addr_type,
|
||||
&ng_parse_uint32_type
|
||||
},
|
||||
{
|
||||
NGM_NAT_COOKIE,
|
||||
NGM_NAT_REDIRECT_PROTO,
|
||||
"redirectproto",
|
||||
&ng_nat_redirect_proto_type,
|
||||
&ng_parse_uint32_type
|
||||
},
|
||||
{
|
||||
NGM_NAT_COOKIE,
|
||||
NGM_NAT_REDIRECT_DYNAMIC,
|
||||
"redirectdynamic",
|
||||
&ng_parse_uint32_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_NAT_COOKIE,
|
||||
NGM_NAT_REDIRECT_DELETE,
|
||||
"redirectdelete",
|
||||
&ng_parse_uint32_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_NAT_COOKIE,
|
||||
NGM_NAT_ADD_SERVER,
|
||||
"addserver",
|
||||
&ng_nat_add_server_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_NAT_COOKIE,
|
||||
NGM_NAT_LIST_REDIRECTS,
|
||||
"listredirects",
|
||||
NULL,
|
||||
&ng_nat_list_redirects_type
|
||||
},
|
||||
{
|
||||
NGM_NAT_COOKIE,
|
||||
NGM_NAT_PROXY_RULE,
|
||||
"proxyrule",
|
||||
&ng_parse_string_type,
|
||||
NULL
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@ -109,6 +243,14 @@ static struct ng_type typestruct = {
|
||||
NETGRAPH_INIT(nat, &typestruct);
|
||||
MODULE_DEPEND(ng_nat, libalias, 1, 1, 1);
|
||||
|
||||
/* Element for list of redirects. */
|
||||
struct ng_nat_rdr_lst {
|
||||
STAILQ_ENTRY(ng_nat_rdr_lst) entries;
|
||||
struct alias_link *lnk;
|
||||
struct ng_nat_listrdrs_entry rdr;
|
||||
};
|
||||
STAILQ_HEAD(rdrhead, ng_nat_rdr_lst);
|
||||
|
||||
/* Information we store for each node. */
|
||||
struct ng_nat_priv {
|
||||
node_p node; /* back pointer to node */
|
||||
@ -116,6 +258,9 @@ struct ng_nat_priv {
|
||||
hook_p out; /* hook for masquerading */
|
||||
struct libalias *lib; /* libalias handler */
|
||||
uint32_t flags; /* status flags */
|
||||
uint32_t rdrcount; /* number or redirects in list */
|
||||
uint32_t nextid; /* for next in turn in list */
|
||||
struct rdrhead redirhead; /* redirect list header */
|
||||
};
|
||||
typedef struct ng_nat_priv *priv_p;
|
||||
|
||||
@ -145,6 +290,11 @@ ng_nat_constructor(node_p node)
|
||||
(void )LibAliasSetMode(priv->lib, PKT_ALIAS_SAME_PORTS,
|
||||
PKT_ALIAS_SAME_PORTS);
|
||||
|
||||
/* Init redirects housekeeping. */
|
||||
priv->rdrcount = 0;
|
||||
priv->nextid = 1;
|
||||
STAILQ_INIT(&priv->redirhead);
|
||||
|
||||
/* Link structs together. */
|
||||
NG_NODE_SET_PRIVATE(node, priv);
|
||||
priv->node = node;
|
||||
@ -234,6 +384,277 @@ ng_nat_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
LibAliasSetTarget(priv->lib, *ia);
|
||||
}
|
||||
break;
|
||||
case NGM_NAT_REDIRECT_PORT:
|
||||
{
|
||||
struct ng_nat_rdr_lst *entry;
|
||||
struct ng_nat_redirect_port *const rp =
|
||||
(struct ng_nat_redirect_port *)msg->data;
|
||||
|
||||
if (msg->header.arglen < sizeof(*rp)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
|
||||
M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try actual redirect. */
|
||||
entry->lnk = LibAliasRedirectPort(priv->lib,
|
||||
rp->local_addr, htons(rp->local_port),
|
||||
rp->remote_addr, htons(rp->remote_port),
|
||||
rp->alias_addr, htons(rp->alias_port),
|
||||
rp->proto);
|
||||
|
||||
if (entry->lnk == NULL) {
|
||||
error = ENOMEM;
|
||||
FREE(entry, M_NETGRAPH);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Successful, save info in our internal list. */
|
||||
entry->rdr.local_addr = rp->local_addr;
|
||||
entry->rdr.alias_addr = rp->alias_addr;
|
||||
entry->rdr.remote_addr = rp->remote_addr;
|
||||
entry->rdr.local_port = rp->local_port;
|
||||
entry->rdr.alias_port = rp->alias_port;
|
||||
entry->rdr.remote_port = rp->remote_port;
|
||||
entry->rdr.proto = rp->proto;
|
||||
bcopy(rp->description, entry->rdr.description,
|
||||
NG_NAT_DESC_LENGTH);
|
||||
|
||||
/* Safety precaution. */
|
||||
entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
|
||||
|
||||
entry->rdr.id = priv->nextid++;
|
||||
priv->rdrcount++;
|
||||
|
||||
/* Link to list of redirects. */
|
||||
STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
|
||||
|
||||
/* Response with id of newly added entry. */
|
||||
NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
|
||||
if (resp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
|
||||
}
|
||||
break;
|
||||
case NGM_NAT_REDIRECT_ADDR:
|
||||
{
|
||||
struct ng_nat_rdr_lst *entry;
|
||||
struct ng_nat_redirect_addr *const ra =
|
||||
(struct ng_nat_redirect_addr *)msg->data;
|
||||
|
||||
if (msg->header.arglen < sizeof(*ra)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
|
||||
M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try actual redirect. */
|
||||
entry->lnk = LibAliasRedirectAddr(priv->lib,
|
||||
ra->local_addr, ra->alias_addr);
|
||||
|
||||
if (entry->lnk == NULL) {
|
||||
error = ENOMEM;
|
||||
FREE(entry, M_NETGRAPH);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Successful, save info in our internal list. */
|
||||
entry->rdr.local_addr = ra->local_addr;
|
||||
entry->rdr.alias_addr = ra->alias_addr;
|
||||
entry->rdr.proto = NG_NAT_REDIRPROTO_ADDR;
|
||||
bcopy(ra->description, entry->rdr.description,
|
||||
NG_NAT_DESC_LENGTH);
|
||||
|
||||
/* Safety precaution. */
|
||||
entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
|
||||
|
||||
entry->rdr.id = priv->nextid++;
|
||||
priv->rdrcount++;
|
||||
|
||||
/* Link to list of redirects. */
|
||||
STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
|
||||
|
||||
/* Response with id of newly added entry. */
|
||||
NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
|
||||
if (resp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
|
||||
}
|
||||
break;
|
||||
case NGM_NAT_REDIRECT_PROTO:
|
||||
{
|
||||
struct ng_nat_rdr_lst *entry;
|
||||
struct ng_nat_redirect_proto *const rp =
|
||||
(struct ng_nat_redirect_proto *)msg->data;
|
||||
|
||||
if (msg->header.arglen < sizeof(*rp)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
|
||||
M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try actual redirect. */
|
||||
entry->lnk = LibAliasRedirectProto(priv->lib,
|
||||
rp->local_addr, rp->remote_addr,
|
||||
rp->alias_addr, rp->proto);
|
||||
|
||||
if (entry->lnk == NULL) {
|
||||
error = ENOMEM;
|
||||
FREE(entry, M_NETGRAPH);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Successful, save info in our internal list. */
|
||||
entry->rdr.local_addr = rp->local_addr;
|
||||
entry->rdr.alias_addr = rp->alias_addr;
|
||||
entry->rdr.remote_addr = rp->remote_addr;
|
||||
entry->rdr.proto = rp->proto;
|
||||
bcopy(rp->description, entry->rdr.description,
|
||||
NG_NAT_DESC_LENGTH);
|
||||
|
||||
/* Safety precaution. */
|
||||
entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
|
||||
|
||||
entry->rdr.id = priv->nextid++;
|
||||
priv->rdrcount++;
|
||||
|
||||
/* Link to list of redirects. */
|
||||
STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
|
||||
|
||||
/* Response with id of newly added entry. */
|
||||
NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
|
||||
if (resp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
|
||||
}
|
||||
break;
|
||||
case NGM_NAT_REDIRECT_DYNAMIC:
|
||||
case NGM_NAT_REDIRECT_DELETE:
|
||||
{
|
||||
struct ng_nat_rdr_lst *entry;
|
||||
uint32_t *const id = (uint32_t *)msg->data;
|
||||
|
||||
if (msg->header.arglen < sizeof(*id)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find entry with supplied id. */
|
||||
STAILQ_FOREACH(entry, &priv->redirhead, entries) {
|
||||
if (entry->rdr.id == *id)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not found. */
|
||||
if (entry == NULL) {
|
||||
error = ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg->header.cmd == NGM_NAT_REDIRECT_DYNAMIC) {
|
||||
if (LibAliasRedirectDynamic(priv->lib,
|
||||
entry->lnk) == -1) {
|
||||
error = ENOTTY; /* XXX Something better? */
|
||||
break;
|
||||
}
|
||||
} else { /* NGM_NAT_REDIRECT_DELETE */
|
||||
LibAliasRedirectDelete(priv->lib, entry->lnk);
|
||||
}
|
||||
|
||||
/* Delete entry from our internal list. */
|
||||
priv->rdrcount--;
|
||||
STAILQ_REMOVE(&priv->redirhead, entry, ng_nat_rdr_lst, entries);
|
||||
FREE(entry, M_NETGRAPH);
|
||||
}
|
||||
break;
|
||||
case NGM_NAT_ADD_SERVER:
|
||||
{
|
||||
struct ng_nat_rdr_lst *entry;
|
||||
struct ng_nat_add_server *const as =
|
||||
(struct ng_nat_add_server *)msg->data;
|
||||
|
||||
if (msg->header.arglen < sizeof(*as)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find entry with supplied id. */
|
||||
STAILQ_FOREACH(entry, &priv->redirhead, entries) {
|
||||
if (entry->rdr.id == as->id)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not found. */
|
||||
if (entry == NULL) {
|
||||
error = ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (LibAliasAddServer(priv->lib, entry->lnk,
|
||||
as->addr, htons(as->port)) == -1) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
entry->rdr.lsnat++;
|
||||
}
|
||||
break;
|
||||
case NGM_NAT_LIST_REDIRECTS:
|
||||
{
|
||||
struct ng_nat_rdr_lst *entry;
|
||||
struct ng_nat_list_redirects *ary;
|
||||
int i = 0;
|
||||
|
||||
NG_MKRESPONSE(resp, msg, sizeof(*ary) +
|
||||
(priv->rdrcount) * sizeof(*entry), M_NOWAIT);
|
||||
if (resp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
ary = (struct ng_nat_list_redirects *)resp->data;
|
||||
ary->total_count = priv->rdrcount;
|
||||
|
||||
STAILQ_FOREACH(entry, &priv->redirhead, entries) {
|
||||
bcopy(&entry->rdr, &ary->redirects[i++],
|
||||
sizeof(struct ng_nat_listrdrs_entry));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NGM_NAT_PROXY_RULE:
|
||||
{
|
||||
char *cmd = (char *)msg->data;
|
||||
|
||||
if (msg->header.arglen < 6) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (LibAliasProxyRule(priv->lib, cmd) != 0)
|
||||
error = ENOMEM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error = EINVAL; /* unknown command */
|
||||
break;
|
||||
@ -361,6 +782,15 @@ ng_nat_shutdown(node_p node)
|
||||
|
||||
NG_NODE_SET_PRIVATE(node, NULL);
|
||||
NG_NODE_UNREF(node);
|
||||
|
||||
/* Free redirects list. */
|
||||
while (!STAILQ_EMPTY(&priv->redirhead)) {
|
||||
struct ng_nat_rdr_lst *entry = STAILQ_FIRST(&priv->redirhead);
|
||||
STAILQ_REMOVE_HEAD(&priv->redirhead, entries);
|
||||
FREE(entry, M_NETGRAPH);
|
||||
};
|
||||
|
||||
/* Final free. */
|
||||
LibAliasUninit(priv->lib);
|
||||
FREE(priv, M_NETGRAPH);
|
||||
|
||||
|
@ -53,8 +53,135 @@ struct ng_nat_mode {
|
||||
#define NG_NAT_PROXY_ONLY 0x40
|
||||
#define NG_NAT_REVERSE 0x80
|
||||
|
||||
#define NG_NAT_DESC_LENGTH 64
|
||||
#define NG_NAT_REDIRPROTO_ADDR (IPPROTO_MAX + 3) /* LibAlias' LINK_ADDR, also unused in in.h */
|
||||
|
||||
/* Arguments for NGM_NAT_REDIRECT_PORT message */
|
||||
struct ng_nat_redirect_port {
|
||||
struct in_addr local_addr;
|
||||
struct in_addr alias_addr;
|
||||
struct in_addr remote_addr;
|
||||
uint16_t local_port;
|
||||
uint16_t alias_port;
|
||||
uint16_t remote_port;
|
||||
uint8_t proto;
|
||||
char description[NG_NAT_DESC_LENGTH];
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_NAT_REDIRECT_PORT_TYPE_INFO(desctype) { \
|
||||
{ "local_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "alias_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "remote_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "local_port", &ng_parse_uint16_type }, \
|
||||
{ "alias_port", &ng_parse_uint16_type }, \
|
||||
{ "remote_port", &ng_parse_uint16_type }, \
|
||||
{ "proto", &ng_parse_uint8_type }, \
|
||||
{ "description", (desctype) }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* Arguments for NGM_NAT_REDIRECT_ADDR message */
|
||||
struct ng_nat_redirect_addr {
|
||||
struct in_addr local_addr;
|
||||
struct in_addr alias_addr;
|
||||
char description[NG_NAT_DESC_LENGTH];
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_NAT_REDIRECT_ADDR_TYPE_INFO(desctype) { \
|
||||
{ "local_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "alias_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "description", (desctype) }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* Arguments for NGM_NAT_REDIRECT_PROTO message */
|
||||
struct ng_nat_redirect_proto {
|
||||
struct in_addr local_addr;
|
||||
struct in_addr alias_addr;
|
||||
struct in_addr remote_addr;
|
||||
uint8_t proto;
|
||||
char description[NG_NAT_DESC_LENGTH];
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_NAT_REDIRECT_PROTO_TYPE_INFO(desctype) { \
|
||||
{ "local_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "alias_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "remote_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "proto", &ng_parse_uint8_type }, \
|
||||
{ "description", (desctype) }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* Arguments for NGM_NAT_ADD_SERVER message */
|
||||
struct ng_nat_add_server {
|
||||
uint32_t id;
|
||||
struct in_addr addr;
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_NAT_ADD_SERVER_TYPE_INFO { \
|
||||
{ "id", &ng_parse_uint32_type }, \
|
||||
{ "addr", &ng_parse_ipaddr_type }, \
|
||||
{ "port", &ng_parse_uint16_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* List entry of array returned in NGM_NAT_LIST_REDIRECTS message */
|
||||
struct ng_nat_listrdrs_entry {
|
||||
uint32_t id; /* Anything except zero */
|
||||
struct in_addr local_addr;
|
||||
struct in_addr alias_addr;
|
||||
struct in_addr remote_addr;
|
||||
uint16_t local_port;
|
||||
uint16_t alias_port;
|
||||
uint16_t remote_port;
|
||||
uint16_t proto; /* Valid proto or NG_NAT_REDIRPROTO_ADDR */
|
||||
uint16_t lsnat; /* LSNAT servers count */
|
||||
char description[NG_NAT_DESC_LENGTH];
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_NAT_LISTRDRS_ENTRY_TYPE_INFO(desctype) { \
|
||||
{ "id", &ng_parse_uint32_type }, \
|
||||
{ "local_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "alias_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "remote_addr", &ng_parse_ipaddr_type }, \
|
||||
{ "local_port", &ng_parse_uint16_type }, \
|
||||
{ "alias_port", &ng_parse_uint16_type }, \
|
||||
{ "remote_port", &ng_parse_uint16_type }, \
|
||||
{ "proto", &ng_parse_uint16_type }, \
|
||||
{ "lsnat", &ng_parse_uint16_type }, \
|
||||
{ "description", (desctype) }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* Structure returned by NGM_NAT_LIST_REDIRECTS */
|
||||
struct ng_nat_list_redirects {
|
||||
uint32_t total_count;
|
||||
struct ng_nat_listrdrs_entry redirects[];
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_NAT_LIST_REDIRECTS_TYPE_INFO(redirtype) { \
|
||||
{ "total_count", &ng_parse_uint32_type }, \
|
||||
{ "redirects", (redirtype) }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
enum {
|
||||
NGM_NAT_SET_IPADDR = 1,
|
||||
NGM_NAT_SET_MODE,
|
||||
NGM_NAT_SET_TARGET,
|
||||
NGM_NAT_REDIRECT_PORT,
|
||||
NGM_NAT_REDIRECT_ADDR,
|
||||
NGM_NAT_REDIRECT_PROTO,
|
||||
NGM_NAT_REDIRECT_DYNAMIC,
|
||||
NGM_NAT_REDIRECT_DELETE,
|
||||
NGM_NAT_ADD_SERVER,
|
||||
NGM_NAT_LIST_REDIRECTS,
|
||||
NGM_NAT_PROXY_RULE,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user