v3: - no tokens are used for priority names, lookup is used instead - names and values are moved out to a structure - the helper function became unnecessary, thus I removed it -- 8< -- This patch adds the possibility to use textual names to set the chain priority to basic values so that numeric values do not need to be learnt any more for basic usage. Basic arithmetic can also be done with them to ease the addition of relatively higher/lower priority chains. Addition and substraction is possible. Values are also printed with their friendly name within the range of <basicprio> +- 10. Example: nft> add table x nft> add chain x y { type filter hook prerouting priority mangleprio; } nft> add chain x z { type filter hook prerouting priority mangleprio + 1; } nft> add chain x w { type filter hook prerouting priority mangleprio - 5; } nft> add chain x r { type filter hook prerouting priority filterprio + 10; } nft> add chain x t { type filter hook prerouting priority rawprio; } nft> add chain x q { type filter hook prerouting priority rawprio + 11; } nft> add chain x h { type filter hook prerouting priority 15; } nft> list ruleset table ip x { chain y { type filter hook prerouting priority mangle; policy accept; } chain z { type filter hook prerouting priority mangle + 1; policy accept; } chain w { type filter hook prerouting priority mangle - 5; policy accept; } chain r { type filter hook prerouting priority filter + 10; policy accept; } chain t { type filter hook prerouting priority raw; policy accept; } chain q { type filter hook prerouting priority -289; policy accept; } chain h { type filter hook prerouting priority 15; policy accept; } } nft> add chain x h { type filter hook rerouting priority first; } Error: priority name 'first' is invalid add chain x h { type filter hook prerouting priority first; } ^^^^^ Signed-off-by: Máté Eckl <ecklm94@xxxxxxxxx> --- include/rule.h | 1 + src/parser_bison.y | 24 ++++++++++++++++--- src/rule.c | 59 ++++++++++++++++++++++++++++++++++++++++++---- src/scanner.l | 2 ++ 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/include/rule.h b/include/rule.h index 909ff36..bed9c2a 100644 --- a/include/rule.h +++ b/include/rule.h @@ -193,6 +193,7 @@ struct chain { struct list_head rules; }; +extern int chain_std_prio_lookup(const char *std_prio_name); extern const char *chain_type_name_lookup(const char *name); extern const char *chain_hookname_lookup(const char *name); extern struct chain *chain_alloc(const char *name); diff --git a/src/parser_bison.y b/src/parser_bison.y index 98bfeba..d753fd9 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -21,6 +21,7 @@ #include <linux/netfilter/nf_conntrack_tuple_common.h> #include <linux/netfilter/nf_nat.h> #include <linux/netfilter/nf_log.h> +#include <linux/netfilter_ipv4.h> #include <netinet/ip_icmp.h> #include <netinet/icmp6.h> #include <libnftnl/common.h> @@ -182,6 +183,8 @@ int nft_lex(void *, void *, void *); %token AT "@" %token VMAP "vmap" +%token PLUS "+" + %token INCLUDE "include" %token DEFINE "define" %token REDEFINE "redefine" @@ -521,7 +524,7 @@ int nft_lex(void *, void *, void *); %destructor { handle_free(&$$); } table_spec tableid_spec chain_spec chainid_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec index_spec %type <handle> set_spec setid_spec set_identifier flowtable_identifier obj_spec objid_spec obj_identifier %destructor { handle_free(&$$); } set_spec setid_spec set_identifier obj_spec objid_spec obj_identifier -%type <val> family_spec family_spec_explicit chain_policy prio_spec +%type <val> family_spec family_spec_explicit chain_policy prio_spec standard_prio %type <string> dev_spec quota_unit %destructor { xfree($$); } dev_spec quota_unit @@ -1794,8 +1797,23 @@ hook_spec : TYPE STRING HOOK STRING dev_spec PRIORITY prio_spec } ; -prio_spec : NUM { $$ = $1; } - | DASH NUM { $$ = -$2; } +prio_spec : NUM { $$ = $1; } + | DASH NUM { $$ = -$2; } + | standard_prio + | standard_prio PLUS NUM { $$ = $1 + $3; } + | standard_prio DASH NUM { $$ = $1 - $3; } + ; + +standard_prio : STRING + { + int tmp = chain_std_prio_lookup($1); + if (tmp == NF_IP_PRI_LAST) { + erec_queue(error(&@$, "priority name '%s' is invalid", $1), + state->msgs); + YYERROR; + } + $$ = tmp; + } ; dev_spec : DEVICE STRING { $$ = $2; } diff --git a/src/rule.c b/src/rule.c index 56b956a..11d11b1 100644 --- a/src/rule.c +++ b/src/rule.c @@ -28,6 +28,7 @@ #include <netinet/ip.h> #include <linux/netfilter.h> #include <linux/netfilter_arp.h> +#include <linux/netfilter_ipv4.h> void handle_free(struct handle *h) { @@ -769,6 +770,56 @@ const char *chain_policy2str(uint32_t policy) return "unknown"; } +struct chain_prio_tag{ + int val; + const char *str; +}; + +const static struct chain_prio_tag chain_std_prios[] = { + { NF_IP_PRI_RAW, "raw" }, + { NF_IP_PRI_MANGLE, "mangle" }, + { NF_IP_PRI_NAT_DST, "dnat" }, + { NF_IP_PRI_FILTER, "filter" }, + { NF_IP_PRI_SECURITY, "security" }, + { NF_IP_PRI_NAT_SRC, "snat" }, +}; + +int chain_std_prio_lookup(const char *std_prio_name) { + long unsigned int i; + + for (i = 0; i < sizeof(chain_std_prios) / sizeof(struct chain_prio_tag); ++i) { + if (!strcmp(chain_std_prios[i].str, std_prio_name)) + return chain_std_prios[i].val; + } + return NF_IP_PRI_LAST; +} + +static const char *chain_prio2str(int prio) +{ + static char ret[256]; + char offstr[20]; + const int reach = 10; + size_t i; + + ret[0] = 0; + offstr[0] = 0; + for (i = 0; i < sizeof(chain_std_prios) / sizeof(struct chain_prio_tag); ++i) { + const int sdt_prio = chain_std_prios[i].val; + const char *sdt_prio_str = chain_std_prios[i].str; + if (prio >= sdt_prio - reach && prio <= sdt_prio + reach) { + int offset = prio - sdt_prio; + if (offset != 0) { + snprintf(offstr, sizeof(offstr), " %c %d", + offset > 0 ? '+' : '-', abs(offset)); + } + sprintf(ret, "%s%s", sdt_prio_str, offstr); + return ret; + } + } + sprintf(ret, "%d", prio); + return ret; +} + static void chain_print_declaration(const struct chain *chain, struct output_ctx *octx) { @@ -781,8 +832,8 @@ static void chain_print_declaration(const struct chain *chain, hooknum2str(chain->handle.family, chain->hooknum)); if (chain->dev != NULL) nft_print(octx, " device %s", chain->dev); - nft_print(octx, " priority %d; policy %s;\n", - chain->priority, chain_policy2str(chain->policy)); + nft_print(octx, " priority %s; policy %s;\n", + chain_prio2str(chain->priority), chain_policy2str(chain->policy)); } } @@ -806,9 +857,9 @@ void chain_print_plain(const struct chain *chain, struct output_ctx *octx) chain->handle.table.name, chain->handle.chain.name); if (chain->flags & CHAIN_F_BASECHAIN) { - nft_print(octx, " { type %s hook %s priority %d; policy %s; }", + nft_print(octx, " { type %s hook %s priority %s; policy %s; }", chain->type, chain->hookstr, - chain->priority, chain_policy2str(chain->policy)); + chain_prio2str(chain->priority), chain_policy2str(chain->policy)); } if (octx->handle > 0) nft_print(octx, " # handle %" PRIu64, chain->handle.handle.id); diff --git a/src/scanner.l b/src/scanner.l index ed01b5e..4fb3a39 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -232,6 +232,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "=" { return '='; } "vmap" { return VMAP; } +"+" { return PLUS; } + "include" { return INCLUDE; } "define" { return DEFINE; } "redefine" { return REDEFINE; } -- ecklm -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html