]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: Wrap netfilter hooks around human readable strings
authorTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Wed, 4 Sep 2013 09:50:19 +0000 (12:50 +0300)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 4 Sep 2013 10:31:17 +0000 (12:31 +0200)
This allows to use unique, human readable, hook names for the command
line and let the user being unaware of the complex netfilter's hook
names and there difference depending on the netfilter family.

So:
add chain foo bar { type route hook NF_INET_LOCAL_IN 0; }

becomes:
add chain foo bar { type route hook input 0; }

It also fixes then the difference in hook values between families.
I.e. ARP family has different values for input, forward and output
compared to IPv4, IPv6 or bridge.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/rule.h
src/evaluate.c
src/parser.y
src/rule.c
src/scanner.l

index 4f68431956830a44df023d866fb55fb3b70f6487..1de23dce6fd02a1d3945d02e4e0b7db84990c4e3 100644 (file)
@@ -98,6 +98,7 @@ enum chain_flags {
  * @handle:    chain handle
  * @location:  location the chain was defined at
  * @flags:     chain flags
+ * @hookstr:   unified and human readable hook name (base chains)
  * @hooknum:   hook number (base chains)
  * @priority:  hook priority (base chains)
  * @type:      chain type
@@ -108,6 +109,7 @@ struct chain {
        struct handle           handle;
        struct location         location;
        uint32_t                flags;
+       const char              *hookstr;
        unsigned int            hooknum;
        unsigned int            priority;
        const char              *type;
@@ -115,6 +117,7 @@ struct chain {
        struct list_head        rules;
 };
 
+extern const char *chain_hookname_lookup(const char *name);
 extern struct chain *chain_alloc(const char *name);
 extern void chain_free(struct chain *chain);
 extern void chain_add_hash(struct chain *chain, struct table *table);
index 85c647e5a590f6f54ea8dbef65a8ac07943ebd22..29fa32bd4aabf841af639d0372b07dd4f1a22722 100644 (file)
@@ -14,6 +14,8 @@
 #include <stdint.h>
 #include <string.h>
 #include <arpa/inet.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_arp.h>
 #include <linux/netfilter/nf_tables.h>
 
 #include <expression.h>
@@ -54,6 +56,8 @@ static int __fmtstring(4, 5) __stmt_binary_error(struct eval_ctx *ctx,
        __stmt_binary_error(ctx, &(s1)->location, NULL, fmt, ## args)
 #define stmt_binary_error(ctx, s1, s2, fmt, args...) \
        __stmt_binary_error(ctx, &(s1)->location, &(s2)->location, fmt, ## args)
+#define chain_error(ctx, s1, fmt, args...) \
+       __stmt_binary_error(ctx, &(s1)->location, NULL, fmt, ## args)
 
 static int __fmtstring(3, 4) set_error(struct eval_ctx *ctx,
                                       const struct set *set,
@@ -1247,10 +1251,49 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule)
        return 0;
 }
 
+static uint32_t str2hooknum(uint32_t family, const char *hook)
+{
+       switch (family) {
+       case NFPROTO_IPV4:
+       case NFPROTO_BRIDGE:
+       case NFPROTO_IPV6:
+               /* These families have overlapping values for each hook */
+               if (!strcmp(hook, "prerouting"))
+                       return NF_INET_PRE_ROUTING;
+               else if (!strcmp(hook, "input"))
+                       return NF_INET_LOCAL_IN;
+               else if (!strcmp(hook, "forward"))
+                       return NF_INET_FORWARD;
+               else if (!strcmp(hook, "postrouting"))
+                       return NF_INET_POST_ROUTING;
+               else if (!strcmp(hook, "output"))
+                       return NF_INET_LOCAL_OUT;
+       case NFPROTO_ARP:
+               if (!strcmp(hook, "input"))
+                       return NF_ARP_IN;
+               else if (!strcmp(hook, "forward"))
+                       return NF_ARP_FORWARD;
+               else if (!strcmp(hook, "output"))
+                       return NF_ARP_OUT;
+       default:
+               break;
+       }
+
+       return NF_INET_NUMHOOKS;
+}
+
 static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain)
 {
        struct rule *rule;
 
+       if (chain->flags & CHAIN_F_BASECHAIN) {
+               chain->hooknum = str2hooknum(chain->handle.family,
+                                            chain->hookstr);
+               if (chain->hooknum == NF_INET_NUMHOOKS)
+                       return chain_error(ctx, chain, "invalid hook %s",
+                                          chain->hookstr);
+       }
+
        list_for_each_entry(rule, &chain->rules, list) {
                handle_merge(&rule->handle, &chain->handle);
                if (rule_evaluate(ctx, rule) < 0)
index f0eb8e32bb36e3949740eb4d421bd79ffd53c7f7..ec78e7fdf56ba3fc289ff141597931b220f76269 100644 (file)
@@ -155,7 +155,6 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token DEFINE                  "define"
 
 %token HOOK                    "hook"
-%token <val> HOOKNUM           "hooknum"
 %token TABLE                   "table"
 %token TABLES                  "tables"
 %token CHAIN                   "chain"
@@ -550,6 +549,7 @@ add_cmd                     :       TABLE           table_spec
                        |       CHAIN           chain_spec      chain_block_alloc
                                                '{'     chain_block     '}'
                        {
+                               $5->location = @5;
                                handle_merge(&$3->handle, &$2);
                                close_scope(state);
                                $$ = cmd_alloc(CMD_ADD, CMD_OBJ_CHAIN, &$2, &@$, $5);
@@ -667,6 +667,7 @@ table_block         :       /* empty */     { $$ = $<table>-1; }
                                        chain_block_alloc       '{'     chain_block     '}'
                                        stmt_seperator
                        {
+                               $4->location = @3;
                                handle_merge(&$4->handle, &$3);
                                handle_free(&$3);
                                close_scope(state);
@@ -766,17 +767,27 @@ map_block         :       /* empty */     { $$ = $<set>-1; }
                        }
                        ;
 
-hook_spec              :       TYPE            STRING          HOOK            HOOKNUM         NUM
+hook_spec              :       TYPE            STRING          HOOK            STRING          NUM
                        {
                                $<chain>0->type         = $2;
-                               $<chain>0->hooknum      = $4;
+                               $<chain>0->hookstr      = chain_hookname_lookup($4);
+                               if ($<chain>0->hookstr == NULL) {
+                                       erec_queue(error(&@4, "unknown hook name %s", $4),
+                                                  state->msgs);
+                                       YYERROR;
+                               }
                                $<chain>0->priority     = $5;
                                $<chain>0->flags        |= CHAIN_F_BASECHAIN;
                        }
-                       |       TYPE            STRING          HOOK            HOOKNUM         DASH    NUM
+                       |       TYPE            STRING          HOOK            STRING          DASH    NUM
                        {
                                $<chain>0->type         = $2;
-                               $<chain>0->hooknum      = $4;
+                               $<chain>0->hookstr      = chain_hookname_lookup($4);
+                               if ($<chain>0->hookstr == NULL) {
+                                       erec_queue(error(&@4, "unknown hook name %s", $4),
+                                                  state->msgs);
+                                       YYERROR;
+                               }
                                $<chain>0->priority     = -$6;
                                $<chain>0->flags        |= CHAIN_F_BASECHAIN;
                        }
index 73054bada4ccf297762ae970ee27ea89de3e315a..f493cd48a6599dec749c37344b6a0692f1c8628f 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <netinet/ip.h>
 #include <linux/netfilter.h>
+#include <linux/netfilter_arp.h>
 
 void handle_free(struct handle *h)
 {
@@ -189,6 +190,27 @@ struct symbol *symbol_lookup(const struct scope *scope, const char *identifier)
        return NULL;
 }
 
+static const char *chain_hookname_str_array[] = {
+       "prerouting",
+       "input",
+       "forward",
+       "postrouting",
+       "output",
+       NULL,
+};
+
+const char *chain_hookname_lookup(const char *name)
+{
+       int i;
+
+       for (i = 0; chain_hookname_str_array[i]; i++) {
+               if (!strcmp(name, chain_hookname_str_array[i]))
+                       return chain_hookname_str_array[i];
+       }
+
+       return NULL;
+}
+
 struct chain *chain_alloc(const char *name)
 {
        struct chain *chain;
@@ -228,20 +250,43 @@ struct chain *chain_lookup(const struct table *table, const struct handle *h)
        return NULL;
 }
 
-static const char *hooknum2str_array[NF_INET_NUMHOOKS] = {
-       [NF_INET_PRE_ROUTING]   = "NF_INET_PRE_ROUTING",
-       [NF_INET_LOCAL_IN]      = "NF_INET_LOCAL_IN",
-       [NF_INET_FORWARD]       = "NF_INET_FORWARD",
-       [NF_INET_LOCAL_OUT]     = "NF_INET_LOCAL_OUT",
-       [NF_INET_POST_ROUTING]  = "NF_INET_POST_ROUTING",
-};
-
-static const char *hooknum2str(unsigned int hooknum)
-{
-       if (hooknum >= NF_INET_NUMHOOKS)
-               return "UNKNOWN";
+static const char *hooknum2str(unsigned int family, unsigned int hooknum)
+{
+       switch (family) {
+       case NFPROTO_IPV4:
+       case NFPROTO_BRIDGE:
+       case NFPROTO_IPV6:
+               switch (hooknum) {
+               case NF_INET_PRE_ROUTING:
+                       return "prerouting";
+               case NF_INET_LOCAL_IN:
+                       return "input";
+               case NF_INET_FORWARD:
+                       return "forward";
+               case NF_INET_POST_ROUTING:
+                       return "postrouting";
+               case NF_INET_LOCAL_OUT:
+                       return "output";
+               default:
+                       break;
+               };
+               break;
+       case NFPROTO_ARP:
+               switch (hooknum) {
+               case NF_ARP_IN:
+                       return "input";
+               case NF_ARP_FORWARD:
+                       return "forward";
+               case NF_ARP_OUT:
+                       return "output";
+               default:
+                       break;
+               }
+       default:
+               break;
+       };
 
-       return hooknum2str_array[hooknum];
+       return "unknown";
 }
 
 static void chain_print(const struct chain *chain)
@@ -251,7 +296,8 @@ static void chain_print(const struct chain *chain)
        printf("\tchain %s {\n", chain->handle.chain);
        if (chain->flags & CHAIN_F_BASECHAIN) {
                printf("\t\t type %s hook %s %u;\n", chain->type,
-                      hooknum2str(chain->hooknum), chain->priority);
+                      hooknum2str(chain->handle.family, chain->hooknum),
+                      chain->priority);
        }
        list_for_each_entry(rule, &chain->rules, list) {
                printf("\t\t");
index 59e0aac734d4b39d91e4419f325159289d504f0e..cee6aa6ee7553cc7840d81c968cab65b55492b8c 100644 (file)
@@ -212,12 +212,6 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
 "=>"                   { return ARROW; }
 "vmap"                 { return VMAP; }
 
-"NF_INET_PRE_ROUTING"  { yylval->val = NF_INET_PRE_ROUTING;    return HOOKNUM; }
-"NF_INET_LOCAL_IN"     { yylval->val = NF_INET_LOCAL_IN;       return HOOKNUM; }
-"NF_INET_FORWARD"      { yylval->val = NF_INET_FORWARD;        return HOOKNUM; }
-"NF_INET_LOCAL_OUT"    { yylval->val = NF_INET_LOCAL_OUT;      return HOOKNUM; }
-"NF_INET_POST_ROUTING" { yylval->val = NF_INET_POST_ROUTING;   return HOOKNUM; }
-
 "include"              { return INCLUDE; }
 "define"               { return DEFINE; }