diff --git a/usr.sbin/npf/npfctl/npf_build.c b/usr.sbin/npf/npfctl/npf_build.c index 6556e5aec067..490442934267 100644 --- a/usr.sbin/npf/npfctl/npf_build.c +++ b/usr.sbin/npf/npfctl/npf_build.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_build.c,v 1.5 2012/02/20 00:18:19 rmind Exp $ */ +/* $NetBSD: npf_build.c,v 1.6 2012/02/26 21:50:05 christos Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include -__RCSID("$NetBSD: npf_build.c,v 1.5 2012/02/20 00:18:19 rmind Exp $"); +__RCSID("$NetBSD: npf_build.c,v 1.6 2012/02/26 21:50:05 christos Exp $"); #include #include @@ -161,7 +161,7 @@ npfctl_build_fam(nc_ctx_t *nc, sa_family_t family, static void npfctl_build_vars(nc_ctx_t *nc, sa_family_t family, npfvar_t *vars, int opts) { - const int type = npfvar_get_type(vars); + const int type = npfvar_get_type(vars, 0); size_t i; npfctl_ncgen_group(nc); @@ -335,7 +335,7 @@ npfctl_build_rpcall(nl_rproc_t *rp, const char *name, npfvar_t *args) return; } - const int type = npfvar_get_type(arg->ma_opts); + const int type = npfvar_get_type(arg->ma_opts, 0); if (type != -1 && type != NPFVAR_NUM) { yyerror("option '%s' is not numeric", aval); } diff --git a/usr.sbin/npf/npfctl/npf_data.c b/usr.sbin/npf/npfctl/npf_data.c index 583ac8e482a0..4ce14be7e5c6 100644 --- a/usr.sbin/npf/npfctl/npf_data.c +++ b/usr.sbin/npf/npfctl/npf_data.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_data.c,v 1.10 2012/01/08 21:34:21 rmind Exp $ */ +/* $NetBSD: npf_data.c,v 1.11 2012/02/26 21:50:05 christos Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include -__RCSID("$NetBSD: npf_data.c,v 1.10 2012/01/08 21:34:21 rmind Exp $"); +__RCSID("$NetBSD: npf_data.c,v 1.11 2012/02/26 21:50:05 christos Exp $"); #include #include @@ -231,6 +231,45 @@ out: return NULL; } +npfvar_t * +npfctl_parse_port_range_variable(const char *v) +{ + npfvar_t *vp = npfvar_lookup(v); + in_port_t p; + port_range_t *pr; + size_t count = npfvar_get_count(vp); + npfvar_t *pvp = npfvar_create(".port_range"); + + for (size_t i = 0; i < count; i++) { + int type = npfvar_get_type(vp, i); + void *data = npfvar_get_data(vp, type, i); + switch (type) { + case NPFVAR_IDENTIFIER: + case NPFVAR_STRING: + p = npfctl_portno(data); + npfvar_add_elements(pvp, npfctl_parse_port_range(p, p)); + break; + case NPFVAR_PORT_RANGE: + pr = data; + npfvar_add_element(pvp, NPFVAR_PORT_RANGE, pr, + sizeof(*pr)); + break; + case NPFVAR_NUM: + p = *(unsigned long *)data; + npfvar_add_elements(pvp, npfctl_parse_port_range(p, p)); + break; + default: + yyerror("wrong variable '%s' type '%s' for port range", + v, npfvar_type(type)); + goto out; + } + } + return pvp; +out: + npfvar_destroy(pvp); + return NULL; +} + npfvar_t * npfctl_parse_iface(const char *ifname) { diff --git a/usr.sbin/npf/npfctl/npf_parse.y b/usr.sbin/npf/npfctl/npf_parse.y index 5e1253cbb7ad..8ece20931669 100644 --- a/usr.sbin/npf/npfctl/npf_parse.y +++ b/usr.sbin/npf/npfctl/npf_parse.y @@ -1,4 +1,4 @@ -/* $NetBSD: npf_parse.y,v 1.4 2012/02/26 21:14:50 rmind Exp $ */ +/* $NetBSD: npf_parse.y,v 1.5 2012/02/26 21:50:05 christos Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -213,6 +213,11 @@ list_elem npfvar_add_element(vp, NPFVAR_STRING, $1, strlen($1) + 1); npfvar_add_elements(cvar, vp); } + | NUM MINUS NUM + { + npfvar_t *vp = npfctl_parse_port_range($1, $3); + npfvar_add_elements(cvar, vp); + } | NUM { npfvar_t *vp = npfvar_create(".num"); @@ -569,7 +574,7 @@ addr_or_iface | VAR_ID { npfvar_t *vp = npfvar_lookup($1); - const int type = npfvar_get_type(vp); + const int type = npfvar_get_type(vp, 0); switch (type) { case NPFVAR_VAR_ID: @@ -606,6 +611,9 @@ port_range { $$ = npfctl_parse_port_range($2, $4); } + | PORT VAR_ID { + $$ = npfctl_parse_port_range_variable($2); + } | { $$ = NULL; @@ -683,7 +691,7 @@ ifindex | VAR_ID { npfvar_t *vp = npfvar_lookup($1); - const int type = npfvar_get_type(vp); + const int type = npfvar_get_type(vp, 0); switch (type) { case NPFVAR_VAR_ID: diff --git a/usr.sbin/npf/npfctl/npf_var.c b/usr.sbin/npf/npfctl/npf_var.c index 43de88b956d4..9a4f141aaf09 100644 --- a/usr.sbin/npf/npfctl/npf_var.c +++ b/usr.sbin/npf/npfctl/npf_var.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_var.c,v 1.3 2012/01/15 00:49:48 rmind Exp $ */ +/* $NetBSD: npf_var.c,v 1.4 2012/02/26 21:50:05 christos Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__RCSID("$NetBSD: npf_var.c,v 1.3 2012/01/15 00:49:48 rmind Exp $"); +__RCSID("$NetBSD: npf_var.c,v 1.4 2012/02/26 21:50:05 christos Exp $"); #include #include @@ -41,6 +41,7 @@ __RCSID("$NetBSD: npf_var.c,v 1.3 2012/01/15 00:49:48 rmind Exp $"); typedef struct npf_element { void * e_data; + int e_type; struct npf_element *e_next; } npf_element_t; @@ -105,6 +106,7 @@ npfvar_add_element(npfvar_t *vp, int type, const void *data, size_t len) vp->v_count++; el = zalloc(sizeof(*el)); el->e_data = zalloc(len); + el->e_type = type; memcpy(el->e_data, data, len); /* Preserve order of insertion. */ @@ -181,12 +183,6 @@ npfvar_get_count(const npfvar_t *vp) return vp ? vp->v_count : 0; } -int -npfvar_get_type(const npfvar_t *vp) -{ - return vp ? vp->v_type : -1; -} - static void * npfvar_get_data1(const npfvar_t *vp, int type, size_t idx, size_t level) { @@ -224,6 +220,43 @@ npfvar_get_data1(const npfvar_t *vp, int type, size_t idx, size_t level) return el->e_data; } +static int +npfvar_get_type1(const npfvar_t *vp, size_t idx, size_t level) +{ + npf_element_t *el; + + if (level >= var_num) { + yyerror("variable loop for '%s'", vp->v_key); + return -1; + } + + if (vp == NULL) + return -1; + + if (vp->v_count <= idx) { + yyerror("variable '%s' has only %zu elements, requested %zu", + vp->v_key, vp->v_count, idx); + return -1; + } + + el = vp->v_elements; + while (idx--) { + el = el->e_next; + } + + if (vp->v_type == NPFVAR_VAR_ID) { + npfvar_t *rvp = npfvar_lookup(el->e_data); + return npfvar_get_type1(rvp, 0, level + 1); + } + return el->e_type; +} + +int +npfvar_get_type(const npfvar_t *vp, size_t idx) +{ + return npfvar_get_type1(vp, idx, 0); +} + void * npfvar_get_data(const npfvar_t *vp, int type, size_t idx) { diff --git a/usr.sbin/npf/npfctl/npf_var.h b/usr.sbin/npf/npfctl/npf_var.h index bc75fce74981..65bbfde1c59d 100644 --- a/usr.sbin/npf/npfctl/npf_var.h +++ b/usr.sbin/npf/npfctl/npf_var.h @@ -1,4 +1,4 @@ -/* $NetBSD: npf_var.h,v 1.1 2012/01/08 21:34:21 rmind Exp $ */ +/* $NetBSD: npf_var.h,v 1.2 2012/02/26 21:50:05 christos Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -36,14 +36,14 @@ #define NPFVAR_IDENTIFIER 1 #define NPFVAR_VAR_ID 2 #define NPFVAR_NUM 3 +#define NPFVAR_PORT_RANGE 4 /* Note: primitive types are equivalent. */ -#define NPFVAR_PRIM NPFVAR_NUM -#define NPFVAR_TYPE(x) (((x) & ~NPFVAR_PRIM) ? (x) : 0) +#define NPFVAR_PRIM NPFVAR_PORT_RANGE +#define NPFVAR_TYPE(x) (((x) > NPFVAR_PRIM) ? (x) : 0) -#define NPFVAR_TABLE 4 -#define NPFVAR_FAM 5 -#define NPFVAR_PORT_RANGE 6 +#define NPFVAR_TABLE 5 +#define NPFVAR_FAM 6 #define NPFVAR_TCPFLAG 7 #define NPFVAR_ICMP 8 #define NPFVAR_PROC_OP 9 @@ -69,7 +69,7 @@ void npfvar_destroy(npfvar_t *); char * npfvar_expand_string(const npfvar_t *); size_t npfvar_get_count(const npfvar_t *); -int npfvar_get_type(const npfvar_t *); +int npfvar_get_type(const npfvar_t *, size_t); void * npfvar_get_data(const npfvar_t *, int, size_t); #endif diff --git a/usr.sbin/npf/npfctl/npfctl.h b/usr.sbin/npf/npfctl/npfctl.h index 2a33c829c3fa..3512a51a445b 100644 --- a/usr.sbin/npf/npfctl/npfctl.h +++ b/usr.sbin/npf/npfctl/npfctl.h @@ -1,4 +1,4 @@ -/* $NetBSD: npfctl.h,v 1.11 2012/02/05 00:37:13 rmind Exp $ */ +/* $NetBSD: npfctl.h,v 1.12 2012/02/26 21:50:05 christos Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -103,6 +103,7 @@ npfvar_t * npfctl_parse_icmpcode(const char *); npfvar_t * npfctl_parse_icmp(uint8_t, uint8_t); npfvar_t * npfctl_parse_iface(const char *); npfvar_t * npfctl_parse_port_range(in_port_t, in_port_t); +npfvar_t * npfctl_parse_port_range_variable(const char *); npfvar_t * npfctl_parse_fam_addr_mask(const char *, const char *, unsigned long *); fam_addr_mask_t *npfctl_parse_cidr(char *);