iproute2: backport json_print-fix-hidden-64-bit-type-promotion
[oweals/openwrt.git] / package / network / utils / nftables / patches / 201-src-add-support-to-add-flowtables.patch
1 From: Pablo Neira Ayuso <pablo@netfilter.org>
2 Date: Thu, 18 Jan 2018 08:43:23 +0100
3 Subject: [PATCH] src: add support to add flowtables
4
5 This patch allows you to create flowtable:
6
7  # nft add table x
8  # nft add flowtable x m { hook ingress priority 10\; devices = { eth0, wlan0 }\; }
9
10 You have to specify hook and priority. So far, only the ingress hook is
11 supported. The priority represents where this flowtable is placed in the
12 ingress hook, which is registered to the devices that the user
13 specifies.
14
15 You can also use the 'create' command instead to bail out in case that
16 there is an existing flowtable with this name.
17
18 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
19 ---
20
21 --- a/include/expression.h
22 +++ b/include/expression.h
23 @@ -407,6 +407,8 @@ extern struct expr *prefix_expr_alloc(co
24  extern struct expr *range_expr_alloc(const struct location *loc,
25                                      struct expr *low, struct expr *high);
26  
27 +extern struct expr *compound_expr_alloc(const struct location *loc,
28 +                                       const struct expr_ops *ops);
29  extern void compound_expr_add(struct expr *compound, struct expr *expr);
30  extern void compound_expr_remove(struct expr *compound, struct expr *expr);
31  extern void list_expr_sort(struct list_head *head);
32 --- a/include/mnl.h
33 +++ b/include/mnl.h
34 @@ -92,6 +92,10 @@ int mnl_nft_obj_batch_del(struct nftnl_o
35  struct nftnl_flowtable_list *
36  mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table);
37  
38 +int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo,
39 +                               struct nftnl_batch *batch, unsigned int flags,
40 +                               uint32_t seqnum);
41 +
42  struct nftnl_ruleset *mnl_nft_ruleset_dump(struct netlink_ctx *ctx,
43                                            uint32_t family);
44  int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
45 --- a/include/netlink.h
46 +++ b/include/netlink.h
47 @@ -7,6 +7,7 @@
48  #include <libnftnl/expr.h>
49  #include <libnftnl/set.h>
50  #include <libnftnl/object.h>
51 +#include <libnftnl/flowtable.h>
52  
53  #include <linux/netlink.h>
54  #include <linux/netfilter/nf_tables.h>
55 @@ -182,6 +183,9 @@ extern int netlink_delete_obj(struct net
56  extern int netlink_list_flowtables(struct netlink_ctx *ctx,
57                                    const struct handle *h,
58                                    const struct location *loc);
59 +extern int netlink_add_flowtable(struct netlink_ctx *ctx,
60 +                                const struct handle *h, struct flowtable *ft,
61 +                                uint32_t flags);
62  
63  extern void netlink_dump_chain(const struct nftnl_chain *nlc,
64                                struct netlink_ctx *ctx);
65 --- a/include/rule.h
66 +++ b/include/rule.h
67 @@ -322,10 +322,13 @@ uint32_t obj_type_to_cmd(uint32_t type);
68  struct flowtable {
69         struct list_head        list;
70         struct handle           handle;
71 +       struct scope            scope;
72         struct location         location;
73 +       const char *            hookstr;
74         unsigned int            hooknum;
75         int                     priority;
76         const char              **dev_array;
77 +       struct expr             *dev_expr;
78         int                     dev_array_len;
79         unsigned int            refcnt;
80  };
81 @@ -383,6 +386,8 @@ enum cmd_ops {
82   * @CMD_OBJ_CHAIN:     chain
83   * @CMD_OBJ_CHAINS:    multiple chains
84   * @CMD_OBJ_TABLE:     table
85 + * @CMD_OBJ_FLOWTABLE: flowtable
86 + * @CMD_OBJ_FLOWTABLES:        flowtables
87   * @CMD_OBJ_RULESET:   ruleset
88   * @CMD_OBJ_EXPR:      expression
89   * @CMD_OBJ_MONITOR:   monitor
90 @@ -422,6 +427,7 @@ enum cmd_obj {
91         CMD_OBJ_CT_HELPERS,
92         CMD_OBJ_LIMIT,
93         CMD_OBJ_LIMITS,
94 +       CMD_OBJ_FLOWTABLE,
95         CMD_OBJ_FLOWTABLES,
96  };
97  
98 @@ -481,6 +487,7 @@ struct cmd {
99                 struct rule     *rule;
100                 struct chain    *chain;
101                 struct table    *table;
102 +               struct flowtable *flowtable;
103                 struct monitor  *monitor;
104                 struct markup   *markup;
105                 struct obj      *object;
106 --- a/src/evaluate.c
107 +++ b/src/evaluate.c
108 @@ -2897,6 +2897,24 @@ static int set_evaluate(struct eval_ctx
109         return 0;
110  }
111  
112 +static uint32_t str2hooknum(uint32_t family, const char *hook);
113 +
114 +static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft)
115 +{
116 +       struct table *table;
117 +
118 +       table = table_lookup_global(ctx);
119 +       if (table == NULL)
120 +               return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
121 +                                ctx->cmd->handle.table);
122 +
123 +       ft->hooknum = str2hooknum(NFPROTO_NETDEV, ft->hookstr);
124 +       if (ft->hooknum == NF_INET_NUMHOOKS)
125 +               return chain_error(ctx, ft, "invalid hook %s", ft->hookstr);
126 +
127 +       return 0;
128 +}
129 +
130  static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule)
131  {
132         struct stmt *stmt, *tstmt = NULL;
133 @@ -3069,6 +3087,14 @@ static int cmd_evaluate_add(struct eval_
134                 return chain_evaluate(ctx, cmd->chain);
135         case CMD_OBJ_TABLE:
136                 return table_evaluate(ctx, cmd->table);
137 +       case CMD_OBJ_FLOWTABLE:
138 +               ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op,
139 +                                  ctx->msgs, ctx->debug_mask & NFT_DEBUG_NETLINK, ctx->octx);
140 +               if (ret < 0)
141 +                       return ret;
142 +
143 +               handle_merge(&cmd->flowtable->handle, &cmd->handle);
144 +               return flowtable_evaluate(ctx, cmd->flowtable);
145         case CMD_OBJ_COUNTER:
146         case CMD_OBJ_QUOTA:
147         case CMD_OBJ_CT_HELPER:
148 --- a/src/expression.c
149 +++ b/src/expression.c
150 @@ -663,8 +663,8 @@ struct expr *range_expr_alloc(const stru
151         return expr;
152  }
153  
154 -static struct expr *compound_expr_alloc(const struct location *loc,
155 -                                       const struct expr_ops *ops)
156 +struct expr *compound_expr_alloc(const struct location *loc,
157 +                                const struct expr_ops *ops)
158  {
159         struct expr *expr;
160  
161 --- a/src/mnl.c
162 +++ b/src/mnl.c
163 @@ -1011,6 +1011,22 @@ err:
164         return NULL;
165  }
166  
167 +int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo,
168 +                               struct nftnl_batch *batch, unsigned int flags,
169 +                               uint32_t seqnum)
170 +{
171 +       struct nlmsghdr *nlh;
172 +
173 +       nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch),
174 +                                   NFT_MSG_NEWFLOWTABLE,
175 +                                   nftnl_flowtable_get_u32(flo, NFTNL_FLOWTABLE_FAMILY),
176 +                                   NLM_F_CREATE | flags, seqnum);
177 +       nftnl_flowtable_nlmsg_build_payload(nlh, flo);
178 +       mnl_nft_batch_continue(batch);
179 +
180 +       return 0;
181 +}
182 +
183  /*
184   * ruleset
185   */
186 --- a/src/netlink.c
187 +++ b/src/netlink.c
188 @@ -1773,6 +1773,64 @@ static struct obj *netlink_delinearize_o
189         return obj;
190  }
191  
192 +static struct nftnl_flowtable *alloc_nftnl_flowtable(const struct handle *h,
193 +                                                    const struct flowtable *ft)
194 +{
195 +       struct nftnl_flowtable *flo;
196 +
197 +       flo = nftnl_flowtable_alloc();
198 +       if (flo == NULL)
199 +               memory_allocation_error();
200 +
201 +       nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_FAMILY, h->family);
202 +       nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE, h->table);
203 +       if (h->flowtable != NULL)
204 +               nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME, h->flowtable);
205 +
206 +       return flo;
207 +}
208 +
209 +static void netlink_dump_flowtable(struct nftnl_flowtable *flo,
210 +                                  struct netlink_ctx *ctx)
211 +{
212 +       FILE *fp = ctx->octx->output_fp;
213 +
214 +       if (!(ctx->debug_mask & NFT_DEBUG_NETLINK) || !fp)
215 +               return;
216 +
217 +       nftnl_flowtable_fprintf(fp, flo, 0, 0);
218 +       fprintf(fp, "\n");
219 +}
220 +
221 +int netlink_add_flowtable(struct netlink_ctx *ctx, const struct handle *h,
222 +                         struct flowtable *ft, uint32_t flags)
223 +{
224 +       struct nftnl_flowtable *flo;
225 +       const char *dev_array[8];
226 +       struct expr *expr;
227 +       int i = 0, err;
228 +
229 +       flo = alloc_nftnl_flowtable(h, ft);
230 +       nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_HOOKNUM, ft->hooknum);
231 +       nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_PRIO, ft->priority);
232 +
233 +       list_for_each_entry(expr, &ft->dev_expr->expressions, list)
234 +               dev_array[i++] = expr->identifier;
235 +
236 +       dev_array[i] = NULL;
237 +       nftnl_flowtable_set_array(flo, NFTNL_FLOWTABLE_DEVICES, dev_array);
238 +
239 +       netlink_dump_flowtable(flo, ctx);
240 +
241 +       err = mnl_nft_flowtable_batch_add(flo, ctx->batch, flags, ctx->seqnum);
242 +       if (err < 0)
243 +               netlink_io_error(ctx, &ft->location, "Could not add flowtable: %s",
244 +                                strerror(errno));
245 +       nftnl_flowtable_free(flo);
246 +
247 +       return err;
248 +}
249 +
250  static int list_obj_cb(struct nftnl_obj *nls, void *arg)
251  {
252         struct netlink_ctx *ctx = arg;
253 --- a/src/parser_bison.y
254 +++ b/src/parser_bison.y
255 @@ -145,6 +145,7 @@ int nft_lex(void *, void *, void *);
256         struct expr             *expr;
257         struct set              *set;
258         struct obj              *obj;
259 +       struct flowtable        *flowtable;
260         struct counter          *counter;
261         struct quota            *quota;
262         struct ct               *ct;
263 @@ -189,6 +190,7 @@ int nft_lex(void *, void *, void *);
264  
265  %token HOOK                    "hook"
266  %token DEVICE                  "device"
267 +%token DEVICES                 "devices"
268  %token TABLE                   "table"
269  %token TABLES                  "tables"
270  %token CHAIN                   "chain"
271 @@ -200,6 +202,7 @@ int nft_lex(void *, void *, void *);
272  %token ELEMENT                 "element"
273  %token MAP                     "map"
274  %token MAPS                    "maps"
275 +%token FLOWTABLE               "flowtable"
276  %token HANDLE                  "handle"
277  %token RULESET                 "ruleset"
278  %token TRACE                   "trace"
279 @@ -500,9 +503,9 @@ int nft_lex(void *, void *, void *);
280  %type <cmd>                    base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd
281  %destructor { cmd_free($$); }  base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd
282  
283 -%type <handle>                 table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
284 -%destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
285 -%type <handle>                 set_spec set_identifier obj_spec obj_identifier
286 +%type <handle>                 table_spec chain_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
287 +%destructor { handle_free(&$$); } table_spec chain_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
288 +%type <handle>                 set_spec set_identifier flowtable_identifier obj_spec obj_identifier
289  %destructor { handle_free(&$$); } set_spec set_identifier obj_spec obj_identifier
290  %type <val>                    family_spec family_spec_explicit chain_policy prio_spec
291  
292 @@ -526,6 +529,9 @@ int nft_lex(void *, void *, void *);
293  %type <set>                    map_block_alloc map_block
294  %destructor { set_free($$); }  map_block_alloc
295  
296 +%type <flowtable>              flowtable_block_alloc flowtable_block
297 +%destructor { flowtable_free($$); }    flowtable_block_alloc
298 +
299  %type <obj>                    obj_block_alloc counter_block quota_block ct_helper_block limit_block
300  %destructor { obj_free($$); }  obj_block_alloc
301  
302 @@ -606,8 +612,8 @@ int nft_lex(void *, void *, void *);
303  %type <expr>                   verdict_map_expr verdict_map_list_expr verdict_map_list_member_expr
304  %destructor { expr_free($$); } verdict_map_expr verdict_map_list_expr verdict_map_list_member_expr
305  
306 -%type <expr>                   set_expr set_block_expr set_list_expr set_list_member_expr
307 -%destructor { expr_free($$); } set_expr set_block_expr set_list_expr set_list_member_expr
308 +%type <expr>                   set_expr set_block_expr set_list_expr set_list_member_expr flowtable_expr flowtable_list_expr flowtable_expr_member
309 +%destructor { expr_free($$); } set_expr set_block_expr set_list_expr set_list_member_expr flowtable_expr flowtable_list_expr flowtable_expr_member
310  %type <expr>                   set_elem_expr set_elem_expr_alloc set_lhs_expr set_rhs_expr
311  %destructor { expr_free($$); } set_elem_expr set_elem_expr_alloc set_lhs_expr set_rhs_expr
312  %type <expr>                   set_elem_expr_stmt set_elem_expr_stmt_alloc
313 @@ -872,6 +878,13 @@ add_cmd                    :       TABLE           table_spec
314                         {
315                                 $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SETELEM, &$2, &@$, $3);
316                         }
317 +                       |       FLOWTABLE       flowtable_spec  flowtable_block_alloc
318 +                                               '{'     flowtable_block '}'
319 +                       {
320 +                               $5->location = @5;
321 +                               handle_merge(&$3->handle, &$2);
322 +                               $$ = cmd_alloc(CMD_ADD, CMD_OBJ_FLOWTABLE, &$2, &@$, $5);
323 +                       }
324                         |       COUNTER         obj_spec
325                         {
326                                 struct obj *obj;
327 @@ -947,6 +960,13 @@ create_cmd         :       TABLE           table_spec
328                         {
329                                 $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_SETELEM, &$2, &@$, $3);
330                         }
331 +                       |       FLOWTABLE       flowtable_spec  flowtable_block_alloc
332 +                                               '{'     flowtable_block '}'
333 +                       {
334 +                               $5->location = @5;
335 +                               handle_merge(&$3->handle, &$2);
336 +                               $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_FLOWTABLE, &$2, &@$, $5);
337 +                       }
338                         |       COUNTER         obj_spec
339                         {
340                                 struct obj *obj;
341 @@ -1317,6 +1337,17 @@ table_block              :       /* empty */     { $$ = $<tabl
342                                 list_add_tail(&$4->list, &$1->sets);
343                                 $$ = $1;
344                         }
345 +
346 +                       |       table_block     FLOWTABLE       flowtable_identifier
347 +                                       flowtable_block_alloc   '{'     flowtable_block '}'
348 +                                       stmt_separator
349 +                       {
350 +                               $4->location = @3;
351 +                               handle_merge(&$4->handle, &$3);
352 +                               handle_free(&$3);
353 +                               list_add_tail(&$4->list, &$1->flowtables);
354 +                               $$ = $1;
355 +                       }
356                         |       table_block     COUNTER         obj_identifier
357                                         obj_block_alloc '{'     counter_block   '}'
358                                         stmt_separator
359 @@ -1512,6 +1543,62 @@ set_policy_spec          :       PERFORMANCE     { $$ = NF
360                         |       MEMORY          { $$ = NFT_SET_POL_MEMORY; }
361                         ;
362  
363 +flowtable_block_alloc  :       /* empty */
364 +                       {
365 +                               $$ = flowtable_alloc(NULL);
366 +                       }
367 +                       ;
368 +
369 +flowtable_block                :       /* empty */     { $$ = $<flowtable>-1; }
370 +                       |       flowtable_block common_block
371 +                       |       flowtable_block stmt_separator
372 +                       |       flowtable_block HOOK            STRING  PRIORITY        prio_spec       stmt_separator
373 +                       {
374 +                               $$->hookstr     = chain_hookname_lookup($3);
375 +                               if ($$->hookstr == NULL) {
376 +                                       erec_queue(error(&@3, "unknown chain hook %s", $3),
377 +                                                  state->msgs);
378 +                                       xfree($3);
379 +                                       YYERROR;
380 +                               }
381 +                               xfree($3);
382 +
383 +                               $$->priority = $5;
384 +                       }
385 +                       |       flowtable_block DEVICES         '='     flowtable_expr  stmt_separator
386 +                       {
387 +                               $$->dev_expr = $4;
388 +                       }
389 +                       ;
390 +
391 +flowtable_expr         :       '{'     flowtable_list_expr     '}'
392 +                       {
393 +                               $2->location = @$;
394 +                               $$ = $2;
395 +                       }
396 +                       ;
397 +
398 +flowtable_list_expr    :       flowtable_expr_member
399 +                       {
400 +                               $$ = compound_expr_alloc(&@$, NULL);
401 +                               compound_expr_add($$, $1);
402 +                       }
403 +                       |       flowtable_list_expr     COMMA   flowtable_expr_member
404 +                       {
405 +                               compound_expr_add($1, $3);
406 +                               $$ = $1;
407 +                       }
408 +                       |       flowtable_list_expr     COMMA   opt_newline
409 +                       ;
410 +
411 +flowtable_expr_member  :       STRING
412 +                       {
413 +                               $$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
414 +                                                      current_scope(state),
415 +                                                      $1);
416 +                       }
417 +                       ;
418 +
419  data_type_atom_expr    :       type_identifier
420                         {
421                                 const struct datatype *dtype = datatype_lookup_byname($1);
422 @@ -1720,6 +1807,21 @@ set_identifier           :       identifier
423                         }
424                         ;
425  
426 +
427 +flowtable_spec         :       table_spec      identifier
428 +                       {
429 +                               $$              = $1;
430 +                               $$.flowtable    = $2;
431 +                       }
432 +                       ;
433 +
434 +flowtable_identifier   :       identifier
435 +                       {
436 +                               memset(&$$, 0, sizeof($$));
437 +                               $$.flowtable    = $1;
438 +                       }
439 +                       ;
440 +
441  obj_spec               :       table_spec      identifier
442                         {
443                                 $$              = $1;
444 --- a/src/rule.c
445 +++ b/src/rule.c
446 @@ -45,6 +45,8 @@ void handle_merge(struct handle *dst, co
447                 dst->chain = xstrdup(src->chain);
448         if (dst->set == NULL && src->set != NULL)
449                 dst->set = xstrdup(src->set);
450 +       if (dst->flowtable == NULL && src->flowtable != NULL)
451 +               dst->flowtable = xstrdup(src->flowtable);
452         if (dst->obj == NULL && src->obj != NULL)
453                 dst->obj = xstrdup(src->obj);
454         if (dst->handle.id == 0)
455 @@ -857,6 +859,7 @@ struct cmd *cmd_alloc(enum cmd_ops op, e
456  void nft_cmd_expand(struct cmd *cmd)
457  {
458         struct list_head new_cmds;
459 +       struct flowtable *ft;
460         struct table *table;
461         struct chain *chain;
462         struct rule *rule;
463 @@ -896,6 +899,14 @@ void nft_cmd_expand(struct cmd *cmd)
464                                         &set->location, set_get(set));
465                         list_add_tail(&new->list, &new_cmds);
466                 }
467 +               list_for_each_entry(ft, &table->flowtables, list) {
468 +                       handle_merge(&ft->handle, &table->handle);
469 +                       memset(&h, 0, sizeof(h));
470 +                       handle_merge(&h, &ft->handle);
471 +                       new = cmd_alloc(CMD_ADD, CMD_OBJ_FLOWTABLE, &h,
472 +                                       &ft->location, flowtable_get(ft));
473 +                       list_add_tail(&new->list, &new_cmds);
474 +               }
475                 list_for_each_entry(chain, &table->chains, list) {
476                         list_for_each_entry(rule, &chain->rules, list) {
477                                 memset(&h, 0, sizeof(h));
478 @@ -982,6 +993,9 @@ void cmd_free(struct cmd *cmd)
479                 case CMD_OBJ_LIMIT:
480                         obj_free(cmd->object);
481                         break;
482 +               case CMD_OBJ_FLOWTABLE:
483 +                       flowtable_free(cmd->flowtable);
484 +                       break;
485                 default:
486                         BUG("invalid command object type %u\n", cmd->obj);
487                 }
488 @@ -1071,6 +1085,9 @@ static int do_command_add(struct netlink
489         case CMD_OBJ_CT_HELPER:
490         case CMD_OBJ_LIMIT:
491                 return netlink_add_obj(ctx, &cmd->handle, cmd->object, flags);
492 +       case CMD_OBJ_FLOWTABLE:
493 +               return netlink_add_flowtable(ctx, &cmd->handle, cmd->flowtable,
494 +                                            flags);
495         default:
496                 BUG("invalid command object type %u\n", cmd->obj);
497         }
498 --- a/src/scanner.l
499 +++ b/src/scanner.l
500 @@ -238,6 +238,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr
501  
502  "hook"                 { return HOOK; }
503  "device"               { return DEVICE; }
504 +"devices"              { return DEVICES; }
505  "table"                        { return TABLE; }
506  "tables"               { return TABLES; }
507  "chain"                        { return CHAIN; }
508 @@ -249,6 +250,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr
509  "element"              { return ELEMENT; }
510  "map"                  { return MAP; }
511  "maps"                 { return MAPS; }
512 +"flowtable"            { return FLOWTABLE; }
513  "handle"               { return HANDLE; }
514  "ruleset"              { return RULESET; }
515  "trace"                        { return TRACE; }