diff options
Diffstat (limited to 'package/network/utils/nftables/patches/201-src-add-support-to-add-flowtables.patch')
-rw-r--r-- | package/network/utils/nftables/patches/201-src-add-support-to-add-flowtables.patch | 515 |
1 files changed, 515 insertions, 0 deletions
diff --git a/package/network/utils/nftables/patches/201-src-add-support-to-add-flowtables.patch b/package/network/utils/nftables/patches/201-src-add-support-to-add-flowtables.patch new file mode 100644 index 0000000..888a767 --- /dev/null +++ b/package/network/utils/nftables/patches/201-src-add-support-to-add-flowtables.patch @@ -0,0 +1,515 @@ +From: Pablo Neira Ayuso <pablo@netfilter.org> +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 <pablo@netfilter.org> +--- + +--- 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; } |