summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nf_tables.h18
-rw-r--r--include/rule.h9
-rw-r--r--src/evaluate.c5
-rw-r--r--src/json.c10
-rw-r--r--src/netlink.c8
-rw-r--r--src/parser_bison.y104
-rw-r--r--src/parser_json.c19
-rw-r--r--src/rule.c16
-rw-r--r--src/scanner.l3
-rw-r--r--src/statement.c1
10 files changed, 187 insertions, 6 deletions
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 169c2abc..4e285988 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1168,6 +1168,21 @@ enum nft_quota_attributes {
#define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1)
/**
+ * enum nft_secmark_attributes - nf_tables secmark expression netlink attributes
+ *
+ * @NFTA_SECMARK_CTX: security context (NLA_STRING)
+ */
+enum nft_secmark_attributes {
+ NFTA_SECMARK_UNSPEC,
+ NFTA_SECMARK_CTX,
+ __NFTA_SECMARK_MAX,
+};
+#define NFTA_SECMARK_MAX (__NFTA_SECMARK_MAX - 1)
+
+/* Max security context length */
+#define NFT_SECMARK_CTX_MAXLEN 256
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
@@ -1422,7 +1437,8 @@ enum nft_ct_timeout_attributes {
#define NFT_OBJECT_CONNLIMIT 5
#define NFT_OBJECT_TUNNEL 6
#define NFT_OBJECT_CT_TIMEOUT 7
-#define __NFT_OBJECT_MAX 8
+#define NFT_OBJECT_SECMARK 8
+#define __NFT_OBJECT_MAX 9
#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
/**
diff --git a/include/rule.h b/include/rule.h
index 88478aa6..9e029899 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -349,6 +349,10 @@ struct limit {
uint32_t flags;
};
+struct secmark {
+ char ctx[NFT_SECMARK_CTX_MAXLEN];
+};
+
/**
* struct obj - nftables stateful object statement
*
@@ -370,6 +374,7 @@ struct obj {
struct ct_helper ct_helper;
struct limit limit;
struct ct_timeout ct_timeout;
+ struct secmark secmark;
};
};
@@ -468,6 +473,8 @@ enum cmd_ops {
* @CMD_OBJ_LIMIT: limit
* @CMD_OBJ_LIMITS: multiple limits
* @CMD_OBJ_FLOWTABLES: flow tables
+ * @CMD_OBJ_SECMARK: secmark
+ * @CMD_OBJ_SECMARKS: multiple secmarks
*/
enum cmd_obj {
CMD_OBJ_INVALID,
@@ -497,6 +504,8 @@ enum cmd_obj {
CMD_OBJ_FLOWTABLE,
CMD_OBJ_FLOWTABLES,
CMD_OBJ_CT_TIMEOUT,
+ CMD_OBJ_SECMARK,
+ CMD_OBJ_SECMARKS,
};
struct markup {
diff --git a/src/evaluate.c b/src/evaluate.c
index ff36f576..db49a18d 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3344,6 +3344,7 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_CT_HELPER:
case CMD_OBJ_LIMIT:
case CMD_OBJ_CT_TIMEOUT:
+ case CMD_OBJ_SECMARK:
return obj_evaluate(ctx, cmd->object);
default:
BUG("invalid command object type %u\n", cmd->obj);
@@ -3372,6 +3373,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_CT_HELPER:
case CMD_OBJ_CT_TIMEOUT:
case CMD_OBJ_LIMIT:
+ case CMD_OBJ_SECMARK:
return 0;
default:
BUG("invalid command object type %u\n", cmd->obj);
@@ -3507,12 +3509,15 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_CT_TIMEOUT);
case CMD_OBJ_LIMIT:
return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_LIMIT);
+ case CMD_OBJ_SECMARK:
+ return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_SECMARK);
case CMD_OBJ_COUNTERS:
case CMD_OBJ_QUOTAS:
case CMD_OBJ_CT_HELPERS:
case CMD_OBJ_LIMITS:
case CMD_OBJ_SETS:
case CMD_OBJ_FLOWTABLES:
+ case CMD_OBJ_SECMARKS:
if (cmd->handle.table.name == NULL)
return 0;
if (table_lookup(&cmd->handle, ctx->cache) == NULL)
diff --git a/src/json.c b/src/json.c
index 1ab2d431..1cde2706 100644
--- a/src/json.c
+++ b/src/json.c
@@ -294,6 +294,12 @@ static json_t *obj_print_json(struct output_ctx *octx, const struct obj *obj)
json_object_update(root, tmp);
json_decref(tmp);
break;
+ case NFT_OBJECT_SECMARK:
+ tmp = json_pack("{s:s}",
+ "context", obj->secmark.ctx);
+ json_object_update(root, tmp);
+ json_decref(tmp);
+ break;
case NFT_OBJECT_CT_HELPER:
tmp = json_pack("{s:s, s:o, s:s}",
"type", obj->ct_helper.name, "protocol",
@@ -1706,6 +1712,10 @@ int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_LIMITS:
root = do_list_obj_json(ctx, cmd, NFT_OBJECT_LIMIT);
break;
+ case CMD_OBJ_SECMARK:
+ case CMD_OBJ_SECMARKS:
+ root = do_list_obj_json(ctx, cmd, NFT_OBJECT_SECMARK);
+ break;
case CMD_OBJ_FLOWTABLES:
root = do_list_flowtables_json(ctx, cmd);
break;
diff --git a/src/netlink.c b/src/netlink.c
index b7638815..42d3506d 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -245,6 +245,10 @@ alloc_nftnl_obj(const struct handle *h, struct obj *obj)
nftnl_obj_set_u32(nlo, NFTNL_OBJ_QUOTA_FLAGS,
obj->quota.flags);
break;
+ case NFT_OBJECT_SECMARK:
+ nftnl_obj_set_str(nlo, NFTNL_OBJ_SECMARK_CTX,
+ obj->secmark.ctx);
+ break;
case NFT_OBJECT_CT_HELPER:
nftnl_obj_set_str(nlo, NFTNL_OBJ_CT_HELPER_NAME,
obj->ct_helper.name);
@@ -1090,6 +1094,10 @@ struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
obj->quota.flags =
nftnl_obj_get_u32(nlo, NFTNL_OBJ_QUOTA_FLAGS);
break;
+ case NFT_OBJECT_SECMARK:
+ snprintf(obj->secmark.ctx, sizeof(obj->secmark.ctx), "%s",
+ nftnl_obj_get_str(nlo, NFTNL_OBJ_SECMARK_CTX));
+ break;
case NFT_OBJECT_CT_HELPER:
snprintf(obj->ct_helper.name, sizeof(obj->ct_helper.name), "%s",
nftnl_obj_get_str(nlo, NFTNL_OBJ_CT_HELPER_NAME));
diff --git a/src/parser_bison.y b/src/parser_bison.y
index c9189e9c..947a3cde 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -149,6 +149,7 @@ int nft_lex(void *, void *, void *);
struct flowtable *flowtable;
struct counter *counter;
struct quota *quota;
+ struct secmark *secmark;
struct ct *ct;
struct limit *limit;
const struct datatype *datatype;
@@ -458,6 +459,9 @@ int nft_lex(void *, void *, void *);
%token QUOTA "quota"
%token USED "used"
+%token SECMARK "secmark"
+%token SECMARKS "secmarks"
+
%token NANOSECOND "nanosecond"
%token MICROSECOND "microsecond"
%token MILLISECOND "millisecond"
@@ -567,7 +571,7 @@ int nft_lex(void *, void *, void *);
%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 ct_timeout_block limit_block
+%type <obj> obj_block_alloc counter_block quota_block ct_helper_block ct_timeout_block limit_block secmark_block
%destructor { obj_free($$); } obj_block_alloc
%type <list> stmt_list
@@ -672,8 +676,8 @@ int nft_lex(void *, void *, void *);
%type <expr> and_rhs_expr exclusive_or_rhs_expr inclusive_or_rhs_expr
%destructor { expr_free($$); } and_rhs_expr exclusive_or_rhs_expr inclusive_or_rhs_expr
-%type <obj> counter_obj quota_obj ct_obj_alloc limit_obj
-%destructor { obj_free($$); } counter_obj quota_obj ct_obj_alloc limit_obj
+%type <obj> counter_obj quota_obj ct_obj_alloc limit_obj secmark_obj
+%destructor { obj_free($$); } counter_obj quota_obj ct_obj_alloc limit_obj secmark_obj
%type <expr> relational_expr
%destructor { expr_free($$); } relational_expr
@@ -752,6 +756,8 @@ int nft_lex(void *, void *, void *);
%destructor { xfree($$); } quota_config
%type <limit> limit_config
%destructor { xfree($$); } limit_config
+%type <secmark> secmark_config
+%destructor { xfree($$); } secmark_config
%type <expr> tcp_hdr_expr
%destructor { expr_free($$); } tcp_hdr_expr
@@ -990,6 +996,10 @@ add_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_LIMIT, &$2, &@$, $3);
}
+ | SECMARK obj_spec secmark_obj
+ {
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SECMARK, &$2, &@$, $3);
+ }
;
replace_cmd : RULE ruleid_spec rule
@@ -1075,6 +1085,10 @@ create_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_CREATE, CMD_OBJ_LIMIT, &$2, &@$, $3);
}
+ | SECMARK obj_spec secmark_obj
+ {
+ $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_SECMARK, &$2, &@$, $3);
+ }
;
insert_cmd : RULE rule_position rule
@@ -1151,6 +1165,14 @@ delete_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_DELETE, CMD_OBJ_LIMIT, &$2, &@$, NULL);
}
+ | SECMARK obj_spec
+ {
+ $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_SECMARK, &$2, &@$, NULL);
+ }
+ | SECMARK objid_spec
+ {
+ $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_SECMARK, &$2, &@$, NULL);
+ }
;
get_cmd : ELEMENT set_spec set_block_expr
@@ -1223,6 +1245,18 @@ list_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_LIST, CMD_OBJ_LIMIT, &$2, &@$, NULL);
}
+ | SECMARKS ruleset_spec
+ {
+ $$ = cmd_alloc(CMD_LIST, CMD_OBJ_SECMARKS, &$2, &@$, NULL);
+ }
+ | SECMARKS TABLE table_spec
+ {
+ $$ = cmd_alloc(CMD_LIST, CMD_OBJ_SECMARKS, &$3, &@$, NULL);
+ }
+ | SECMARK obj_spec
+ {
+ $$ = cmd_alloc(CMD_LIST, CMD_OBJ_SECMARK, &$2, &@$, NULL);
+ }
| RULESET ruleset_spec
{
$$ = cmd_alloc(CMD_LIST, CMD_OBJ_RULESET, &$2, &@$, NULL);
@@ -1518,6 +1552,17 @@ table_block : /* empty */ { $$ = $<table>-1; }
list_add_tail(&$4->list, &$1->objs);
$$ = $1;
}
+ | table_block SECMARK obj_identifier
+ obj_block_alloc '{' secmark_block '}'
+ stmt_separator
+ {
+ $4->location = @3;
+ $4->type = NFT_OBJECT_SECMARK;
+ handle_merge(&$4->handle, &$3);
+ handle_free(&$3);
+ list_add_tail(&$4->list, &$1->objs);
+ $$ = $1;
+ }
;
chain_block_alloc : /* empty */
@@ -1650,6 +1695,15 @@ map_block : /* empty */ { $$ = $<set>-1; }
$1->flags |= NFT_SET_OBJECT;
$$ = $1;
}
+ | map_block TYPE
+ data_type_expr COLON SECMARK
+ stmt_separator
+ {
+ $1->key = $3;
+ $1->objtype = NFT_OBJECT_SECMARK;
+ $1->flags |= NFT_SET_OBJECT;
+ $$ = $1;
+ }
| map_block FLAGS set_flag_list stmt_separator
{
$1->flags |= $3;
@@ -1821,6 +1875,16 @@ limit_block : /* empty */ { $$ = $<obj>-1; }
}
;
+secmark_block : /* empty */ { $$ = $<obj>-1; }
+ | secmark_block common_block
+ | secmark_block stmt_separator
+ | secmark_block secmark_config
+ {
+ $1->secmark = *$2;
+ $$ = $1;
+ }
+ ;
+
type_identifier : STRING { $$ = $1; }
| MARK { $$ = xstrdup("mark"); }
| DSCP { $$ = xstrdup("dscp"); }
@@ -3336,6 +3400,28 @@ quota_obj : quota_config
}
;
+secmark_config : string
+ {
+ int ret;
+ struct secmark *secmark;
+ secmark = xzalloc(sizeof(*secmark));
+ ret = snprintf(secmark->ctx, sizeof(secmark->ctx), "%s", $1);
+ if (ret <= 0 || ret >= (int)sizeof(secmark->ctx)) {
+ erec_queue(error(&@1, "invalid context '%s', max length is %u\n", $1, (int)sizeof(secmark->ctx)), state->msgs);
+ YYERROR;
+ }
+ $$ = secmark;
+ }
+ ;
+
+secmark_obj : secmark_config
+ {
+ $$ = obj_alloc(&@$);
+ $$->type = NFT_OBJECT_SECMARK;
+ $$->secmark = *$1;
+ }
+ ;
+
ct_obj_type : HELPER { $$ = NFT_OBJECT_CT_HELPER; }
| TIMEOUT { $$ = NFT_OBJECT_CT_TIMEOUT; }
;
@@ -3725,6 +3811,7 @@ meta_key_qualified : LENGTH { $$ = NFT_META_LEN; }
| PROTOCOL { $$ = NFT_META_PROTOCOL; }
| PRIORITY { $$ = NFT_META_PRIORITY; }
| RANDOM { $$ = NFT_META_PRANDOM; }
+ | SECMARK { $$ = NFT_META_SECMARK; }
;
meta_key_unqualified : MARK { $$ = NFT_META_MARK; }
@@ -3752,7 +3839,16 @@ meta_key_unqualified : MARK { $$ = NFT_META_MARK; }
meta_stmt : META meta_key SET stmt_expr
{
- $$ = meta_stmt_alloc(&@$, $2, $4);
+ switch ($2) {
+ case NFT_META_SECMARK:
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_SECMARK;
+ $$->objref.expr = $4;
+ break;
+ default:
+ $$ = meta_stmt_alloc(&@$, $2, $4);
+ break;
+ }
}
| meta_key_unqualified SET stmt_expr
{
diff --git a/src/parser_json.c b/src/parser_json.c
index e9b0ef96..7047c00d 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -2472,6 +2472,7 @@ static int string_to_nft_object(const char *str)
[NFT_OBJECT_QUOTA] = "quota",
[NFT_OBJECT_CT_HELPER] = "ct helper",
[NFT_OBJECT_LIMIT] = "limit",
+ [NFT_OBJECT_SECMARK] = "secmark",
};
unsigned int i;
@@ -2826,6 +2827,19 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
if (obj->quota.flags)
obj->quota.flags = NFT_QUOTA_F_INV;
break;
+ case CMD_OBJ_SECMARK:
+ obj->type = NFT_OBJECT_SECMARK;
+ if (!json_unpack(root, "{s:s}", "context", tmp)) {
+ int ret;
+ ret = snprintf(obj->secmark.ctx, sizeof(obj->secmark.ctx), "%s", tmp);
+ if (ret < 0 || ret >= (int)sizeof(obj->secmark.ctx)) {
+ json_error(ctx, "Invalid secmark context '%s', max length is %zu.",
+ tmp, sizeof(obj->secmark.ctx));
+ obj_free(obj);
+ return NULL;
+ }
+ }
+ break;
case NFT_OBJECT_CT_HELPER:
cmd_obj = CMD_OBJ_CT_HELPER;
obj->type = NFT_OBJECT_CT_HELPER;
@@ -2939,7 +2953,8 @@ static struct cmd *json_parse_cmd_add(struct json_ctx *ctx,
{ "counter", CMD_OBJ_COUNTER, json_parse_cmd_add_object },
{ "quota", CMD_OBJ_QUOTA, json_parse_cmd_add_object },
{ "ct helper", NFT_OBJECT_CT_HELPER, json_parse_cmd_add_object },
- { "limit", CMD_OBJ_LIMIT, json_parse_cmd_add_object }
+ { "limit", CMD_OBJ_LIMIT, json_parse_cmd_add_object },
+ { "secmark", CMD_OBJ_SECMARK, json_parse_cmd_add_object }
};
unsigned int i;
json_t *tmp;
@@ -3103,6 +3118,8 @@ static struct cmd *json_parse_cmd_list(struct json_ctx *ctx,
{ "meter", CMD_OBJ_METER, json_parse_cmd_add_set },
{ "meters", CMD_OBJ_METERS, json_parse_cmd_list_multiple },
{ "flowtables", CMD_OBJ_FLOWTABLES, json_parse_cmd_list_multiple },
+ { "secmark", CMD_OBJ_SECMARK, json_parse_cmd_add_object },
+ { "secmarks", CMD_OBJ_SECMARKS, json_parse_cmd_list_multiple },
};
unsigned int i;
json_t *tmp;
diff --git a/src/rule.c b/src/rule.c
index e1b004c7..8f78a36c 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1326,6 +1326,7 @@ void cmd_free(struct cmd *cmd)
case CMD_OBJ_CT_HELPER:
case CMD_OBJ_CT_TIMEOUT:
case CMD_OBJ_LIMIT:
+ case CMD_OBJ_SECMARK:
obj_free(cmd->object);
break;
case CMD_OBJ_FLOWTABLE:
@@ -1421,6 +1422,7 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl)
case CMD_OBJ_CT_HELPER:
case CMD_OBJ_CT_TIMEOUT:
case CMD_OBJ_LIMIT:
+ case CMD_OBJ_SECMARK:
return netlink_add_obj(ctx, cmd, flags);
case CMD_OBJ_FLOWTABLE:
return netlink_add_flowtable(ctx, cmd, flags);
@@ -1510,6 +1512,8 @@ static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd)
NFT_OBJECT_CT_TIMEOUT);
case CMD_OBJ_LIMIT:
return netlink_delete_obj(ctx, cmd, NFT_OBJECT_LIMIT);
+ case CMD_OBJ_SECMARK:
+ return netlink_delete_obj(ctx, cmd, NFT_OBJECT_SECMARK);
case CMD_OBJ_FLOWTABLE:
return netlink_delete_flowtable(ctx, cmd);
default:
@@ -1716,6 +1720,13 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, "%s", opts->nl);
}
break;
+ case NFT_OBJECT_SECMARK:
+ nft_print(octx, " %s {", obj->handle.obj.name);
+ if (octx->handle > 0)
+ nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
+ nft_print(octx, "%s", obj->secmark.ctx);
+ break;
case NFT_OBJECT_CT_HELPER:
nft_print(octx, " %s {", obj->handle.obj.name);
if (octx->handle > 0)
@@ -1793,6 +1804,7 @@ static const char * const obj_type_name_array[] = {
[NFT_OBJECT_CT_HELPER] = "ct helper",
[NFT_OBJECT_LIMIT] = "limit",
[NFT_OBJECT_CT_TIMEOUT] = "ct timeout",
+ [NFT_OBJECT_SECMARK] = "secmark",
};
const char *obj_type_name(enum stmt_types type)
@@ -1808,6 +1820,7 @@ static uint32_t obj_type_cmd_array[NFT_OBJECT_MAX + 1] = {
[NFT_OBJECT_CT_HELPER] = CMD_OBJ_CT_HELPER,
[NFT_OBJECT_LIMIT] = CMD_OBJ_LIMIT,
[NFT_OBJECT_CT_TIMEOUT] = CMD_OBJ_CT_TIMEOUT,
+ [NFT_OBJECT_SECMARK] = CMD_OBJ_SECMARK,
};
uint32_t obj_type_to_cmd(uint32_t type)
@@ -2167,6 +2180,9 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_LIMIT:
case CMD_OBJ_LIMITS:
return do_list_obj(ctx, cmd, NFT_OBJECT_LIMIT);
+ case CMD_OBJ_SECMARK:
+ case CMD_OBJ_SECMARKS:
+ return do_list_obj(ctx, cmd, NFT_OBJECT_SECMARK);
case CMD_OBJ_FLOWTABLES:
return do_list_flowtables(ctx, cmd);
default:
diff --git a/src/scanner.l b/src/scanner.l
index 4a143b1e..f96944e9 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -564,6 +564,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"in" { return IN; }
"out" { return OUT; }
+"secmark" { return SECMARK; }
+"secmarks" { return SECMARKS; }
+
{addrstring} {
yylval->string = xstrdup(yytext);
return STRING;
diff --git a/src/statement.c b/src/statement.c
index a02ebc84..909f04ca 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -204,6 +204,7 @@ static const char *objref_type[NFT_OBJECT_MAX + 1] = {
[NFT_OBJECT_CT_HELPER] = "ct helper",
[NFT_OBJECT_LIMIT] = "limit",
[NFT_OBJECT_CT_TIMEOUT] = "ct timeout",
+ [NFT_OBJECT_SECMARK] = "secmark",
};
const char *objref_type_name(uint32_t type)