]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add ability to set/get secmarks to/from connection
authorChristian Göttsche <cgzones@googlemail.com>
Sat, 23 Nov 2019 16:22:39 +0000 (17:22 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 25 Nov 2019 14:44:00 +0000 (15:44 +0100)
Labeling established and related packets requires the secmark to be stored in the connection.
Add the ability to store and retrieve secmarks like:

    ...
    chain input {
        ...

        # label new incoming packets
        ct state new meta secmark set tcp dport map @secmapping_in

        # add label to connection
        ct state new ct secmark set meta secmark

        # set label for est/rel packets from connection
        ct state established,related meta secmark set ct secmark

        ...
    }
    ...
    chain output {
        ...

        # label new outgoing packets
        ct state new meta secmark set tcp dport map @secmapping_out

        # add label to connection
        ct state new ct secmark set meta secmark

        # set label for est/rel packets from connection
        ct state established,related meta secmark set ct secmark

        ...
        }
    ...

This patch also disallow constant value on the right hand side.

    # nft add rule x y meta secmark 12
    Error: Cannot be used with right hand side constant value
    add rule x y meta secmark 12
                 ~~~~~~~~~~~~ ^^
    # nft add rule x y ct secmark 12
    Error: Cannot be used with right hand side constant value
    add rule x y ct secmark 12
                 ~~~~~~~~~~ ^^
    # nft add rule x y ct secmark set 12
    Error: ct secmark must not be set to constant value
    add rule x y ct secmark set 12
                 ^^^^^^^^^^^^^^^^^

This patch improves 3bc84e5c1fdd ("src: add support for setting secmark").

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/ct.c
src/evaluate.c
src/meta.c
src/parser_bison.y

index ed458e6b679b57bd930c90f13228528cb52fc294..9e6a8351ffb2fb90fc405f5642adc818211682b5 100644 (file)
--- a/src/ct.c
+++ b/src/ct.c
@@ -299,6 +299,8 @@ const struct ct_template ct_templates[__NFT_CT_MAX] = {
                                              BYTEORDER_BIG_ENDIAN, 128),
        [NFT_CT_DST_IP6]        = CT_TEMPLATE("ip6 daddr", &ip6addr_type,
                                              BYTEORDER_BIG_ENDIAN, 128),
+       [NFT_CT_SECMARK]        = CT_TEMPLATE("secmark", &integer_type,
+                                             BYTEORDER_HOST_ENDIAN, 32),
 };
 
 static void ct_print(enum nft_ct_keys key, int8_t dir, uint8_t nfproto,
index e54eaf1a711080e9d0e1d3c2d5a64f606d5dc3b1..a865902c0fc7bbdda53a55fc77defcbea2632dc7 100644 (file)
@@ -1784,6 +1784,18 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
                                         left->dtype->desc,
                                         right->dtype->desc);
 
+       /*
+        * Statements like 'ct secmark 12' are parsed as relational,
+        * disallow constant value on the right hand side.
+        */
+       if (((left->etype == EXPR_META &&
+             left->meta.key == NFT_META_SECMARK) ||
+            (left->etype == EXPR_CT &&
+             left->ct.key == NFT_CT_SECMARK)) &&
+           right->flags & EXPR_F_CONSTANT)
+               return expr_binary_error(ctx->msgs, right, left,
+                                        "Cannot be used with right hand side constant value");
+
        switch (rel->op) {
        case OP_EQ:
        case OP_IMPLICIT:
@@ -2319,11 +2331,19 @@ static int stmt_evaluate_meta(struct eval_ctx *ctx, struct stmt *stmt)
 
 static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt)
 {
-       return stmt_evaluate_arg(ctx, stmt,
+       if (stmt_evaluate_arg(ctx, stmt,
                                 stmt->ct.tmpl->dtype,
                                 stmt->ct.tmpl->len,
                                 stmt->ct.tmpl->byteorder,
-                                &stmt->ct.expr);
+                                &stmt->ct.expr) < 0)
+               return -1;
+
+       if (stmt->ct.key == NFT_CT_SECMARK &&
+           expr_is_constant(stmt->ct.expr))
+               return stmt_error(ctx, stmt,
+                                 "ct secmark must not be set to constant value");
+
+       return 0;
 }
 
 static int reject_payload_gen_dependency_tcp(struct eval_ctx *ctx,
index 69a897a926869a097d6a58679f4649d2fb253b90..796d8e9414868d21beaf3cbf7707bfad990285ef 100644 (file)
@@ -698,6 +698,8 @@ const struct meta_template meta_templates[] = {
        [NFT_META_TIME_HOUR]    = META_TEMPLATE("hour", &hour_type,
                                                4 * BITS_PER_BYTE,
                                                BYTEORDER_HOST_ENDIAN),
+       [NFT_META_SECMARK]      = META_TEMPLATE("secmark", &integer_type,
+                                               32, BYTEORDER_HOST_ENDIAN),
 };
 
 static bool meta_key_is_unqualified(enum nft_meta_keys key)
index 631b7d68455566b1829693cb5c2925098f669081..707f46716ed3ff5b03f7132788d8b96e6a82a7cd 100644 (file)
@@ -4190,9 +4190,16 @@ meta_stmt                :       META    meta_key        SET     stmt_expr
                        {
                                switch ($2) {
                                case NFT_META_SECMARK:
-                                       $$ = objref_stmt_alloc(&@$);
-                                       $$->objref.type = NFT_OBJECT_SECMARK;
-                                       $$->objref.expr = $4;
+                                       switch ($4->etype) {
+                                       case EXPR_CT:
+                                               $$ = meta_stmt_alloc(&@$, $2, $4);
+                                               break;
+                                       default:
+                                               $$ = objref_stmt_alloc(&@$);
+                                               $$->objref.type = NFT_OBJECT_SECMARK;
+                                               $$->objref.expr = $4;
+                                               break;
+                                       }
                                        break;
                                default:
                                        $$ = meta_stmt_alloc(&@$, $2, $4);
@@ -4388,6 +4395,7 @@ ct_key                    :       L3PROTOCOL      { $$ = NFT_CT_L3PROTOCOL; }
                        |       PROTO_DST       { $$ = NFT_CT_PROTO_DST; }
                        |       LABEL           { $$ = NFT_CT_LABELS; }
                        |       EVENT           { $$ = NFT_CT_EVENTMASK; }
+                       |       SECMARK         { $$ = NFT_CT_SECMARK; }
                        |       ct_key_dir_optional
                        ;