Module Name: src Committed By: rmind Date: Sun Sep 29 16:58:35 UTC 2019
Modified Files: src/usr.sbin/npf/npfctl: npfctl.8 npfctl.c npfctl.h Log Message: npfctl: implement table replace subcommand. Contributed by Timshel Knoll-Miller. To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/usr.sbin/npf/npfctl/npfctl.8 cvs rdiff -u -r1.61 -r1.62 src/usr.sbin/npf/npfctl/npfctl.c cvs rdiff -u -r1.49 -r1.50 src/usr.sbin/npf/npfctl/npfctl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/npf/npfctl/npfctl.8 diff -u src/usr.sbin/npf/npfctl/npfctl.8:1.21 src/usr.sbin/npf/npfctl/npfctl.8:1.22 --- src/usr.sbin/npf/npfctl/npfctl.8:1.21 Sat Jan 19 21:19:32 2019 +++ src/usr.sbin/npf/npfctl/npfctl.8 Sun Sep 29 16:58:35 2019 @@ -1,4 +1,4 @@ -.\" $NetBSD: npfctl.8,v 1.21 2019/01/19 21:19:32 rmind Exp $ +.\" $NetBSD: npfctl.8,v 1.22 2019/09/29 16:58:35 rmind Exp $ .\" .\" Copyright (c) 2009-2014 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 December 10, 2017 +.Dd August 26, 2019 .Dt NPFCTL 8 .Os .Sh NAME @@ -114,28 +114,50 @@ List all rules in the dynamic ruleset sp Remove all rules from the dynamic ruleset specified by .Ar name . .\" --- -.It Ic table Ar tid Ic add Aq Ar addr/mask +.It Ic table Ar name Ic add Aq Ar addr/mask In table -.Ar tid , +.Ar name , add the IP address and optionally netmask, specified by .Aq Ar addr/mask . Only the tables of type "lpm" support masks. -.It Ic table Ar tid Ic rem Aq Ar addr/mask +.It Ic table Ar name Ic rem Aq Ar addr/mask In table -.Ar tid , +.Ar name , remove the IP address and optionally netmask, specified by .Aq Ar addr/mask . Only the tables of type "lpm" support masks. -.It Ic table Ar tid Ic test Aq Ar addr +.It Ic table Ar name Ic test Aq Ar addr Query the table -.Ar tid +.Ar name for a specific IP address, specified by .Ar addr . If no mask is specified, a single host is assumed. -.It Ic table Ar tid Ic list +.It Ic table Ar name Ic list List all entries in the currently loaded table specified by -.Ar tid . +.Ar name . This operation is expensive and should be used with caution. +.It Ic table Ar name Ic replace Oo Fl n Ar newname Oc Oo Fl t Ar type Oc Aq Ar path +Replace the existing table specified by +.Ar name +with a new table built from the file specified by +.Ar path . +Optionally, the new table will: +.Bl -tag -width xxxxxxxxxx -compact -offset 3n +.It Fl n Ar newname +be named +.Ar newname , +effectively renaming the table. +If not specified, the name of the table being replaced will be used. +.It Fl n Ar type +be of type +.Ar type ; +currently supported types are +.Cm ipset , +.Cm lpm , +or +.Cm const . +If not specified, the type of the table being replaced will be used. +.El .\" --- .It Ic save Save the active configuration and a snapshot of the current connections. @@ -201,6 +223,13 @@ Addition and removal of entries in the t # npfctl table "vip" add 10.0.0.1 # npfctl table "vip" rem 182.168.0.0/24 .Ed +.Pp +Replacing the existing table which has ID "svr" +with a new const table populated from file "/tmp/npf_vps_new", +and renamed to "vps": +.Bd -literal -offset indent +# npfctl table "svr" replace -n "vps" -t const "/tmp/npf_vps_new" +.Ed .\" ----- .Sh SEE ALSO .Xr bpf 4 , Index: src/usr.sbin/npf/npfctl/npfctl.c diff -u src/usr.sbin/npf/npfctl/npfctl.c:1.61 src/usr.sbin/npf/npfctl/npfctl.c:1.62 --- src/usr.sbin/npf/npfctl/npfctl.c:1.61 Wed Aug 21 21:41:53 2019 +++ src/usr.sbin/npf/npfctl/npfctl.c Sun Sep 29 16:58:35 2019 @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npfctl.c,v 1.61 2019/08/21 21:41:53 rmind Exp $"); +__RCSID("$NetBSD: npfctl.c,v 1.62 2019/09/29 16:58:35 rmind Exp $"); #include <sys/stat.h> #include <sys/types.h> @@ -142,10 +142,14 @@ usage(void) "\t%s rule \"rule-name\" { list | flush }\n", progname); fprintf(stderr, - "\t%s table <tid> { add | rem | test } <address/mask>\n", + "\t%s table \"table-name\" { add | rem | test } <address/mask>\n", progname); fprintf(stderr, - "\t%s table <tid> { list | flush }\n", + "\t%s table \"table-name\" { list | flush }\n", + progname); + fprintf(stderr, + "\t%s table \"table-name\" replace [-n \"name\"]" + " [-t <type>] <table-file>\n", progname); fprintf(stderr, "\t%s save | load\n", @@ -275,7 +279,101 @@ npfctl_print_addrmask(int alen, const ch return buf; } -__dead static void +static int +npfctl_table_type(const char *typename) +{ + int i; + + static const struct tbltype_s { + const char *name; + u_int type; + } tbltypes[] = { + { "ipset", NPF_TABLE_IPSET }, + { "lpm", NPF_TABLE_LPM }, + { "const", NPF_TABLE_CONST }, + { NULL, 0 } + }; + + for (i = 0; tbltypes[i].name != NULL; i++) { + if (strcmp(typename, tbltypes[i].name) == 0) { + return tbltypes[i].type; + } + } + + return 0; +} + +static void +npfctl_table_replace(int fd, int argc, char **argv) +{ + const char *name, *newname, *path, *typename = NULL; + int c, tid = -1; + FILE *fp; + nl_config_t *ncf; + nl_table_t *t; + u_int type = 0; + + name = newname = argv[0]; + optind = 2; + while ((c = getopt(argc, argv, "n:t:")) != -1) { + switch (c) { + case 't': + typename = optarg; + break; + case 'n': + newname = optarg; + break; + default: + fprintf(stderr, + "Usage: %s table \"table-name\" replace " + "[-n \"name\"] [-t <type>] <table-file>\n", + getprogname()); + exit(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + + if (typename && (type = npfctl_table_type(typename)) == 0) { + errx(EXIT_FAILURE, "unsupported table type '%s'", typename); + } + + if (argc != 1) { + usage(); + } + + path = argv[0]; + if (strcmp(path, "-") == 0) { + path = "stdin"; + fp = stdin; + } else if ((fp = fopen(path, "r")) == NULL) { + err(EXIT_FAILURE, "open '%s'", path); + } + + /* Get existing config to lookup ID of existing table */ + if ((ncf = npf_config_retrieve(fd)) == NULL) { + err(EXIT_FAILURE, "npf_config_retrieve()"); + } + if ((t = npfctl_table_getbyname(ncf, name)) == NULL) { + errx(EXIT_FAILURE, + "table '%s' not found in the active configuration", name); + } + tid = npf_table_getid(t); + if (!type) { + type = npf_table_gettype(t); + } + npf_config_destroy(ncf); + + if ((t = npfctl_load_table(newname, tid, type, path, fp)) == NULL) { + err(EXIT_FAILURE, "table load failed"); + } + + if (npf_table_replace(fd, t, NULL)) { + err(EXIT_FAILURE, "npf_table_replace(<%s>)", name); + } +} + +static void npfctl_table(int fd, int argc, char **argv) { static const struct tblops_s { @@ -383,7 +481,6 @@ again: nct.nct_cmd == NPF_CMD_TABLE_LOOKUP ? "match" : "success"); } - exit(EXIT_SUCCESS); } static nl_rule_t * @@ -431,7 +528,7 @@ npfctl_generate_key(nl_rule_t *rl, void free(meta); } -__dead static void +static void npfctl_rule(int fd, int argc, char **argv) { static const struct ruleops_s { @@ -509,7 +606,6 @@ npfctl_rule(int fd, int argc, char **arg if (action == NPF_CMD_RULE_ADD) { printf("OK %" PRIx64 "\n", rule_id); } - exit(EXIT_SUCCESS); } static bool bpfjit = true; @@ -754,7 +850,11 @@ npfctl(int action, int argc, char **argv usage(); } argv += 2; - npfctl_table(fd, argc, argv); + if (strcmp(argv[1], "replace") == 0) { + npfctl_table_replace(fd, argc, argv); + } else { + npfctl_table(fd, argc, argv); + } break; case NPFCTL_RULE: if ((argc -= 2) < 2) { Index: src/usr.sbin/npf/npfctl/npfctl.h diff -u src/usr.sbin/npf/npfctl/npfctl.h:1.49 src/usr.sbin/npf/npfctl/npfctl.h:1.50 --- src/usr.sbin/npf/npfctl/npfctl.h:1.49 Thu Aug 8 21:29:15 2019 +++ src/usr.sbin/npf/npfctl/npfctl.h Sun Sep 29 16:58:35 2019 @@ -117,6 +117,7 @@ void npfctl_print_error(const npf_error char * npfctl_print_addrmask(int, const char *, const npf_addr_t *, npf_netmask_t); void npfctl_note_interface(const char *); +nl_table_t * npfctl_table_getbyname(nl_config_t *, const char *); unsigned npfctl_table_getid(const char *); const char * npfctl_table_getname(nl_config_t *, unsigned, bool *); int npfctl_protono(const char *); @@ -196,8 +197,11 @@ void npfctl_show_init(void); int npfctl_ruleset_show(int, const char *); nl_rule_t * npfctl_rule_ref(void); +nl_table_t * npfctl_table_ref(void); bool npfctl_debug_addif(const char *); +nl_table_t * npfctl_load_table(const char *, int, u_int, const char *, FILE *); + void npfctl_build_alg(const char *); void npfctl_build_rproc(const char *, npfvar_t *); void npfctl_build_group(const char *, int, const char *, bool);