]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
osf: add ttl option support
authorFernando Fernandez Mancera <ffmancera@riseup.net>
Tue, 23 Oct 2018 15:06:22 +0000 (17:06 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 23 Oct 2018 15:46:47 +0000 (17:46 +0200)
Add support for ttl option in "osf" expression. Example:

table ip foo {
chain bar {
type filter hook input priority filter; policy accept;
osf ttl skip name "Linux"
}
}

Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 files changed:
include/expression.h
include/linux/netfilter/nf_tables.h
include/osf.h
src/json.c
src/netlink_delinearize.c
src/netlink_linearize.c
src/osf.c
src/parser_bison.y
src/parser_json.c
tests/py/inet/osf.t
tests/py/inet/osf.t.json
tests/py/inet/osf.t.payload

index d6977c3ae62efd2a09be803c9337b080ee73d94e..f018c958d2dcc1a6438e35a741c268f316f3f9fa 100644 (file)
@@ -345,6 +345,10 @@ struct expr {
                        uint8_t         direction;
                        uint8_t         spnum;
                } xfrm;
+               struct {
+                       /* EXPR_OSF */
+                       uint8_t                 ttl;
+               } osf;
        };
 };
 
index 4e2859880d77c22a69c9c7f4a747fcae677033dd..1d13ad37ec8921d8e1fe1c539e4b53972f563a00 100644 (file)
@@ -939,10 +939,12 @@ enum nft_socket_keys {
  * enum nft_osf_attributes - nf_tables osf expression netlink attributes
  *
  * @NFTA_OSF_DREG: destination register (NLA_U32: nft_registers)
+ * @NFTA_OSF_TTL: Value of the TTL osf option (NLA_U8)
  */
 enum nft_osf_attributes {
        NFTA_OSF_UNSPEC,
        NFTA_OSF_DREG,
+       NFTA_OSF_TTL,
        __NFTA_OSF_MAX
 };
 #define NFT_OSF_MAX            (__NFTA_OSF_MAX - 1)
index 54cdd4af5df34d29b47ab10171a1888d06a677ca..23ea34d371402e43367ba1d43625ff722102e4a1 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef NFTABLES_OSF_H
 #define NFTABLES_OSF_H
 
-struct expr *osf_expr_alloc(const struct location *loc);
+struct expr *osf_expr_alloc(const struct location *loc, const uint8_t ttl);
 
 extern int nfnl_osf_load_fingerprints(struct netlink_ctx *ctx, int del);
 
index 1cde2706b84888b5dee5eb661ebcbf8e2937daaa..cea9f19cd99829f5639e9bea87ea688a2de2cfa0 100644 (file)
@@ -857,7 +857,7 @@ json_t *socket_expr_json(const struct expr *expr, struct output_ctx *octx)
 
 json_t *osf_expr_json(const struct expr *expr, struct output_ctx *octx)
 {
-       return json_pack("{s:{s:s}}", "osf", "key", "name");
+       return json_pack("{s:{s:i, s:s}}", "osf", "ttl", expr->osf.ttl, "key", "name");
 }
 
 json_t *xfrm_expr_json(const struct expr *expr, struct output_ctx *octx)
index 3931127feffaa19d87efb5ffb60d1153ba8f7391..db1bf03e5c6ad1198fe3b49467a544af37db4953 100644 (file)
@@ -655,8 +655,11 @@ static void netlink_parse_osf(struct netlink_parse_ctx *ctx,
 {
        enum nft_registers dreg;
        struct expr *expr;
+       uint8_t ttl;
+
+       ttl = nftnl_expr_get_u8(nle, NFTNL_EXPR_OSF_TTL);
+       expr = osf_expr_alloc(loc, ttl);
 
-       expr = osf_expr_alloc(loc);
        dreg = netlink_parse_register(nle, NFTNL_EXPR_OSF_DREG);
        netlink_set_register(ctx, dreg, expr);
 }
index 0ac51bd0d710fdc5dd9ded64f1403081cb39823b..0c8f5fe42814c403c6a5817bd19093eee91dfb7f 100644 (file)
@@ -227,6 +227,7 @@ static void netlink_gen_osf(struct netlink_linearize_ctx *ctx,
 
        nle = alloc_nft_expr("osf");
        netlink_put_register(nle, NFTNL_EXPR_OSF_DREG, dreg);
+       nftnl_expr_set_u8(nle, NFTNL_EXPR_OSF_TTL, expr->osf.ttl);
        nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
index 85c957391b573e10020208e3feff304ae1148629..b98d16508d00159853481c3085b18d9630335e5a 100644 (file)
--- a/src/osf.c
+++ b/src/osf.c
@@ -5,13 +5,31 @@
 #include <osf.h>
 #include <json.h>
 
+static const char *osf_ttl_int_to_str(const uint8_t ttl)
+{
+       if (ttl == 1)
+               return "ttl loose ";
+       else if (ttl == 2)
+               return "ttl skip ";
+
+       return "";
+}
+
 static void osf_expr_print(const struct expr *expr, struct output_ctx *octx)
 {
-       nft_print(octx, "osf name");
+       const char *ttl_str = osf_ttl_int_to_str(expr->osf.ttl);
+
+       nft_print(octx, "osf %sname", ttl_str);
 }
 
 static void osf_expr_clone(struct expr *new, const struct expr *expr)
 {
+       new->osf.ttl = expr->osf.ttl;
+}
+
+static bool osf_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+       return e1->osf.ttl == e2->osf.ttl;
 }
 
 static const struct expr_ops osf_expr_ops = {
@@ -19,10 +37,11 @@ static const struct expr_ops osf_expr_ops = {
        .name           = "osf",
        .print          = osf_expr_print,
        .clone          = osf_expr_clone,
+       .cmp            = osf_expr_cmp,
        .json           = osf_expr_json,
 };
 
-struct expr *osf_expr_alloc(const struct location *loc)
+struct expr *osf_expr_alloc(const struct location *loc, const uint8_t ttl)
 {
        unsigned int len = NFT_OSF_MAXGENRELEN * BITS_PER_BYTE;
        const struct datatype *type = &string_type;
@@ -30,6 +49,7 @@ struct expr *osf_expr_alloc(const struct location *loc)
 
        expr = expr_alloc(loc, &osf_expr_ops, type,
                          BYTEORDER_HOST_ENDIAN, len);
+       expr->osf.ttl = ttl;
 
        return expr;
 }
index 36a987193c78dd6b641f97bd782b4b5a5b957489..dfe3068376241b8b56ba1a39d94f853e02fd6ea7 100644 (file)
 #include <inttypes.h>
 #include <syslog.h>
 #include <netinet/ip.h>
+#include <netinet/tcp.h>
 #include <netinet/if_ether.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter/nf_tables.h>
 #include <linux/netfilter/nf_conntrack_tuple_common.h>
 #include <linux/netfilter/nf_nat.h>
 #include <linux/netfilter/nf_log.h>
+#include <linux/netfilter/nfnetlink_osf.h>
 #include <linux/xfrm.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/icmp6.h>
@@ -740,6 +742,7 @@ int nft_lex(void *, void *, void *);
 %type <val>                    fib_tuple       fib_result      fib_flag
 
 %type <expr>                   osf_expr
+%type <val>                    osf_ttl
 %destructor { expr_free($$); } osf_expr
 
 %type <val>                    markup_format
@@ -3173,9 +3176,27 @@ fib_tuple                :       fib_flag        DOT     fib_tuple
                        |       fib_flag
                        ;
 
-osf_expr               :       OSF     NAME
+osf_expr               :       OSF     osf_ttl         NAME
                        {
-                               $$ = osf_expr_alloc(&@$);
+                               $$ = osf_expr_alloc(&@$, $2);
+                       }
+                       ;
+
+osf_ttl                        :       /* empty */
+                       {
+                               $$ = NF_OSF_TTL_TRUE;
+                       }
+                       |       TTL     STRING
+                       {
+                               if (!strcmp($2, "loose"))
+                                       $$ = NF_OSF_TTL_LESS;
+                               else if (!strcmp($2, "skip"))
+                                       $$ = NF_OSF_TTL_NOCHECK;
+                               else {
+                                       erec_queue(error(&@2, "invalid ttl option"),
+                                                  state->msgs);
+                                       YYERROR;
+                               }
                        }
                        ;
 
index 7047c00d78f6e5b533ec22f4599b277b84840bac..fc0dc9a9e40468f797bb2b68ba7e6353b6a6ffb9 100644 (file)
@@ -376,12 +376,13 @@ static struct expr *json_parse_osf_expr(struct json_ctx *ctx,
                                        const char *type, json_t *root)
 {
        const char *key;
+       uint8_t ttl;
 
-       if (json_unpack_err(ctx, root, "{s:s}", "key", &key))
+       if (json_unpack_err(ctx, root, "{s:i, s:s}", "ttl", ttl,"key", &key))
                return NULL;
 
        if (!strcmp(key, "name"))
-               return osf_expr_alloc(int_loc);
+               return osf_expr_alloc(int_loc, ttl);
 
        json_error(ctx, "Invalid osf key value.");
        return NULL;
index bccfc75116d480b260283545f4d9fbc0d8b832ad..fd5d9ed868ff0f5fb324d454c8061f8e5b981de9 100644 (file)
@@ -5,6 +5,9 @@
 *inet;osfinet;osfchain
 
 osf name "Linux";ok
+osf ttl loose name "Linux";ok
+osf ttl skip name "Linux";ok
+osf ttl nottl name "Linux";fail
 osf name "morethansixteenbytes";fail
 osf name ;fail
 osf name { "Windows", "MacOs" };ok
index 4bb413ca114a00816c65f48e286f8d56c5cd8bbb..45335cab30c0b0765d5d2844072617ff64f8f496 100644 (file)
@@ -4,6 +4,7 @@
         "match": {
             "left": {
                 "osf": {
+                    "ttl": 0,
                     "key": "name"
                 }
             },
@@ -19,6 +20,7 @@
         "match": {
             "left": {
                 "osf": {
+                    "ttl": 0,
                     "key": "name"
                 }
             },
@@ -58,6 +60,7 @@
                     },
                     "key": {
                         "osf": {
+                            "ttl": 0,
                             "key": "name"
                         }
                     }
index 850ca29e4711507a1ce297690ec992ec6c590e7c..9b8f0bc051725da41047e00d8788b8444ffbffee 100644 (file)
@@ -13,19 +13,83 @@ inet osfinet osfchain
   [ osf dreg 1 ]
   [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
 
+# osf ttl loose name "Linux"
+ip osfip osfchain
+  [ osf dreg 1 ]
+  [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl loose name "Linux"
+ip6 osfip6 osfchain
+  [ osf dreg 1 ]
+  [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl loose name "Linux"
+inet osfinet osfchain
+  [ osf dreg 1 ]
+  [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl skip name "Linux"
+ip osfip osfchain
+  [ osf dreg 1 ]
+  [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl skip name "Linux"
+ip6 osfip6 osfchain
+  [ osf dreg 1 ]
+  [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl skip name "Linux"
+inet osfinet osfchain
+  [ osf dreg 1 ]
+  [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf name { "Windows", "MacOs" }
+__set%d osfip 3 size 2
+__set%d osfip 0
+       element 646e6957 0073776f 00000000 00000000  : 0 [end]  element 4f63614d 00000073 00000000 00000000  : 0 [end]
+ip osfip osfchain
+  [ osf dreg 1 ]
+  [ lookup reg 1 set __set%d ]
+
+# osf name { "Windows", "MacOs" }
+__set%d osfip6 3 size 2
+__set%d osfip6 0
+       element 646e6957 0073776f 00000000 00000000  : 0 [end]  element 4f63614d 00000073 00000000 00000000  : 0 [end]
+ip6 osfip6 osfchain
+  [ osf dreg 1 ]
+  [ lookup reg 1 set __set%d ]
+
 # osf name { "Windows", "MacOs" }
 __set%d osfinet 3 size 2
 __set%d osfinet 0
        element 646e6957 0073776f 00000000 00000000  : 0 [end]  element 4f63614d 00000073 00000000 00000000  : 0 [end]
-inet osfinet osfchain 
+inet osfinet osfchain
   [ osf dreg 1 ]
   [ lookup reg 1 set __set%d ]
 
 # ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
 __map%d osfip b size 2
 __map%d osfip 0
-        element 646e6957 0073776f 00000000 00000000  : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000  : 00000002 0 [end]
+       element 646e6957 0073776f 00000000 00000000  : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000  : 00000002 0 [end]
 ip osfip osfchain
   [ osf dreg 1 ]
   [ lookup reg 1 set __map%d dreg 1 ]
   [ ct set mark with reg 1 ]
+
+# ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
+__map%d osfip6 b size 2
+__map%d osfip6 0
+       element 646e6957 0073776f 00000000 00000000  : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000  : 00000002 0 [end]
+ip6 osfip6 osfchain
+  [ osf dreg 1 ]
+  [ lookup reg 1 set __map%d dreg 1 ]
+  [ ct set mark with reg 1 ]
+
+# ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
+__map%d osfinet b size 2
+__map%d osfinet 0
+       element 646e6957 0073776f 00000000 00000000  : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000  : 00000002 0 [end]
+inet osfinet osfchain
+  [ osf dreg 1 ]
+  [ lookup reg 1 set __map%d dreg 1 ]
+  [ ct set mark with reg 1 ]