]> git.ipfire.org Git - thirdparty/libnftnl.git/commitdiff
src: add TCP option matching requirements
authorManuel Messner <mm@skelett.io>
Tue, 7 Feb 2017 02:15:18 +0000 (03:15 +0100)
committerFlorian Westphal <fw@strlen.de>
Sun, 12 Feb 2017 00:18:38 +0000 (01:18 +0100)
This patch is a requirement of the TCP option patch.

Signed-off-by: Manuel Messner <mm@skelett.io>
Signed-off-by: Florian Westphal <fw@strlen.de>
include/libnftnl/expr.h
include/linux/netfilter/nf_tables.h
src/expr/exthdr.c

index 38a4b83efffa9bfe53fc96a142240ce3125f9db5..f5e9cc133b7aa0b69c1f02d1caedf0bdc95c7d8c 100644 (file)
@@ -156,6 +156,7 @@ enum {
        NFTNL_EXPR_EXTHDR_TYPE,
        NFTNL_EXPR_EXTHDR_OFFSET,
        NFTNL_EXPR_EXTHDR_LEN,
+       NFTNL_EXPR_EXTHDR_OP,
 };
 
 enum {
index b00a05d1ee566f18ff07fc6a2cf73643081b87af..6c0c9efddad6e548433e21b98e61c985e75ebb86 100644 (file)
@@ -705,12 +705,13 @@ enum nft_payload_attributes {
 #define NFTA_PAYLOAD_MAX       (__NFTA_PAYLOAD_MAX - 1)
 
 /**
- * enum nft_exthdr_attributes - nf_tables IPv6 extension header expression netlink attributes
+ * enum nft_exthdr_attributes - nf_tables extension header expression netlink attributes
  *
  * @NFTA_EXTHDR_DREG: destination register (NLA_U32: nft_registers)
  * @NFTA_EXTHDR_TYPE: extension header type (NLA_U8)
  * @NFTA_EXTHDR_OFFSET: extension header offset (NLA_U32)
  * @NFTA_EXTHDR_LEN: extension header length (NLA_U32)
+ * @NFTA_EXTHDR_OP: option match type (NLA_U8)
  */
 enum nft_exthdr_attributes {
        NFTA_EXTHDR_UNSPEC,
@@ -718,10 +719,24 @@ enum nft_exthdr_attributes {
        NFTA_EXTHDR_TYPE,
        NFTA_EXTHDR_OFFSET,
        NFTA_EXTHDR_LEN,
+       NFTA_EXTHDR_OP,
        __NFTA_EXTHDR_MAX
 };
 #define NFTA_EXTHDR_MAX                (__NFTA_EXTHDR_MAX - 1)
 
+/**
+ * enum nft_exthdr_op - nf_tables match options
+ *
+ * @NFT_EXTHDR_OP_IPV6: match against ipv6 extension headers
+ * @NFT_EXTHDR_OP_TCP: match against tcp options
+ */
+enum nft_exthdr_op {
+       NFT_EXTHDR_OP_IPV6,
+       NFT_EXTHDR_OP_TCPOPT,
+       __NFT_EXTHDR_OP_MAX
+};
+#define NFT_EXTHDR_OP_MAX      (__NFT_EXTHDR_OP_MAX - 1)
+
 /**
  * enum nft_meta_keys - nf_tables meta expression keys
  *
index b164e3fba3de439622a735c4992bd05eb7726fc5..a64c1bb81cb5fea4effa6ceeccc3745b0b5e37fb 100644 (file)
@@ -33,6 +33,7 @@ struct nftnl_expr_exthdr {
        uint32_t                offset;
        uint32_t                len;
        uint8_t                 type;
+       uint32_t                op;
 };
 
 static int
@@ -54,6 +55,9 @@ nftnl_expr_exthdr_set(struct nftnl_expr *e, uint16_t type,
        case NFTNL_EXPR_EXTHDR_LEN:
                exthdr->len = *((uint32_t *)data);
                break;
+       case NFTNL_EXPR_EXTHDR_OP:
+               exthdr->op = *((uint32_t *)data);
+               break;
        default:
                return -1;
        }
@@ -79,6 +83,9 @@ nftnl_expr_exthdr_get(const struct nftnl_expr *e, uint16_t type,
        case NFTNL_EXPR_EXTHDR_LEN:
                *data_len = sizeof(exthdr->len);
                return &exthdr->len;
+       case NFTNL_EXPR_EXTHDR_OP:
+               *data_len = sizeof(exthdr->op);
+               return &exthdr->op;
        }
        return NULL;
 }
@@ -99,6 +106,7 @@ static int nftnl_expr_exthdr_cb(const struct nlattr *attr, void *data)
        case NFTA_EXTHDR_DREG:
        case NFTA_EXTHDR_OFFSET:
        case NFTA_EXTHDR_LEN:
+       case NFTA_EXTHDR_OP:
                if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
                        abi_breakage();
                break;
@@ -121,6 +129,8 @@ nftnl_expr_exthdr_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
                mnl_attr_put_u32(nlh, NFTA_EXTHDR_OFFSET, htonl(exthdr->offset));
        if (e->flags & (1 << NFTNL_EXPR_EXTHDR_LEN))
                mnl_attr_put_u32(nlh, NFTA_EXTHDR_LEN, htonl(exthdr->len));
+       if (e->flags & (1 << NFTNL_EXPR_EXTHDR_OP))
+               mnl_attr_put_u32(nlh, NFTA_EXTHDR_OP, htonl(exthdr->op));
 }
 
 static int
@@ -148,10 +158,25 @@ nftnl_expr_exthdr_parse(struct nftnl_expr *e, struct nlattr *attr)
                exthdr->len = ntohl(mnl_attr_get_u32(tb[NFTA_EXTHDR_LEN]));
                e->flags |= (1 << NFTNL_EXPR_EXTHDR_LEN);
        }
+       if (tb[NFTA_EXTHDR_OP]) {
+               exthdr->op = ntohl(mnl_attr_get_u32(tb[NFTA_EXTHDR_OP]));
+               e->flags |= (1 << NFTNL_EXPR_EXTHDR_OP);
+       }
 
        return 0;
 }
 
+static const char *op2str(uint8_t op)
+{
+       switch (op) {
+       case NFT_EXTHDR_OP_TCPOPT:
+               return " tcpopt";
+       case NFT_EXTHDR_OP_IPV6:
+       default:
+               return "";
+       }
+}
+
 static const char *type2str(uint32_t type)
 {
        switch (type) {
@@ -170,6 +195,15 @@ static const char *type2str(uint32_t type)
        }
 }
 
+static inline int str2exthdr_op(const char* str)
+{
+       if (!strcmp(str, "tcpopt"))
+               return NFT_EXTHDR_OP_TCPOPT;
+
+       /* if str == "ipv6" or anything else */
+       return NFT_EXTHDR_OP_IPV6;
+}
+
 static inline int str2exthdr_type(const char *str)
 {
        if (strcmp(str, "hopopts") == 0)
@@ -193,6 +227,7 @@ nftnl_expr_exthdr_json_parse(struct nftnl_expr *e, json_t *root,
 #ifdef JSON_PARSING
        const char *exthdr_type;
        uint32_t uval32;
+       uint8_t uval8;
        int type;
 
        if (nftnl_jansson_parse_reg(root, "dreg", NFTNL_TYPE_U32, &uval32,
@@ -214,6 +249,9 @@ nftnl_expr_exthdr_json_parse(struct nftnl_expr *e, json_t *root,
        if (nftnl_jansson_parse_val(root, "len", NFTNL_TYPE_U32, &uval32, err) == 0)
                nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_LEN, uval32);
 
+       if (nftnl_jansson_parse_val(root, "op", NFTNL_TYPE_U32, &uval32, err) == 0)
+               nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_OP, uval32);
+
        return 0;
 #else
        errno = EOPNOTSUPP;
@@ -235,6 +273,8 @@ static int nftnl_expr_exthdr_export(char *buf, size_t len,
                nftnl_buf_u32(&b, type, exthdr->offset, OFFSET);
        if (e->flags & (1 << NFTNL_EXPR_EXTHDR_LEN))
                nftnl_buf_u32(&b, type, exthdr->len, LEN);
+       if (e->flags & (1 << NFTNL_EXPR_EXTHDR_OP))
+               nftnl_buf_u32(&b, type, exthdr->op, OP);
 
        return nftnl_buf_done(&b);
 }
@@ -243,10 +283,9 @@ static int nftnl_expr_exthdr_snprintf_default(char *buf, size_t len,
                                              const struct nftnl_expr *e)
 {
        struct nftnl_expr_exthdr *exthdr = nftnl_expr_data(e);
-
-       return snprintf(buf, len, "load %ub @ %u + %u => reg %u ",
-                       exthdr->len, exthdr->type, exthdr->offset,
-                       exthdr->dreg);
+       return snprintf(buf, len, "load%s %ub @ %u + %u => reg %u ",
+                       op2str(exthdr->op), exthdr->len, exthdr->type,
+                       exthdr->offset, exthdr->dreg);
 }
 
 static int
@@ -280,6 +319,8 @@ static bool nftnl_expr_exthdr_cmp(const struct nftnl_expr *e1,
                eq &= (h1->len == h2->len);
        if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_TYPE))
                eq &= (h1->type == h2->type);
+       if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_OP))
+               eq &= (h1->op == h2->op);
 
        return eq;
 }