Module Name: src
Committed By: rmind
Date: Mon Sep 30 00:37:12 UTC 2019
Modified Files:
src/lib/libnpf: libnpf.3 npf.c npf.h
src/sys/net/npf: npf_ctl.c
src/usr.sbin/npf/npfctl: npf.conf.5 npf_build.c npf_parse.y npf_scan.l
npfctl.c npfctl.h
src/usr.sbin/npf/npftest: npftest.conf
Log Message:
libnpf/npfctl: support dynamic NAT rulesets using a name prefix.
To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/lib/libnpf/libnpf.3
cvs rdiff -u -r1.47 -r1.48 src/lib/libnpf/npf.c
cvs rdiff -u -r1.37 -r1.38 src/lib/libnpf/npf.h
cvs rdiff -u -r1.58 -r1.59 src/sys/net/npf/npf_ctl.c
cvs rdiff -u -r1.88 -r1.89 src/usr.sbin/npf/npfctl/npf.conf.5
cvs rdiff -u -r1.52 -r1.53 src/usr.sbin/npf/npfctl/npf_build.c
cvs rdiff -u -r1.49 -r1.50 src/usr.sbin/npf/npfctl/npf_parse.y
cvs rdiff -u -r1.29 -r1.30 src/usr.sbin/npf/npfctl/npf_scan.l
cvs rdiff -u -r1.62 -r1.63 src/usr.sbin/npf/npfctl/npfctl.c
cvs rdiff -u -r1.50 -r1.51 src/usr.sbin/npf/npfctl/npfctl.h
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/npf/npftest/npftest.conf
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libnpf/libnpf.3
diff -u src/lib/libnpf/libnpf.3:1.10 src/lib/libnpf/libnpf.3:1.11
--- src/lib/libnpf/libnpf.3:1.10 Wed Aug 21 21:45:47 2019
+++ src/lib/libnpf/libnpf.3 Mon Sep 30 00:37:11 2019
@@ -1,4 +1,4 @@
-.\" $NetBSD: libnpf.3,v 1.10 2019/08/21 21:45:47 rmind Exp $
+.\" $NetBSD: libnpf.3,v 1.11 2019/09/30 00:37:11 rmind Exp $
.\"
.\" Copyright (c) 2011-2019 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd August 21, 2019
+.Dd August 25, 2019
.Dt LIBNPF 3
.Os
.Sh NAME
@@ -108,6 +108,15 @@
.Fn npf_table_replace "int fd" "nl_table_t *tl" "npf_error_t *errinfo"
.Ft void
.Fn npf_table_destroy "nl_table_t *tl"
+.\" ---
+.Ft int
+.Fn npf_ruleset_add "int fd" "const char *name" "nl_rule_t *rl" "uint64_t *id"
+.Ft int
+.Fn npf_ruleset_remove "int fd" "const char *name" "uint64_t id"
+.Ft int
+.Fn npf_ruleset_remkey "int fd" "const char *name" "const void *key" "size_t len"
+.Ft int
+.Fn npf_ruleset_flush "int fd" "const char *name"
.\" -----
.Sh DESCRIPTION
The
@@ -352,7 +361,9 @@ Additionally,
may be specified to indicate the translation network;
otherwise, it should be set to
.Dv NPF_NO_NETMASK .
-In such case, a custom algorithm may need to be specified using the
+.Pp
+In order to use the translation network, a custom algorithm may need to
+be specified using the
.Fn npf_nat_setalgo
function.
.\" ---
@@ -368,6 +379,9 @@ Currently, the following algorithms are
Hash of the source and destination addresses.
.It Dv NPF_ALGO_RR
Round-robin for the translation addresses.
+.It Dv NPF_ALGO_NETMAP
+Network-to-network map as described below, but with state tracking.
+It is used when it is necessary to translate the ports.
.El
.Pp
The following are support with static NAT:
@@ -450,6 +464,39 @@ specified by
Destroy the specified table.
.El
.\" -----
+.Ss Ruleset interface
+.Bl -tag -width 4n
+.It Fn npf_ruleset_add "fd" "name" "rl" "id"
+Add a given rule, specified by
+.Fa rl ,
+into the dynamic ruleset named
+.Fa name .
+On success, return 0 and a unique rule ID in the
+.Fa id
+parameter.
+.It Fn npf_ruleset_remove "fd" "name" "id"
+Remove a rule from the dynamic ruleset, specified by
+.Fa name .
+The rule is specified by its unique ID in the
+.Fa id
+parameter.
+.It Fn npf_ruleset_remkey "fd" "name" "key" "len"
+Remove a rule from the dynamic ruleset, specified by
+.Fa name .
+The rule is specified by its key, in the
+.Fa key
+and
+.Fa len
+parameters.
+The key for the rule must have been set during its construction, using the
+.Fn npf_rule_setkey
+routine.
+.It Fn npf_ruleset_flush "fd" "name"
+Clear the dynamic ruleset, specified by
+.Fa name ,
+by removing all its rules.
+.El
+.\" -----
.Sh SEE ALSO
.Xr bpf 4 ,
.Xr npf 7 ,
Index: src/lib/libnpf/npf.c
diff -u src/lib/libnpf/npf.c:1.47 src/lib/libnpf/npf.c:1.48
--- src/lib/libnpf/npf.c:1.47 Wed Aug 21 21:45:47 2019
+++ src/lib/libnpf/npf.c Mon Sep 30 00:37:11 2019
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.47 2019/08/21 21:45:47 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.48 2019/09/30 00:37:11 rmind Exp $");
#include <sys/types.h>
#include <sys/mman.h>
@@ -401,14 +401,31 @@ npf_param_set(nl_config_t *ncf, const ch
* DYNAMIC RULESET INTERFACE.
*/
+static inline bool
+_npf_nat_ruleset_p(const char *name)
+{
+ return strncmp(name, NPF_RULESET_MAP_PREF,
+ sizeof(NPF_RULESET_MAP_PREF) - 1) == 0;
+}
+
int
npf_ruleset_add(int fd, const char *rname, nl_rule_t *rl, uint64_t *id)
{
+ const bool natset = _npf_nat_ruleset_p(rname);
nvlist_t *rule_dict = rl->rule_dict;
nvlist_t *ret_dict;
+ nvlist_add_number(rule_dict, "attr",
+ NPF_RULE_DYNAMIC | nvlist_take_number(rule_dict, "attr"));
+
+ if (natset && !dnvlist_get_bool(rule_dict, "nat-rule", false)) {
+ errno = EINVAL;
+ return errno;
+ }
nvlist_add_string(rule_dict, "ruleset-name", rname);
+ nvlist_add_bool(rule_dict, "nat-ruleset", natset);
nvlist_add_number(rule_dict, "command", NPF_CMD_RULE_ADD);
+
if (nvlist_xfer_ioctl(fd, IOC_NPF_RULE, rule_dict, &ret_dict) == -1) {
return errno;
}
@@ -419,11 +436,14 @@ npf_ruleset_add(int fd, const char *rnam
int
npf_ruleset_remove(int fd, const char *rname, uint64_t id)
{
+ const bool natset = _npf_nat_ruleset_p(rname);
nvlist_t *rule_dict = nvlist_create(0);
nvlist_add_string(rule_dict, "ruleset-name", rname);
+ nvlist_add_bool(rule_dict, "nat-ruleset", natset);
nvlist_add_number(rule_dict, "command", NPF_CMD_RULE_REMOVE);
nvlist_add_number(rule_dict, "id", id);
+
if (nvlist_send_ioctl(fd, IOC_NPF_RULE, rule_dict) == -1) {
return errno;
}
@@ -433,11 +453,14 @@ npf_ruleset_remove(int fd, const char *r
int
npf_ruleset_remkey(int fd, const char *rname, const void *key, size_t len)
{
+ const bool natset = _npf_nat_ruleset_p(rname);
nvlist_t *rule_dict = nvlist_create(0);
nvlist_add_string(rule_dict, "ruleset-name", rname);
+ nvlist_add_bool(rule_dict, "nat-ruleset", natset);
nvlist_add_number(rule_dict, "command", NPF_CMD_RULE_REMKEY);
nvlist_add_binary(rule_dict, "key", key, len);
+
if (nvlist_send_ioctl(fd, IOC_NPF_RULE, rule_dict) == -1) {
return errno;
}
@@ -447,10 +470,13 @@ npf_ruleset_remkey(int fd, const char *r
int
npf_ruleset_flush(int fd, const char *rname)
{
+ const bool natset = _npf_nat_ruleset_p(rname);
nvlist_t *rule_dict = nvlist_create(0);
nvlist_add_string(rule_dict, "ruleset-name", rname);
+ nvlist_add_bool(rule_dict, "nat-ruleset", natset);
nvlist_add_number(rule_dict, "command", NPF_CMD_RULE_FLUSH);
+
if (nvlist_send_ioctl(fd, IOC_NPF_RULE, rule_dict) == -1) {
return errno;
}
@@ -678,10 +704,12 @@ npf_rule_getcode(nl_rule_t *rl, int *typ
int
_npf_ruleset_list(int fd, const char *rname, nl_config_t *ncf)
{
+ const bool natset = _npf_nat_ruleset_p(rname);
nvlist_t *req, *ret;
req = nvlist_create(0);
nvlist_add_string(req, "ruleset-name", rname);
+ nvlist_add_bool(req, "nat-ruleset", natset);
nvlist_add_number(req, "command", NPF_CMD_RULE_LIST);
if (nvlist_xfer_ioctl(fd, IOC_NPF_RULE, req, &ret) == -1) {
Index: src/lib/libnpf/npf.h
diff -u src/lib/libnpf/npf.h:1.37 src/lib/libnpf/npf.h:1.38
--- src/lib/libnpf/npf.h:1.37 Wed Aug 21 21:45:47 2019
+++ src/lib/libnpf/npf.h Mon Sep 30 00:37:11 2019
@@ -56,6 +56,12 @@ typedef struct nl_ext nl_ext_t;
typedef signed long nl_iter_t;
/*
+ * Ruleset prefix(es).
+ */
+
+#define NPF_RULESET_MAP_PREF "map:"
+
+/*
* Extensions API types.
*/
typedef int (*npfext_initfunc_t)(void);
Index: src/sys/net/npf/npf_ctl.c
diff -u src/sys/net/npf/npf_ctl.c:1.58 src/sys/net/npf/npf_ctl.c:1.59
--- src/sys/net/npf/npf_ctl.c:1.58 Sun Aug 25 17:38:25 2019
+++ src/sys/net/npf/npf_ctl.c Mon Sep 30 00:37:11 2019
@@ -36,7 +36,7 @@
#ifdef _KERNEL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.58 2019/08/25 17:38:25 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.59 2019/09/30 00:37:11 rmind Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@@ -196,7 +196,7 @@ npf_mk_table(npf_t *npf, const nvlist_t
goto out;
}
- t = npf_table_create(name, (u_int)tid, type, blob, size);
+ t = npf_table_create(name, (unsigned)tid, type, blob, size);
if (t == NULL) {
NPF_ERR_DEBUG(errdict);
error = ENOMEM;
@@ -473,7 +473,7 @@ npf_mk_singlenat(npf_t *npf, const nvlis
KASSERT(rl != NULL);
*rlp = rl;
- /* If rule is named, it is a group with NAT policies. */
+ /* If this rule is named, then it is a group with NAT policies. */
if (dnvlist_get_string(nat, "name", NULL)) {
return 0;
}
@@ -816,7 +816,7 @@ npfctl_rule(npf_t *npf, u_long cmd, void
return error;
}
rcmd = dnvlist_get_number(npf_rule, "command", 0);
- natset = dnvlist_get_bool(npf_rule, "nat-rule", false);
+ natset = dnvlist_get_bool(npf_rule, "nat-ruleset", false);
ruleset_name = dnvlist_get_string(npf_rule, "ruleset-name", NULL);
if (!ruleset_name) {
error = EINVAL;
Index: src/usr.sbin/npf/npfctl/npf.conf.5
diff -u src/usr.sbin/npf/npfctl/npf.conf.5:1.88 src/usr.sbin/npf/npfctl/npf.conf.5:1.89
--- src/usr.sbin/npf/npfctl/npf.conf.5:1.88 Tue Jul 23 14:20:22 2019
+++ src/usr.sbin/npf/npfctl/npf.conf.5 Mon Sep 30 00:37:11 2019
@@ -1,4 +1,4 @@
-.\" $NetBSD: npf.conf.5,v 1.88 2019/07/23 14:20:22 wiz Exp $
+.\" $NetBSD: npf.conf.5,v 1.89 2019/09/30 00:37:11 rmind Exp $
.\"
.\" Copyright (c) 2009-2019 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd May 19, 2019
+.Dd August 25, 2019
.Dt NPF.CONF 5
.Os
.Sh NAME
@@ -356,6 +356,11 @@ redirecting the public port 9022 to the
.Pp
.Dl map $ext_if dynamic proto tcp 10.1.1.2 port 22 <- $ext_if port 9022
.Pp
+In the regular dynamic NAT case, it is also possible to disable port
+translation using the
+.Cm no-ports
+flag.
+.Pp
The translation address can also be dynamic, based on the interface.
The following would select the IPv4 address(es) currently assigned to the
interface:
@@ -528,13 +533,15 @@ table-def = "table" table-id "type" ( "i
# Mapping for address translation.
-map = "map" interface
+map = map-common | map-ruleset
+map-common = "map" interface
( "static" [ "algo" map-algo ] | "dynamic" )
[ map-flags ] [ proto ]
map-seg ( "->" | "<-" | "<->" ) map-seg
[ "pass" [ proto ] filt-opts ]
+map-ruleset = "map" "ruleset" group-opts
-map-algo = "npt66"
+map-algo = "ip-hash" | "round-robin" | "netmap" | "npt66"
map-flags = "no-ports"
map-seg = ( addr-mask | interface ) [ port-opts ]
Index: src/usr.sbin/npf/npfctl/npf_build.c
diff -u src/usr.sbin/npf/npfctl/npf_build.c:1.52 src/usr.sbin/npf/npfctl/npf_build.c:1.53
--- src/usr.sbin/npf/npfctl/npf_build.c:1.52 Sun Sep 29 18:51:08 2019
+++ src/usr.sbin/npf/npfctl/npf_build.c Mon Sep 30 00:37:11 2019
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.52 2019/09/29 18:51:08 rmind Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.53 2019/09/30 00:37:11 rmind Exp $");
#include <sys/types.h>
#define __FAVOR_BSD
@@ -537,16 +537,32 @@ npfctl_build_rproc(const char *name, npf
npf_rproc_insert(npf_conf, rp);
}
+/*
+ * npfctl_build_maprset: create and insert a NAT ruleset.
+ */
void
npfctl_build_maprset(const char *name, int attr, const char *ifname)
{
const int attr_di = (NPF_RULE_IN | NPF_RULE_OUT);
nl_rule_t *rl;
+ bool natset;
+ int err;
+
+ /* Validate the prefix. */
+ err = npfctl_nat_ruleset_p(name, &natset);
+ if (!natset) {
+ yyerror("NAT ruleset names must be prefixed with `"
+ NPF_RULESET_MAP_PREF "`");
+ }
+ if (err) {
+ yyerror("NAT ruleset is missing a name (only prefix found)");
+ }
/* If no direction is not specified, then both. */
if ((attr & attr_di) == 0) {
attr |= attr_di;
}
+
/* Allow only "in/out" attributes. */
attr = NPF_RULE_GROUP | NPF_RULE_DYNAMIC | (attr & attr_di);
rl = npf_rule_create(name, attr, ifname);
@@ -866,13 +882,22 @@ npfctl_build_natseg(int sd, int type, un
}
}
- if (nt1) {
- npf_rule_setprio(nt1, NPF_PRI_LAST);
- npf_nat_insert(npf_conf, nt1);
- }
- if (nt2) {
- npf_rule_setprio(nt2, NPF_PRI_LAST);
- npf_nat_insert(npf_conf, nt2);
+ if (npf_conf) {
+ if (nt1) {
+ npf_rule_setprio(nt1, NPF_PRI_LAST);
+ npf_nat_insert(npf_conf, nt1);
+ }
+ if (nt2) {
+ npf_rule_setprio(nt2, NPF_PRI_LAST);
+ npf_nat_insert(npf_conf, nt2);
+ }
+ } else {
+ // XXX/TODO: need to refactor a bit to enable this..
+ if (nt1 && nt2) {
+ errx(EXIT_FAILURE, "bidirectional NAT is currently "
+ "not yet supported in the dynamic rules");
+ }
+ the_rule = nt1 ? nt1 : nt2;
}
}
@@ -959,9 +984,13 @@ npfctl_ifnet_table(const char *ifname)
{
char tname[NPF_TABLE_MAXNAMELEN];
nl_table_t *tl;
- u_int tid;
+ unsigned tid;
snprintf(tname, sizeof(tname), NPF_IFNET_TABLE_PREF "%s", ifname);
+ if (!npf_conf) {
+ errx(EXIT_FAILURE, "expression `ifaddrs(%s)` is currently "
+ "not yet supported in dynamic rules", ifname);
+ }
tid = npfctl_table_getid(tname);
if (tid == (unsigned)-1) {
@@ -969,7 +998,7 @@ npfctl_ifnet_table(const char *ifname)
tl = npf_table_create(tname, tid, NPF_TABLE_IFADDR);
(void)npf_table_insert(npf_conf, tl);
}
- return npfvar_create_element(NPFVAR_TABLE, &tid, sizeof(u_int));
+ return npfvar_create_element(NPFVAR_TABLE, &tid, sizeof(unsigned));
}
/*
Index: src/usr.sbin/npf/npfctl/npf_parse.y
diff -u src/usr.sbin/npf/npfctl/npf_parse.y:1.49 src/usr.sbin/npf/npfctl/npf_parse.y:1.50
--- src/usr.sbin/npf/npfctl/npf_parse.y:1.49 Tue Jul 23 00:52:02 2019
+++ src/usr.sbin/npf/npfctl/npf_parse.y Mon Sep 30 00:37:11 2019
@@ -42,11 +42,11 @@
#define YYSTACKSIZE 4096
-int yyparsetarget;
+int yystarttoken;
const char * yyfilename;
extern int yylineno, yycolumn;
-extern int yylex(void);
+extern int yylex(int);
void
yyerror(const char *fmt, ...)
@@ -78,14 +78,6 @@ yyerror(const char *fmt, ...)
exit(EXIT_FAILURE);
}
-#define CHECK_PARSER_FILE \
- if (yyparsetarget != NPFCTL_PARSE_FILE) \
- yyerror("rule must be in the group");
-
-#define CHECK_PARSER_STRING \
- if (yyparsetarget != NPFCTL_PARSE_STRING) \
- yyerror("invalid rule syntax");
-
%}
/*
@@ -94,6 +86,17 @@ yyerror(const char *fmt, ...)
%expect 0
%expect-rr 0
+/*
+ * Depending on the mode of operation, set a different start symbol.
+ * Workaround yacc limitation by passing the start token.
+ */
+%start input
+%token RULE_ENTRY_TOKEN MAP_ENTRY_TOKEN
+%lex-param { int yystarttoken }
+
+/*
+ * General tokens.
+ */
%token ALG
%token ALGO
%token ALL
@@ -209,8 +212,9 @@ yyerror(const char *fmt, ...)
%%
input
- : { CHECK_PARSER_FILE } lines
- | { CHECK_PARSER_STRING } rule
+ : lines
+ | RULE_ENTRY_TOKEN rule
+ | MAP_ENTRY_TOKEN map
;
lines
Index: src/usr.sbin/npf/npfctl/npf_scan.l
diff -u src/usr.sbin/npf/npfctl/npf_scan.l:1.29 src/usr.sbin/npf/npfctl/npf_scan.l:1.30
--- src/usr.sbin/npf/npfctl/npf_scan.l:1.29 Tue Jul 23 00:52:02 2019
+++ src/usr.sbin/npf/npfctl/npf_scan.l Mon Sep 30 00:37:11 2019
@@ -39,7 +39,7 @@ int yycolumn;
#define YY_USER_ACTION yycolumn += yyleng;
-extern int yyparsetarget;
+extern int yystarttoken;
extern int yylineno;
extern const char * yyfilename;
extern int yyparse(void);
@@ -54,7 +54,7 @@ npfctl_parse_file(const char *name)
if (fp == NULL) {
err(EXIT_FAILURE, "open '%s'", name);
}
- yyparsetarget = NPFCTL_PARSE_FILE;
+ yystarttoken = 0;
yyrestart(fp);
yylineno = 1;
yycolumn = 0;
@@ -64,11 +64,21 @@ npfctl_parse_file(const char *name)
}
void
-npfctl_parse_string(const char *str)
+npfctl_parse_string(const char *str, parse_entry_t entry)
{
YY_BUFFER_STATE bs;
- yyparsetarget = NPFCTL_PARSE_STRING;
+ switch (entry) {
+ case NPFCTL_PARSE_RULE:
+ yystarttoken = RULE_ENTRY_TOKEN;
+ break;
+ case NPFCTL_PARSE_MAP:
+ yystarttoken = MAP_ENTRY_TOKEN;
+ break;
+ default:
+ abort();
+ }
+
bs = yy_scan_string(str);
yyfilename = "stdin";
yyparse();
@@ -85,6 +95,15 @@ NUMBER [0-9]+
HEXDIG [0-9a-fA-F]+
%%
+%{
+ /* This is prepended to yylex(). */
+ if (yystarttoken) {
+ int token = yystarttoken;
+ yystarttoken = 0;
+ return token;
+ }
+%}
+
alg return ALG;
table return TABLE;
type return TYPE;
Index: src/usr.sbin/npf/npfctl/npfctl.c
diff -u src/usr.sbin/npf/npfctl/npfctl.c:1.62 src/usr.sbin/npf/npfctl/npfctl.c:1.63
--- src/usr.sbin/npf/npfctl/npfctl.c:1.62 Sun Sep 29 16:58:35 2019
+++ src/usr.sbin/npf/npfctl/npfctl.c Mon Sep 30 00:37:11 2019
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: npfctl.c,v 1.62 2019/09/29 16:58:35 rmind Exp $");
+__RCSID("$NetBSD: npfctl.c,v 1.63 2019/09/30 00:37:11 rmind Exp $");
#include <sys/stat.h>
#include <sys/types.h>
@@ -54,8 +54,6 @@ __RCSID("$NetBSD: npfctl.c,v 1.62 2019/0
#include "npfctl.h"
-extern void npf_yyparse_string(const char *);
-
enum {
NPFCTL_START,
NPFCTL_STOP,
@@ -282,11 +280,9 @@ npfctl_print_addrmask(int alen, const ch
static int
npfctl_table_type(const char *typename)
{
- int i;
-
static const struct tbltype_s {
- const char *name;
- u_int type;
+ const char * name;
+ unsigned type;
} tbltypes[] = {
{ "ipset", NPF_TABLE_IPSET },
{ "lpm", NPF_TABLE_LPM },
@@ -294,12 +290,11 @@ npfctl_table_type(const char *typename)
{ NULL, 0 }
};
- for (i = 0; tbltypes[i].name != NULL; i++) {
+ for (unsigned i = 0; tbltypes[i].name != NULL; i++) {
if (strcmp(typename, tbltypes[i].name) == 0) {
return tbltypes[i].type;
}
}
-
return 0;
}
@@ -484,7 +479,7 @@ again:
}
static nl_rule_t *
-npfctl_parse_rule(int argc, char **argv)
+npfctl_parse_rule(int argc, char **argv, parse_entry_t entry)
{
char rule_string[1024];
nl_rule_t *rl;
@@ -493,7 +488,7 @@ npfctl_parse_rule(int argc, char **argv)
if (!join(rule_string, sizeof(rule_string), argc, argv, " ")) {
errx(EXIT_FAILURE, "command too long");
}
- npfctl_parse_string(rule_string);
+ npfctl_parse_string(rule_string, entry);
if ((rl = npfctl_rule_ref()) == NULL) {
errx(EXIT_FAILURE, "could not parse the rule");
}
@@ -528,6 +523,14 @@ npfctl_generate_key(nl_rule_t *rl, void
free(meta);
}
+int
+npfctl_nat_ruleset_p(const char *name, bool *natset)
+{
+ const size_t preflen = sizeof(NPF_RULESET_MAP_PREF) - 1;
+ *natset = strncmp(name, NPF_RULESET_MAP_PREF, preflen) == 0;
+ return (*natset && strlen(name) <= preflen) ? -1 : 0;
+}
+
static void
npfctl_rule(int fd, int argc, char **argv)
{
@@ -548,11 +551,12 @@ npfctl_rule(int fd, int argc, char **arg
const char *ruleset_name = argv[0];
const char *cmd = argv[1];
int error, action = 0;
+ bool extra_arg, natset;
+ parse_entry_t entry;
uint64_t rule_id;
- bool extra_arg;
nl_rule_t *rl;
- for (int n = 0; ruleops[n].cmd != NULL; n++) {
+ for (unsigned n = 0; ruleops[n].cmd != NULL; n++) {
if (strcmp(cmd, ruleops[n].cmd) == 0) {
action = ruleops[n].action;
extra_arg = ruleops[n].extra_arg;
@@ -566,15 +570,22 @@ npfctl_rule(int fd, int argc, char **arg
usage();
}
+ if (npfctl_nat_ruleset_p(ruleset_name, &natset) != 0) {
+ errx(EXIT_FAILURE,
+ "invalid NAT ruleset name (note: the name must be "
+ "prefixed with `" NPF_RULESET_MAP_PREF "`)");
+ }
+ entry = natset ? NPFCTL_PARSE_MAP : NPFCTL_PARSE_RULE;
+
switch (action) {
case NPF_CMD_RULE_ADD:
- rl = npfctl_parse_rule(argc, argv);
+ rl = npfctl_parse_rule(argc, argv, entry);
npfctl_generate_key(rl, key);
npf_rule_setkey(rl, key, sizeof(key));
error = npf_ruleset_add(fd, ruleset_name, rl, &rule_id);
break;
case NPF_CMD_RULE_REMKEY:
- rl = npfctl_parse_rule(argc, argv);
+ rl = npfctl_parse_rule(argc, argv, entry);
npfctl_generate_key(rl, key);
error = npf_ruleset_remkey(fd, ruleset_name, key, sizeof(key));
break;
Index: src/usr.sbin/npf/npfctl/npfctl.h
diff -u src/usr.sbin/npf/npfctl/npfctl.h:1.50 src/usr.sbin/npf/npfctl/npfctl.h:1.51
--- src/usr.sbin/npf/npfctl/npfctl.h:1.50 Sun Sep 29 16:58:35 2019
+++ src/usr.sbin/npf/npfctl/npfctl.h Mon Sep 30 00:37:11 2019
@@ -102,7 +102,11 @@ typedef struct proc_param {
const char * pp_value;
} proc_param_t;
-enum { NPFCTL_PARSE_FILE, NPFCTL_PARSE_STRING };
+typedef enum {
+ NPFCTL_PARSE_DEFAULT,
+ NPFCTL_PARSE_RULE,
+ NPFCTL_PARSE_MAP
+} parse_entry_t;
#define NPF_IFNET_TABLE_PREF ".ifnet-"
#define NPF_IFNET_TABLE_PREFLEN (sizeof(NPF_IFNET_TABLE_PREF) - 1)
@@ -111,7 +115,7 @@ bool join(char *, size_t, int, char **,
void yyerror(const char *, ...) __printflike(1, 2) __dead;
void npfctl_bpfjit(bool);
void npfctl_parse_file(const char *);
-void npfctl_parse_string(const char *);
+void npfctl_parse_string(const char *, parse_entry_t);
void npfctl_print_error(const npf_error_t *);
char * npfctl_print_addrmask(int, const char *, const npf_addr_t *,
@@ -136,6 +140,7 @@ npfvar_t * npfctl_parse_fam_addr_mask(co
bool npfctl_parse_cidr(char *, fam_addr_mask_t *, int *);
uint16_t npfctl_npt66_calcadj(npf_netmask_t, const npf_addr_t *,
const npf_addr_t *);
+int npfctl_nat_ruleset_p(const char *, bool *);
/*
* NPF extension loading.
Index: src/usr.sbin/npf/npftest/npftest.conf
diff -u src/usr.sbin/npf/npftest/npftest.conf:1.7 src/usr.sbin/npf/npftest/npftest.conf:1.8
--- src/usr.sbin/npf/npftest/npftest.conf:1.7 Tue Jul 23 00:52:02 2019
+++ src/usr.sbin/npf/npftest/npftest.conf Mon Sep 30 00:37:11 2019
@@ -1,4 +1,4 @@
-# $NetBSD: npftest.conf,v 1.7 2019/07/23 00:52:02 rmind Exp $
+# $NetBSD: npftest.conf,v 1.8 2019/09/30 00:37:11 rmind Exp $
$ext_if = "npftest0"
$int_if = "npftest1"
@@ -32,7 +32,7 @@ $net_b = 10.255.0.0/16
map $ext_if static algo npt66 $net6_inner <-> $net6_outer
map $ext_if static algo netmap $net_a <-> $net_b
-map ruleset "dynamic-nat" on $ext_if
+map ruleset "map:some-daemon" on $ext_if
group "ext" on $ext_if {
pass out final from $local_ip3