summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/ng_nat.4190
-rw-r--r--sys/netgraph/ng_nat.c432
-rw-r--r--sys/netgraph/ng_nat.h127
3 files changed, 746 insertions, 3 deletions
diff --git a/share/man/man4/ng_nat.4 b/share/man/man4/ng_nat.4
index dcb521f..cc89703 100644
--- a/share/man/man4/ng_nat.4
+++ b/share/man/man4/ng_nat.4
@@ -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
diff --git a/sys/netgraph/ng_nat.c b/sys/netgraph/ng_nat.c
index fb6e947..0d1e513 100644
--- a/sys/netgraph/ng_nat.c
+++ b/sys/netgraph/ng_nat.c
@@ -63,7 +63,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. */
@@ -89,6 +167,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 }
};
@@ -107,6 +241,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 */
@@ -114,6 +256,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;
@@ -143,6 +288,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;
@@ -232,6 +382,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;
@@ -359,6 +780,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);
diff --git a/sys/netgraph/ng_nat.h b/sys/netgraph/ng_nat.h
index a548cd2..f5eba59 100644
--- a/sys/netgraph/ng_nat.h
+++ b/sys/netgraph/ng_nat.h
@@ -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 }, \
+ { "udp", &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,
};
OpenPOWER on IntegriCloud