]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: interpret the event type from the evaluation step
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 6 Oct 2014 16:03:27 +0000 (18:03 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 9 Oct 2014 12:10:58 +0000 (14:10 +0200)
Postpone the event type interpretation to the evaluation step.
This patch also fixes the combination of event and object types,
which was broken. The export code needed to be adjusted too.

The new and destroy are not tokens that can be recognized by
the scanner anymore, so this also implicitly restores 'ct state'.

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 a1d589002fcdb48df2d973bdf5ac82dce2108d32..936177b9e6c6cb4217bf6941bb5ae42755dcd776 100644 (file)
@@ -252,6 +252,8 @@ enum cmd_ops {
  * @CMD_OBJ_TABLE:     table
  * @CMD_OBJ_RULESET:   ruleset
  * @CMD_OBJ_EXPR:      expression
+ * @CMD_OBJ_MONITOR:   monitor
+ * @CMD_OBJ_EXPORT:    export
  */
 enum cmd_obj {
        CMD_OBJ_INVALID,
@@ -263,8 +265,38 @@ enum cmd_obj {
        CMD_OBJ_TABLE,
        CMD_OBJ_RULESET,
        CMD_OBJ_EXPR,
+       CMD_OBJ_MONITOR,
+       CMD_OBJ_EXPORT,
 };
 
+struct export {
+       uint32_t        format;
+};
+
+struct export *export_alloc(uint32_t format);
+void export_free(struct export *e);
+
+enum {
+       CMD_MONITOR_OBJ_ANY,
+       CMD_MONITOR_OBJ_TABLES,
+       CMD_MONITOR_OBJ_CHAINS,
+       CMD_MONITOR_OBJ_RULES,
+       CMD_MONITOR_OBJ_SETS,
+       CMD_MONITOR_OBJ_ELEMS,
+       CMD_MONITOR_OBJ_MAX
+};
+
+struct monitor {
+       struct location location;
+       uint32_t        format;
+       uint32_t        flags;
+       uint32_t        type;
+       const char      *event;
+};
+
+struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event);
+void monitor_free(struct monitor *m);
+
 /**
  * struct cmd - command statement
  *
@@ -292,10 +324,10 @@ struct cmd {
                struct rule     *rule;
                struct chain    *chain;
                struct table    *table;
+               struct monitor  *monitor;
+               struct export   *export;
        };
        const void              *arg;
-       uint32_t                format;
-       uint32_t                monitor_flags;
 };
 
 extern struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
index 602148c80d55f3c730e8cecf1258fc7fcad81abf..83ef749829413a9cf4694fa0868b4f9f8eea404d 100644 (file)
@@ -59,6 +59,8 @@ static int __fmtstring(4, 5) __stmt_binary_error(struct eval_ctx *ctx,
        __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)
+#define monitor_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,
@@ -1610,6 +1612,72 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
        }
 }
 
+enum {
+       CMD_MONITOR_EVENT_ANY,
+       CMD_MONITOR_EVENT_NEW,
+       CMD_MONITOR_EVENT_DEL,
+       CMD_MONITOR_EVENT_MAX
+};
+
+static uint32_t monitor_flags[CMD_MONITOR_EVENT_MAX][CMD_MONITOR_OBJ_MAX] = {
+       [CMD_MONITOR_EVENT_ANY] = {
+               [CMD_MONITOR_OBJ_ANY]           = 0xffffffff,
+               [CMD_MONITOR_OBJ_TABLES]        = (1 << NFT_MSG_NEWTABLE) |
+                                                 (1 << NFT_MSG_DELTABLE),
+               [CMD_MONITOR_OBJ_CHAINS]        = (1 << NFT_MSG_NEWCHAIN) |
+                                                 (1 << NFT_MSG_DELCHAIN),
+               [CMD_MONITOR_OBJ_RULES]         = (1 << NFT_MSG_NEWRULE) |
+                                                 (1 << NFT_MSG_DELRULE),
+               [CMD_MONITOR_OBJ_SETS]          = (1 << NFT_MSG_NEWSET) |
+                                                 (1 << NFT_MSG_DELSET),
+               [CMD_MONITOR_OBJ_ELEMS]         = (1 << NFT_MSG_NEWSETELEM) |
+                                                 (1 << NFT_MSG_DELSETELEM),
+       },
+       [CMD_MONITOR_EVENT_NEW] = {
+               [CMD_MONITOR_OBJ_ANY]           = (1 << NFT_MSG_NEWTABLE) |
+                                                 (1 << NFT_MSG_NEWCHAIN) |
+                                                 (1 << NFT_MSG_NEWRULE)  |
+                                                 (1 << NFT_MSG_NEWSET)   |
+                                                 (1 << NFT_MSG_NEWSETELEM),
+               [CMD_MONITOR_OBJ_TABLES]        = (1 << NFT_MSG_NEWTABLE),
+               [CMD_MONITOR_OBJ_CHAINS]        = (1 << NFT_MSG_NEWCHAIN),
+               [CMD_MONITOR_OBJ_RULES]         = (1 << NFT_MSG_NEWRULE),
+               [CMD_MONITOR_OBJ_SETS]          = (1 << NFT_MSG_NEWSET),
+               [CMD_MONITOR_OBJ_ELEMS]         = (1 << NFT_MSG_NEWSETELEM),
+       },
+       [CMD_MONITOR_EVENT_DEL] = {
+               [CMD_MONITOR_OBJ_ANY]           = (1 << NFT_MSG_DELTABLE) |
+                                                 (1 << NFT_MSG_DELCHAIN) |
+                                                 (1 << NFT_MSG_DELRULE)  |
+                                                 (1 << NFT_MSG_DELSET)   |
+                                                 (1 << NFT_MSG_DELSETELEM),
+               [CMD_MONITOR_OBJ_TABLES]        = (1 << NFT_MSG_DELTABLE),
+               [CMD_MONITOR_OBJ_CHAINS]        = (1 << NFT_MSG_DELCHAIN),
+               [CMD_MONITOR_OBJ_RULES]         = (1 << NFT_MSG_DELRULE),
+               [CMD_MONITOR_OBJ_SETS]          = (1 << NFT_MSG_DELSET),
+               [CMD_MONITOR_OBJ_ELEMS]         = (1 << NFT_MSG_DELSETELEM),
+       },
+};
+
+static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd)
+{
+       uint32_t event;
+
+       if (cmd->monitor->event == NULL)
+               event = CMD_MONITOR_EVENT_ANY;
+       else if (strcmp(cmd->monitor->event, "new") == 0)
+               event = CMD_MONITOR_EVENT_NEW;
+       else if (strcmp(cmd->monitor->event, "destroy") == 0)
+               event = CMD_MONITOR_EVENT_DEL;
+       else {
+               return monitor_error(ctx, cmd->monitor, "invalid event %s",
+                                    cmd->monitor->event);
+       }
+
+       cmd->monitor->flags = monitor_flags[event][cmd->monitor->type];
+       return 0;
+}
+
 int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
 {
 #ifdef DEBUG
@@ -1632,9 +1700,10 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
        case CMD_FLUSH:
        case CMD_RENAME:
        case CMD_EXPORT:
-       case CMD_MONITOR:
        case CMD_DESCRIBE:
                return 0;
+       case CMD_MONITOR:
+               return cmd_evaluate_monitor(ctx, cmd);
        default:
                BUG("invalid command operation %u\n", cmd->op);
        };
index aac25679630b5256d8f57d156bc9374d519bd86c..e813b258dde1a99ef014b918d3f2606f4354dc45 100644 (file)
@@ -198,9 +198,6 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token GOTO                    "goto"
 %token RETURN                  "return"
 
-%token NEW                     "new"
-%token DESTROY                 "destroy"
-
 %token CONSTANT                        "constant"
 %token INTERVAL                        "interval"
 %token ELEMENTS                        "elements"
@@ -532,7 +529,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <val>                    ct_key
 
 %type <val>                    export_format
-%type <val>                    monitor_event   monitor_object          monitor_format
+%type <string>                 monitor_event
+%destructor { xfree($$); }     monitor_event
+%type <val>                    monitor_object  monitor_format
 
 %%
 
@@ -798,89 +797,30 @@ rename_cmd                :       CHAIN           chain_spec      identifier
 export_cmd             :       export_format
                        {
                                struct handle h = { .family = NFPROTO_UNSPEC };
-                               $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_RULESET, &h, &@$, NULL);
-                               $$->format = $1;
+                               struct export *export = export_alloc($1);
+                               $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export);
                        }
                        ;
 
 monitor_cmd            :       monitor_event   monitor_object  monitor_format
                        {
                                struct handle h = { .family = NFPROTO_UNSPEC };
-                               $$ = cmd_alloc(CMD_MONITOR, CMD_OBJ_RULESET, &h, &@$, NULL);
-                               $$->monitor_flags = $1 & $2;
-                               $$->format = $3;
+                               struct monitor *m = monitor_alloc($3, $2, $1);
+                               m->location = @1;
+                               $$ = cmd_alloc(CMD_MONITOR, CMD_OBJ_MONITOR, &h, &@$, m);
                        }
                        ;
 
-monitor_event          :       /* empty */
-                       {
-                               $$ = (1 << NFT_MSG_NEWRULE)     |
-                                    (1 << NFT_MSG_DELRULE)     |
-                                    (1 << NFT_MSG_NEWSET)      |
-                                    (1 << NFT_MSG_DELSET)      |
-                                    (1 << NFT_MSG_NEWSETELEM)  |
-                                    (1 << NFT_MSG_DELSETELEM)  |
-                                    (1 << NFT_MSG_NEWCHAIN)    |
-                                    (1 << NFT_MSG_DELCHAIN)    |
-                                    (1 << NFT_MSG_NEWTABLE)    |
-                                    (1 << NFT_MSG_DELTABLE);
-                       }
-                       |       NEW
-                       {
-                               $$ = (1 << NFT_MSG_NEWTABLE)    |
-                                    (1 << NFT_MSG_NEWCHAIN)    |
-                                    (1 << NFT_MSG_NEWRULE)     |
-                                    (1 << NFT_MSG_NEWSET)      |
-                                    (1 << NFT_MSG_NEWSETELEM);
-                       }
-                       |       DESTROY
-                       {
-                               $$ = (1 << NFT_MSG_DELTABLE)    |
-                                    (1 << NFT_MSG_DELCHAIN)    |
-                                    (1 << NFT_MSG_DELRULE)     |
-                                    (1 << NFT_MSG_DELSET)      |
-                                    (1 << NFT_MSG_DELSETELEM);
-                       }
+monitor_event          :       /* empty */     { $$ = NULL; }
+                       |       STRING          { $$ = $1; }
                        ;
 
-monitor_object         :       /* empty */
-                       {
-                               $$ = (1 << NFT_MSG_NEWRULE)     |
-                                    (1 << NFT_MSG_DELRULE)     |
-                                    (1 << NFT_MSG_NEWSET)      |
-                                    (1 << NFT_MSG_DELSET)      |
-                                    (1 << NFT_MSG_NEWSETELEM)  |
-                                    (1 << NFT_MSG_DELSETELEM)  |
-                                    (1 << NFT_MSG_NEWCHAIN)    |
-                                    (1 << NFT_MSG_DELCHAIN)    |
-                                    (1 << NFT_MSG_NEWTABLE)    |
-                                    (1 << NFT_MSG_DELTABLE);
-                       }
-                       |       TABLES
-                       {
-                               $$ = (1 << NFT_MSG_NEWTABLE) |
-                                    (1 << NFT_MSG_DELTABLE);
-                       }
-                       |       CHAINS
-                       {
-                               $$ = (1 << NFT_MSG_NEWCHAIN) |
-                                    (1 << NFT_MSG_DELCHAIN);
-                       }
-                       |       SETS
-                       {
-                               $$ = (1 << NFT_MSG_NEWSET) |
-                                    (1 << NFT_MSG_DELSET);
-                       }
-                       |       RULES
-                       {
-                               $$ = (1 << NFT_MSG_NEWRULE) |
-                                    (1 << NFT_MSG_DELRULE);
-                       }
-                       |       ELEMENTS
-                       {
-                               $$ = (1 << NFT_MSG_NEWSETELEM) |
-                                    (1 << NFT_MSG_DELSETELEM);
-                       }
+monitor_object         :       /* empty */     { $$ = CMD_MONITOR_OBJ_ANY; }
+                       |       TABLES          { $$ = CMD_MONITOR_OBJ_TABLES; }
+                       |       CHAINS          { $$ = CMD_MONITOR_OBJ_CHAINS; }
+                       |       SETS            { $$ = CMD_MONITOR_OBJ_SETS; }
+                       |       RULES           { $$ = CMD_MONITOR_OBJ_RULES; }
+                       |       ELEMENTS        { $$ = CMD_MONITOR_OBJ_ELEMS; }
                        ;
 
 monitor_format         :       /* empty */     { $$ = NFT_OUTPUT_DEFAULT; }
index 43355eeb6fab5596587762f055e6feac2bc97c34..a79a420316b18382122754ebe00121eb0c21de93 100644 (file)
@@ -556,6 +556,39 @@ struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
        return cmd;
 }
 
+struct export *export_alloc(uint32_t format)
+{
+       struct export *export;
+
+       export = xmalloc(sizeof(struct export));
+       export->format = format;
+
+       return export;
+}
+
+void export_free(struct export *e)
+{
+       xfree(e);
+}
+
+struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event)
+{
+       struct monitor *mon;
+
+       mon = xmalloc(sizeof(struct monitor));
+       mon->format = format;
+       mon->type = type;
+       mon->event = event;
+       mon->flags = 0;
+
+       return mon;
+}
+
+void monitor_free(struct monitor *m)
+{
+       xfree(m);
+}
+
 void cmd_free(struct cmd *cmd)
 {
        handle_free(&cmd->handle);
@@ -579,6 +612,12 @@ void cmd_free(struct cmd *cmd)
                case CMD_OBJ_EXPR:
                        expr_free(cmd->expr);
                        break;
+               case CMD_OBJ_MONITOR:
+                       monitor_free(cmd->monitor);
+                       break;
+               case CMD_OBJ_EXPORT:
+                       export_free(cmd->export);
+                       break;
                default:
                        BUG("invalid command object type %u\n", cmd->obj);
                }
@@ -726,7 +765,7 @@ static int do_command_export(struct netlink_ctx *ctx, struct cmd *cmd)
        if (rs == NULL)
                return -1;
 
-       nft_ruleset_fprintf(stdout, rs, cmd->format, 0);
+       nft_ruleset_fprintf(stdout, rs, cmd->export->format, 0);
        fprintf(stdout, "\n");
 
        nft_ruleset_free(rs);
@@ -929,9 +968,9 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
         *  - new rules in default format
         *  - new elements
         */
-       if (((cmd->monitor_flags & (1 << NFT_MSG_NEWRULE)) &&
-           (cmd->format == NFT_OUTPUT_DEFAULT)) ||
-           (cmd->monitor_flags & (1 << NFT_MSG_NEWSETELEM)))
+       if (((cmd->monitor->flags & (1 << NFT_MSG_NEWRULE)) &&
+           (cmd->monitor->format == NFT_OUTPUT_DEFAULT)) ||
+           (cmd->monitor->flags & (1 << NFT_MSG_NEWSETELEM)))
                monhandler.cache_needed = true;
        else
                monhandler.cache_needed = false;
@@ -963,8 +1002,8 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
                }
        }
 
-       monhandler.monitor_flags = cmd->monitor_flags;
-       monhandler.format = cmd->format;
+       monhandler.monitor_flags = cmd->monitor->flags;
+       monhandler.format = cmd->monitor->format;
        monhandler.ctx = ctx;
        monhandler.loc = &cmd->location;
 
index 0955c4afa4eab068879fb9049966b7a1509176e0..b5d7d4f9afeac95ec514a5b8ac017e8890e55b2b 100644 (file)
@@ -261,9 +261,6 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "export"               { return EXPORT; }
 "monitor"              { return MONITOR; }
 
-"new"                  { return NEW; }
-"destroy"              { return DESTROY; }
-
 "position"             { return POSITION; }
 "comment"              { return COMMENT; }