| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515 |
- From: Pablo Neira Ayuso <[email protected]>
- Date: Thu, 18 Jan 2018 08:43:23 +0100
- Subject: [PATCH] src: add support to add flowtables
- This patch allows you to create flowtable:
- # nft add table x
- # nft add flowtable x m { hook ingress priority 10\; devices = { eth0, wlan0 }\; }
- You have to specify hook and priority. So far, only the ingress hook is
- supported. The priority represents where this flowtable is placed in the
- ingress hook, which is registered to the devices that the user
- specifies.
- You can also use the 'create' command instead to bail out in case that
- there is an existing flowtable with this name.
- Signed-off-by: Pablo Neira Ayuso <[email protected]>
- ---
- --- a/include/expression.h
- +++ b/include/expression.h
- @@ -407,6 +407,8 @@ extern struct expr *prefix_expr_alloc(co
- extern struct expr *range_expr_alloc(const struct location *loc,
- struct expr *low, struct expr *high);
-
- +extern struct expr *compound_expr_alloc(const struct location *loc,
- + const struct expr_ops *ops);
- extern void compound_expr_add(struct expr *compound, struct expr *expr);
- extern void compound_expr_remove(struct expr *compound, struct expr *expr);
- extern void list_expr_sort(struct list_head *head);
- --- a/include/mnl.h
- +++ b/include/mnl.h
- @@ -92,6 +92,10 @@ int mnl_nft_obj_batch_del(struct nftnl_o
- struct nftnl_flowtable_list *
- mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table);
-
- +int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo,
- + struct nftnl_batch *batch, unsigned int flags,
- + uint32_t seqnum);
- +
- struct nftnl_ruleset *mnl_nft_ruleset_dump(struct netlink_ctx *ctx,
- uint32_t family);
- int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
- --- a/include/netlink.h
- +++ b/include/netlink.h
- @@ -7,6 +7,7 @@
- #include <libnftnl/expr.h>
- #include <libnftnl/set.h>
- #include <libnftnl/object.h>
- +#include <libnftnl/flowtable.h>
-
- #include <linux/netlink.h>
- #include <linux/netfilter/nf_tables.h>
- @@ -182,6 +183,9 @@ extern int netlink_delete_obj(struct net
- extern int netlink_list_flowtables(struct netlink_ctx *ctx,
- const struct handle *h,
- const struct location *loc);
- +extern int netlink_add_flowtable(struct netlink_ctx *ctx,
- + const struct handle *h, struct flowtable *ft,
- + uint32_t flags);
-
- extern void netlink_dump_chain(const struct nftnl_chain *nlc,
- struct netlink_ctx *ctx);
- --- a/include/rule.h
- +++ b/include/rule.h
- @@ -322,10 +322,13 @@ uint32_t obj_type_to_cmd(uint32_t type);
- struct flowtable {
- struct list_head list;
- struct handle handle;
- + struct scope scope;
- struct location location;
- + const char * hookstr;
- unsigned int hooknum;
- int priority;
- const char **dev_array;
- + struct expr *dev_expr;
- int dev_array_len;
- unsigned int refcnt;
- };
- @@ -383,6 +386,8 @@ enum cmd_ops {
- * @CMD_OBJ_CHAIN: chain
- * @CMD_OBJ_CHAINS: multiple chains
- * @CMD_OBJ_TABLE: table
- + * @CMD_OBJ_FLOWTABLE: flowtable
- + * @CMD_OBJ_FLOWTABLES: flowtables
- * @CMD_OBJ_RULESET: ruleset
- * @CMD_OBJ_EXPR: expression
- * @CMD_OBJ_MONITOR: monitor
- @@ -422,6 +427,7 @@ enum cmd_obj {
- CMD_OBJ_CT_HELPERS,
- CMD_OBJ_LIMIT,
- CMD_OBJ_LIMITS,
- + CMD_OBJ_FLOWTABLE,
- CMD_OBJ_FLOWTABLES,
- };
-
- @@ -481,6 +487,7 @@ struct cmd {
- struct rule *rule;
- struct chain *chain;
- struct table *table;
- + struct flowtable *flowtable;
- struct monitor *monitor;
- struct markup *markup;
- struct obj *object;
- --- a/src/evaluate.c
- +++ b/src/evaluate.c
- @@ -2897,6 +2897,24 @@ static int set_evaluate(struct eval_ctx
- return 0;
- }
-
- +static uint32_t str2hooknum(uint32_t family, const char *hook);
- +
- +static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft)
- +{
- + struct table *table;
- +
- + table = table_lookup_global(ctx);
- + if (table == NULL)
- + return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
- + ctx->cmd->handle.table);
- +
- + ft->hooknum = str2hooknum(NFPROTO_NETDEV, ft->hookstr);
- + if (ft->hooknum == NF_INET_NUMHOOKS)
- + return chain_error(ctx, ft, "invalid hook %s", ft->hookstr);
- +
- + return 0;
- +}
- +
- static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule)
- {
- struct stmt *stmt, *tstmt = NULL;
- @@ -3069,6 +3087,14 @@ static int cmd_evaluate_add(struct eval_
- return chain_evaluate(ctx, cmd->chain);
- case CMD_OBJ_TABLE:
- return table_evaluate(ctx, cmd->table);
- + case CMD_OBJ_FLOWTABLE:
- + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op,
- + ctx->msgs, ctx->debug_mask & NFT_DEBUG_NETLINK, ctx->octx);
- + if (ret < 0)
- + return ret;
- +
- + handle_merge(&cmd->flowtable->handle, &cmd->handle);
- + return flowtable_evaluate(ctx, cmd->flowtable);
- case CMD_OBJ_COUNTER:
- case CMD_OBJ_QUOTA:
- case CMD_OBJ_CT_HELPER:
- --- a/src/expression.c
- +++ b/src/expression.c
- @@ -663,8 +663,8 @@ struct expr *range_expr_alloc(const stru
- return expr;
- }
-
- -static struct expr *compound_expr_alloc(const struct location *loc,
- - const struct expr_ops *ops)
- +struct expr *compound_expr_alloc(const struct location *loc,
- + const struct expr_ops *ops)
- {
- struct expr *expr;
-
- --- a/src/mnl.c
- +++ b/src/mnl.c
- @@ -1011,6 +1011,22 @@ err:
- return NULL;
- }
-
- +int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo,
- + struct nftnl_batch *batch, unsigned int flags,
- + uint32_t seqnum)
- +{
- + struct nlmsghdr *nlh;
- +
- + nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch),
- + NFT_MSG_NEWFLOWTABLE,
- + nftnl_flowtable_get_u32(flo, NFTNL_FLOWTABLE_FAMILY),
- + NLM_F_CREATE | flags, seqnum);
- + nftnl_flowtable_nlmsg_build_payload(nlh, flo);
- + mnl_nft_batch_continue(batch);
- +
- + return 0;
- +}
- +
- /*
- * ruleset
- */
- --- a/src/netlink.c
- +++ b/src/netlink.c
- @@ -1773,6 +1773,64 @@ static struct obj *netlink_delinearize_o
- return obj;
- }
-
- +static struct nftnl_flowtable *alloc_nftnl_flowtable(const struct handle *h,
- + const struct flowtable *ft)
- +{
- + struct nftnl_flowtable *flo;
- +
- + flo = nftnl_flowtable_alloc();
- + if (flo == NULL)
- + memory_allocation_error();
- +
- + nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_FAMILY, h->family);
- + nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE, h->table);
- + if (h->flowtable != NULL)
- + nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME, h->flowtable);
- +
- + return flo;
- +}
- +
- +static void netlink_dump_flowtable(struct nftnl_flowtable *flo,
- + struct netlink_ctx *ctx)
- +{
- + FILE *fp = ctx->octx->output_fp;
- +
- + if (!(ctx->debug_mask & NFT_DEBUG_NETLINK) || !fp)
- + return;
- +
- + nftnl_flowtable_fprintf(fp, flo, 0, 0);
- + fprintf(fp, "\n");
- +}
- +
- +int netlink_add_flowtable(struct netlink_ctx *ctx, const struct handle *h,
- + struct flowtable *ft, uint32_t flags)
- +{
- + struct nftnl_flowtable *flo;
- + const char *dev_array[8];
- + struct expr *expr;
- + int i = 0, err;
- +
- + flo = alloc_nftnl_flowtable(h, ft);
- + nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_HOOKNUM, ft->hooknum);
- + nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_PRIO, ft->priority);
- +
- + list_for_each_entry(expr, &ft->dev_expr->expressions, list)
- + dev_array[i++] = expr->identifier;
- +
- + dev_array[i] = NULL;
- + nftnl_flowtable_set_array(flo, NFTNL_FLOWTABLE_DEVICES, dev_array);
- +
- + netlink_dump_flowtable(flo, ctx);
- +
- + err = mnl_nft_flowtable_batch_add(flo, ctx->batch, flags, ctx->seqnum);
- + if (err < 0)
- + netlink_io_error(ctx, &ft->location, "Could not add flowtable: %s",
- + strerror(errno));
- + nftnl_flowtable_free(flo);
- +
- + return err;
- +}
- +
- static int list_obj_cb(struct nftnl_obj *nls, void *arg)
- {
- struct netlink_ctx *ctx = arg;
- --- a/src/parser_bison.y
- +++ b/src/parser_bison.y
- @@ -145,6 +145,7 @@ int nft_lex(void *, void *, void *);
- struct expr *expr;
- struct set *set;
- struct obj *obj;
- + struct flowtable *flowtable;
- struct counter *counter;
- struct quota *quota;
- struct ct *ct;
- @@ -189,6 +190,7 @@ int nft_lex(void *, void *, void *);
-
- %token HOOK "hook"
- %token DEVICE "device"
- +%token DEVICES "devices"
- %token TABLE "table"
- %token TABLES "tables"
- %token CHAIN "chain"
- @@ -200,6 +202,7 @@ int nft_lex(void *, void *, void *);
- %token ELEMENT "element"
- %token MAP "map"
- %token MAPS "maps"
- +%token FLOWTABLE "flowtable"
- %token HANDLE "handle"
- %token RULESET "ruleset"
- %token TRACE "trace"
- @@ -500,9 +503,9 @@ int nft_lex(void *, void *, void *);
- %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
- %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
-
- -%type <handle> table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
- -%destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
- -%type <handle> set_spec set_identifier obj_spec obj_identifier
- +%type <handle> table_spec chain_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
- +%destructor { handle_free(&$$); } table_spec chain_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
- +%type <handle> set_spec set_identifier flowtable_identifier obj_spec obj_identifier
- %destructor { handle_free(&$$); } set_spec set_identifier obj_spec obj_identifier
- %type <val> family_spec family_spec_explicit chain_policy prio_spec
-
- @@ -526,6 +529,9 @@ int nft_lex(void *, void *, void *);
- %type <set> map_block_alloc map_block
- %destructor { set_free($$); } map_block_alloc
-
- +%type <flowtable> flowtable_block_alloc flowtable_block
- +%destructor { flowtable_free($$); } flowtable_block_alloc
- +
- %type <obj> obj_block_alloc counter_block quota_block ct_helper_block limit_block
- %destructor { obj_free($$); } obj_block_alloc
-
- @@ -606,8 +612,8 @@ int nft_lex(void *, void *, void *);
- %type <expr> verdict_map_expr verdict_map_list_expr verdict_map_list_member_expr
- %destructor { expr_free($$); } verdict_map_expr verdict_map_list_expr verdict_map_list_member_expr
-
- -%type <expr> set_expr set_block_expr set_list_expr set_list_member_expr
- -%destructor { expr_free($$); } set_expr set_block_expr set_list_expr set_list_member_expr
- +%type <expr> set_expr set_block_expr set_list_expr set_list_member_expr flowtable_expr flowtable_list_expr flowtable_expr_member
- +%destructor { expr_free($$); } set_expr set_block_expr set_list_expr set_list_member_expr flowtable_expr flowtable_list_expr flowtable_expr_member
- %type <expr> set_elem_expr set_elem_expr_alloc set_lhs_expr set_rhs_expr
- %destructor { expr_free($$); } set_elem_expr set_elem_expr_alloc set_lhs_expr set_rhs_expr
- %type <expr> set_elem_expr_stmt set_elem_expr_stmt_alloc
- @@ -872,6 +878,13 @@ add_cmd : TABLE table_spec
- {
- $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SETELEM, &$2, &@$, $3);
- }
- + | FLOWTABLE flowtable_spec flowtable_block_alloc
- + '{' flowtable_block '}'
- + {
- + $5->location = @5;
- + handle_merge(&$3->handle, &$2);
- + $$ = cmd_alloc(CMD_ADD, CMD_OBJ_FLOWTABLE, &$2, &@$, $5);
- + }
- | COUNTER obj_spec
- {
- struct obj *obj;
- @@ -947,6 +960,13 @@ create_cmd : TABLE table_spec
- {
- $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_SETELEM, &$2, &@$, $3);
- }
- + | FLOWTABLE flowtable_spec flowtable_block_alloc
- + '{' flowtable_block '}'
- + {
- + $5->location = @5;
- + handle_merge(&$3->handle, &$2);
- + $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_FLOWTABLE, &$2, &@$, $5);
- + }
- | COUNTER obj_spec
- {
- struct obj *obj;
- @@ -1317,6 +1337,17 @@ table_block : /* empty */ { $$ = $<tabl
- list_add_tail(&$4->list, &$1->sets);
- $$ = $1;
- }
- +
- + | table_block FLOWTABLE flowtable_identifier
- + flowtable_block_alloc '{' flowtable_block '}'
- + stmt_separator
- + {
- + $4->location = @3;
- + handle_merge(&$4->handle, &$3);
- + handle_free(&$3);
- + list_add_tail(&$4->list, &$1->flowtables);
- + $$ = $1;
- + }
- | table_block COUNTER obj_identifier
- obj_block_alloc '{' counter_block '}'
- stmt_separator
- @@ -1512,6 +1543,62 @@ set_policy_spec : PERFORMANCE { $$ = NF
- | MEMORY { $$ = NFT_SET_POL_MEMORY; }
- ;
-
- +flowtable_block_alloc : /* empty */
- + {
- + $$ = flowtable_alloc(NULL);
- + }
- + ;
- +
- +flowtable_block : /* empty */ { $$ = $<flowtable>-1; }
- + | flowtable_block common_block
- + | flowtable_block stmt_separator
- + | flowtable_block HOOK STRING PRIORITY prio_spec stmt_separator
- + {
- + $$->hookstr = chain_hookname_lookup($3);
- + if ($$->hookstr == NULL) {
- + erec_queue(error(&@3, "unknown chain hook %s", $3),
- + state->msgs);
- + xfree($3);
- + YYERROR;
- + }
- + xfree($3);
- +
- + $$->priority = $5;
- + }
- + | flowtable_block DEVICES '=' flowtable_expr stmt_separator
- + {
- + $$->dev_expr = $4;
- + }
- + ;
- +
- +flowtable_expr : '{' flowtable_list_expr '}'
- + {
- + $2->location = @$;
- + $$ = $2;
- + }
- + ;
- +
- +flowtable_list_expr : flowtable_expr_member
- + {
- + $$ = compound_expr_alloc(&@$, NULL);
- + compound_expr_add($$, $1);
- + }
- + | flowtable_list_expr COMMA flowtable_expr_member
- + {
- + compound_expr_add($1, $3);
- + $$ = $1;
- + }
- + | flowtable_list_expr COMMA opt_newline
- + ;
- +
- +flowtable_expr_member : STRING
- + {
- + $$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
- + current_scope(state),
- + $1);
- + }
- + ;
- +
- data_type_atom_expr : type_identifier
- {
- const struct datatype *dtype = datatype_lookup_byname($1);
- @@ -1720,6 +1807,21 @@ set_identifier : identifier
- }
- ;
-
- +
- +flowtable_spec : table_spec identifier
- + {
- + $$ = $1;
- + $$.flowtable = $2;
- + }
- + ;
- +
- +flowtable_identifier : identifier
- + {
- + memset(&$$, 0, sizeof($$));
- + $$.flowtable = $1;
- + }
- + ;
- +
- obj_spec : table_spec identifier
- {
- $$ = $1;
- --- a/src/rule.c
- +++ b/src/rule.c
- @@ -45,6 +45,8 @@ void handle_merge(struct handle *dst, co
- dst->chain = xstrdup(src->chain);
- if (dst->set == NULL && src->set != NULL)
- dst->set = xstrdup(src->set);
- + if (dst->flowtable == NULL && src->flowtable != NULL)
- + dst->flowtable = xstrdup(src->flowtable);
- if (dst->obj == NULL && src->obj != NULL)
- dst->obj = xstrdup(src->obj);
- if (dst->handle.id == 0)
- @@ -857,6 +859,7 @@ struct cmd *cmd_alloc(enum cmd_ops op, e
- void nft_cmd_expand(struct cmd *cmd)
- {
- struct list_head new_cmds;
- + struct flowtable *ft;
- struct table *table;
- struct chain *chain;
- struct rule *rule;
- @@ -896,6 +899,14 @@ void nft_cmd_expand(struct cmd *cmd)
- &set->location, set_get(set));
- list_add_tail(&new->list, &new_cmds);
- }
- + list_for_each_entry(ft, &table->flowtables, list) {
- + handle_merge(&ft->handle, &table->handle);
- + memset(&h, 0, sizeof(h));
- + handle_merge(&h, &ft->handle);
- + new = cmd_alloc(CMD_ADD, CMD_OBJ_FLOWTABLE, &h,
- + &ft->location, flowtable_get(ft));
- + list_add_tail(&new->list, &new_cmds);
- + }
- list_for_each_entry(chain, &table->chains, list) {
- list_for_each_entry(rule, &chain->rules, list) {
- memset(&h, 0, sizeof(h));
- @@ -982,6 +993,9 @@ void cmd_free(struct cmd *cmd)
- case CMD_OBJ_LIMIT:
- obj_free(cmd->object);
- break;
- + case CMD_OBJ_FLOWTABLE:
- + flowtable_free(cmd->flowtable);
- + break;
- default:
- BUG("invalid command object type %u\n", cmd->obj);
- }
- @@ -1071,6 +1085,9 @@ static int do_command_add(struct netlink
- case CMD_OBJ_CT_HELPER:
- case CMD_OBJ_LIMIT:
- return netlink_add_obj(ctx, &cmd->handle, cmd->object, flags);
- + case CMD_OBJ_FLOWTABLE:
- + return netlink_add_flowtable(ctx, &cmd->handle, cmd->flowtable,
- + flags);
- default:
- BUG("invalid command object type %u\n", cmd->obj);
- }
- --- a/src/scanner.l
- +++ b/src/scanner.l
- @@ -238,6 +238,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr
-
- "hook" { return HOOK; }
- "device" { return DEVICE; }
- +"devices" { return DEVICES; }
- "table" { return TABLE; }
- "tables" { return TABLES; }
- "chain" { return CHAIN; }
- @@ -249,6 +250,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr
- "element" { return ELEMENT; }
- "map" { return MAP; }
- "maps" { return MAPS; }
- +"flowtable" { return FLOWTABLE; }
- "handle" { return HANDLE; }
- "ruleset" { return RULESET; }
- "trace" { return TRACE; }
|