]> git.ipfire.org Git - thirdparty/libnftnl.git/commitdiff
expr: limit: add support for flags
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 11 Jan 2016 18:38:24 +0000 (19:38 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 13 Jan 2016 12:44:53 +0000 (13:44 +0100)
This patch adds the limit flags, the first client of this is the
inversion flag that allows us to match overlimit.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/libnftnl/expr.h
include/linux/netfilter/nf_tables.h
src/expr/limit.c
tests/nft-expr_limit-test.c

index ab2c5ba40e0c17d86fdbce8ecd88b067a44332e8..cb2e8a3d8d81874de5f1f5ca263a44959bb96f19 100644 (file)
@@ -155,6 +155,7 @@ enum {
        NFTNL_EXPR_LIMIT_UNIT,
        NFTNL_EXPR_LIMIT_BURST,
        NFTNL_EXPR_LIMIT_TYPE,
+       NFTNL_EXPR_LIMIT_FLAGS,
 };
 
 enum {
index f77693bddc4ce5d66229706e2adf97e804d3517c..9d65ac27e6efb1033f3b296a256618975d1a502f 100644 (file)
@@ -780,6 +780,10 @@ enum nft_limit_type {
        NFT_LIMIT_PKT_BYTES
 };
 
+enum nft_limit_flags {
+       NFT_LIMIT_F_INV = (1 << 0),
+};
+
 /**
  * enum nft_limit_attributes - nf_tables limit expression netlink attributes
  *
@@ -787,6 +791,7 @@ enum nft_limit_type {
  * @NFTA_LIMIT_UNIT: refill unit (NLA_U64)
  * @NFTA_LIMIT_BURST: burst (NLA_U32)
  * @NFTA_LIMIT_TYPE: type of limit (NLA_U32: enum nft_limit_type)
+ * @NFTA_LIMIT_FLAGS: flags (NLA_U32: enum nft_limit_flags)
  */
 enum nft_limit_attributes {
        NFTA_LIMIT_UNSPEC,
@@ -794,6 +799,7 @@ enum nft_limit_attributes {
        NFTA_LIMIT_UNIT,
        NFTA_LIMIT_BURST,
        NFTA_LIMIT_TYPE,
+       NFTA_LIMIT_FLAGS,
        __NFTA_LIMIT_MAX
 };
 #define NFTA_LIMIT_MAX         (__NFTA_LIMIT_MAX - 1)
index ab9ceffa98fb1b5500764e54e75ff0f11f2a10d6..2c21eb54d2416d399fdf06ee9d672221455ffbf3 100644 (file)
@@ -27,6 +27,7 @@ struct nftnl_expr_limit {
        uint64_t                unit;
        uint32_t                burst;
        enum nft_limit_type     type;
+       uint32_t                flags;
 };
 
 static int
@@ -48,6 +49,9 @@ nftnl_expr_limit_set(struct nftnl_expr *e, uint16_t type,
        case NFTNL_EXPR_LIMIT_TYPE:
                limit->type = *((uint32_t *)data);
                break;
+       case NFTNL_EXPR_LIMIT_FLAGS:
+               limit->flags = *((uint32_t *)data);
+               break;
        default:
                return -1;
        }
@@ -73,6 +77,9 @@ nftnl_expr_limit_get(const struct nftnl_expr *e, uint16_t type,
        case NFTNL_EXPR_LIMIT_TYPE:
                *data_len = sizeof(uint32_t);
                return &limit->type;
+       case NFTNL_EXPR_LIMIT_FLAGS:
+               *data_len = sizeof(uint32_t);
+               return &limit->flags;
        }
        return NULL;
 }
@@ -93,6 +100,7 @@ static int nftnl_expr_limit_cb(const struct nlattr *attr, void *data)
                break;
        case NFTA_LIMIT_BURST:
        case NFTA_LIMIT_TYPE:
+       case NFTA_LIMIT_FLAGS:
                if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
                        abi_breakage();
                break;
@@ -115,6 +123,8 @@ nftnl_expr_limit_build(struct nlmsghdr *nlh, struct nftnl_expr *e)
                mnl_attr_put_u32(nlh, NFTA_LIMIT_BURST, htonl(limit->burst));
        if (e->flags & (1 << NFTNL_EXPR_LIMIT_TYPE))
                mnl_attr_put_u32(nlh, NFTA_LIMIT_TYPE, htonl(limit->type));
+       if (e->flags & (1 << NFTNL_EXPR_LIMIT_FLAGS))
+               mnl_attr_put_u32(nlh, NFTA_LIMIT_FLAGS, htonl(limit->flags));
 }
 
 static int
@@ -142,6 +152,10 @@ nftnl_expr_limit_parse(struct nftnl_expr *e, struct nlattr *attr)
                limit->type = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_TYPE]));
                e->flags |= (1 << NFTNL_EXPR_LIMIT_TYPE);
        }
+       if (tb[NFTA_LIMIT_FLAGS]) {
+               limit->flags = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_FLAGS]));
+               e->flags |= (1 << NFTNL_EXPR_LIMIT_FLAGS);
+       }
 
        return 0;
 }
@@ -162,6 +176,8 @@ static int nftnl_expr_limit_json_parse(struct nftnl_expr *e, json_t *root,
                nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_BURST, uval32);
        if (nftnl_jansson_parse_val(root, "type", NFTNL_TYPE_U32, &uval32, err) == 0)
                nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_TYPE, uval32);
+       if (nftnl_jansson_parse_val(root, "flags", NFTNL_TYPE_U32, &uval32, err) == 0)
+               nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_FLAGS, uval32);
 
        return 0;
 #else
@@ -176,7 +192,7 @@ static int nftnl_expr_limit_xml_parse(struct nftnl_expr *e,
 {
 #ifdef XML_PARSING
        uint64_t rate, unit;
-       uint32_t burst, type;
+       uint32_t burst, type, flags;
 
        if (nftnl_mxml_num_parse(tree, "rate", MXML_DESCEND_FIRST, BASE_DEC,
                               &rate, NFTNL_TYPE_U64, NFTNL_XML_MAND, err) == 0)
@@ -191,6 +207,9 @@ static int nftnl_expr_limit_xml_parse(struct nftnl_expr *e,
        if (nftnl_mxml_num_parse(tree, "type", MXML_DESCEND_FIRST, BASE_DEC,
                               &type, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
                nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_TYPE, type);
+       if (nftnl_mxml_num_parse(tree, "flags", MXML_DESCEND_FIRST, BASE_DEC,
+                              &flags, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
+               nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_FLAGS, flags);
 
        return 0;
 #else
@@ -225,6 +244,8 @@ static int nftnl_expr_limit_export(char *buf, size_t size,
                nftnl_buf_u32(&b, type, limit->burst, BURST);
        if (e->flags & (1 << NFTNL_EXPR_LIMIT_TYPE))
                nftnl_buf_u32(&b, type, limit->type, TYPE);
+       if (e->flags & (1 << NFTNL_EXPR_LIMIT_FLAGS))
+               nftnl_buf_u32(&b, type, limit->flags, FLAGS);
 
        return nftnl_buf_done(&b);
 }
@@ -246,16 +267,15 @@ static int nftnl_expr_limit_snprintf_default(char *buf, size_t len,
 {
        struct nftnl_expr_limit *limit = nftnl_expr_data(e);
 
-       return snprintf(buf, len, "rate %"PRIu64"/%s burst %u type %s ",
+       return snprintf(buf, len, "rate %"PRIu64"/%s burst %u type %s flags 0x%x ",
                        limit->rate, get_unit(limit->unit), limit->burst,
-                       limit_to_type(limit->type));
+                       limit_to_type(limit->type), limit->flags);
 }
 
 static int
 nftnl_expr_limit_snprintf(char *buf, size_t len, uint32_t type,
                            uint32_t flags, struct nftnl_expr *e)
 {
-
        switch(type) {
        case NFTNL_OUTPUT_DEFAULT:
                return nftnl_expr_limit_snprintf_default(buf, len, e);
index bbc82c1c5f01f8da0ad64944ce9cfa5736ecf925..29fb4894b23e55e5c47d5b8afa9c2a5ecf9e55d0 100644 (file)
@@ -43,6 +43,9 @@ static void cmp_nftnl_expr(struct nftnl_expr *rule_a,
        if (nftnl_expr_get_u64(rule_a, NFTNL_EXPR_LIMIT_TYPE) !=
            nftnl_expr_get_u64(rule_b, NFTNL_EXPR_LIMIT_TYPE))
                print_err("Expr TYPE mismatches");
+       if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_LIMIT_FLAGS) !=
+           nftnl_expr_get_u32(rule_b, NFTNL_EXPR_LIMIT_FLAGS))
+               print_err("Expr FLAGS mismatches");
 }
 
 int main(int argc, char *argv[])
@@ -66,6 +69,7 @@ int main(int argc, char *argv[])
        nftnl_expr_set_u64(ex, NFTNL_EXPR_LIMIT_UNIT, 0x123456789abcdef0);
        nftnl_expr_set_u32(ex, NFTNL_EXPR_LIMIT_BURST, 0x89123456);
        nftnl_expr_set_u32(ex, NFTNL_EXPR_LIMIT_TYPE, 0xdef01234);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_LIMIT_FLAGS, 0xdef01234);
 
        nftnl_rule_add_expr(a, ex);