]> git.ipfire.org Git - thirdparty/libnftnl.git/commitdiff
bitwise: add support for left- and right-shifts.
authorJeremy Sowden <jeremy@azazel.net>
Fri, 17 Jan 2020 20:58:08 +0000 (20:58 +0000)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 18 Jan 2020 20:23:33 +0000 (21:23 +0100)
The kernel supports bitwise shifts.  Add support to libnftnl.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/expr/bitwise.c
tests/nft-expr_bitwise-test.c

index 6ea39fbbe2eedfb295bb5c5442fa9696ad0a2522..9ea2f662b3e682c88c1038fca27e7e9ac58d7049 100644 (file)
@@ -233,6 +233,25 @@ nftnl_expr_bitwise_snprintf_bool(char *buf, size_t size,
        return offset;
 }
 
+static int
+nftnl_expr_bitwise_snprintf_shift(char *buf, size_t size, const char *op,
+                                 const struct nftnl_expr_bitwise *bitwise)
+{      int remain = size, offset = 0, ret;
+
+       ret = snprintf(buf, remain, "reg %u = ( reg %u %s ",
+                      bitwise->dreg, bitwise->sreg, op);
+       SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+       ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->data,
+                                     NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+       SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+       ret = snprintf(buf + offset, remain, ") ");
+       SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+       return offset;
+}
+
 static int nftnl_expr_bitwise_snprintf_default(char *buf, size_t size,
                                               const struct nftnl_expr *e)
 {
@@ -244,7 +263,10 @@ static int nftnl_expr_bitwise_snprintf_default(char *buf, size_t size,
                err = nftnl_expr_bitwise_snprintf_bool(buf, size, bitwise);
                break;
        case NFT_BITWISE_LSHIFT:
+               err = nftnl_expr_bitwise_snprintf_shift(buf, size, "<<", bitwise);
+               break;
        case NFT_BITWISE_RSHIFT:
+               err = nftnl_expr_bitwise_snprintf_shift(buf, size, ">>", bitwise);
                break;
        }
 
index 41c0af435283968ac27c756cd1d52324b6eca27b..74a0e2aa6933a70f57c57eddaa51a9b0999f27be 100644 (file)
 
 static int test_ok = 1;
 
-static void print_err(const char *msg)
+static void print_err(const char *test, const char *msg)
 {
        test_ok = 0;
-       printf("\033[31mERROR:\e[0m %s\n", msg);
+       printf("\033[31mERROR:\e[0m [%s] %s\n", test, msg);
 }
 
-static void cmp_nftnl_expr(struct nftnl_expr *rule_a,
-                          struct nftnl_expr *rule_b)
+static void cmp_nftnl_expr_bool(struct nftnl_expr *rule_a,
+                               struct nftnl_expr *rule_b)
 {
        uint32_t maska, maskb;
        uint32_t xora, xorb;
 
        if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_DREG) !=
            nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_DREG))
-               print_err("Expr BITWISE_DREG mismatches");
+               print_err("bool", "Expr BITWISE_DREG mismatches");
        if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_SREG) !=
            nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_SREG))
-               print_err("Expr BITWISE_SREG mismatches");
+               print_err("bool", "Expr BITWISE_SREG mismatches");
        if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_OP) !=
            nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_OP))
-               print_err("Expr BITWISE_OP mismatches");
+               print_err("bool", "Expr BITWISE_OP mismatches");
        if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_LEN) !=
            nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_LEN))
-               print_err("Expr BITWISE_DREG mismatches");
+               print_err("bool", "Expr BITWISE_DREG mismatches");
        nftnl_expr_get(rule_a, NFTNL_EXPR_BITWISE_MASK, &maska);
        nftnl_expr_get(rule_b, NFTNL_EXPR_BITWISE_MASK, &maskb);
        if (maska != maskb)
-               print_err("Size of BITWISE_MASK mismatches");
+               print_err("bool", "Size of BITWISE_MASK mismatches");
        nftnl_expr_get(rule_a, NFTNL_EXPR_BITWISE_XOR, &xora);
        nftnl_expr_get(rule_b, NFTNL_EXPR_BITWISE_XOR, &xorb);
        if (xora != xorb)
-               print_err("Size of BITWISE_XOR mismatches");
+               print_err("bool", "Size of BITWISE_XOR mismatches");
 }
 
-int main(int argc, char *argv[])
+static void cmp_nftnl_expr_lshift(struct nftnl_expr *rule_a,
+                                 struct nftnl_expr *rule_b)
+{
+       uint32_t data_a, data_b;
+
+       if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_DREG) !=
+           nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_DREG))
+               print_err("lshift", "Expr BITWISE_DREG mismatches");
+       if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_SREG) !=
+           nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_SREG))
+               print_err("lshift", "Expr BITWISE_SREG mismatches");
+       if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_OP) !=
+           nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_OP))
+               print_err("lshift", "Expr BITWISE_OP mismatches");
+       if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_LEN) !=
+           nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_LEN))
+               print_err("lshift", "Expr BITWISE_LEN mismatches");
+       nftnl_expr_get(rule_a, NFTNL_EXPR_BITWISE_DATA, &data_a);
+       nftnl_expr_get(rule_b, NFTNL_EXPR_BITWISE_DATA, &data_b);
+       if (data_a != data_b)
+               print_err("lshift", "Expr BITWISE_DATA mismatches");
+}
+
+static void cmp_nftnl_expr_rshift(struct nftnl_expr *rule_a,
+                                 struct nftnl_expr *rule_b)
+{
+       uint32_t data_a, data_b;
+
+       if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_DREG) !=
+           nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_DREG))
+               print_err("rshift", "Expr BITWISE_DREG mismatches");
+       if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_SREG) !=
+           nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_SREG))
+               print_err("rshift", "Expr BITWISE_SREG mismatches");
+       if (nftnl_expr_get_u32(rule_a, NFTNL_EXPR_BITWISE_OP) !=
+           nftnl_expr_get_u32(rule_b, NFTNL_EXPR_BITWISE_OP))
+               print_err("rshift", "Expr BITWISE_OP mismatches");
+       if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_LEN) !=
+           nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_LEN))
+               print_err("rshift", "Expr BITWISE_LEN mismatches");
+       nftnl_expr_get(rule_a, NFTNL_EXPR_BITWISE_DATA, &data_a);
+       nftnl_expr_get(rule_b, NFTNL_EXPR_BITWISE_DATA, &data_b);
+       if (data_a != data_b)
+               print_err("rshift", "Expr BITWISE_DATA mismatches");
+}
+
+static void test_bool(void)
 {
        struct nftnl_rule *a, *b = NULL;
        struct nftnl_expr *ex = NULL;
@@ -69,10 +115,10 @@ int main(int argc, char *argv[])
        a = nftnl_rule_alloc();
        b = nftnl_rule_alloc();
        if (a == NULL || b == NULL)
-               print_err("OOM");
+               print_err("bool", "OOM");
        ex = nftnl_expr_alloc("bitwise");
        if (ex == NULL)
-               print_err("OOM");
+               print_err("bool", "OOM");
 
        nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_SREG, 0x12345678);
        nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DREG, 0x78123456);
@@ -87,30 +133,150 @@ int main(int argc, char *argv[])
        nftnl_rule_nlmsg_build_payload(nlh, a);
 
        if (nftnl_rule_nlmsg_parse(nlh, b) < 0)
-               print_err("parsing problems");
+               print_err("bool", "parsing problems");
+
+       iter_a = nftnl_expr_iter_create(a);
+       iter_b = nftnl_expr_iter_create(b);
+       if (iter_a == NULL || iter_b == NULL)
+               print_err("bool", "OOM");
+
+       rule_a = nftnl_expr_iter_next(iter_a);
+       rule_b = nftnl_expr_iter_next(iter_b);
+       if (rule_a == NULL || rule_b == NULL)
+               print_err("bool", "OOM");
+
+       if (nftnl_expr_iter_next(iter_a) != NULL ||
+           nftnl_expr_iter_next(iter_b) != NULL)
+               print_err("bool", "More 1 expr.");
+
+       nftnl_expr_iter_destroy(iter_a);
+       nftnl_expr_iter_destroy(iter_b);
+
+       cmp_nftnl_expr_bool(rule_a,rule_b);
+
+       nftnl_rule_free(a);
+       nftnl_rule_free(b);
+}
+
+static void test_lshift(void)
+{
+       struct nftnl_rule *a, *b = NULL;
+       struct nftnl_expr *ex = NULL;
+       struct nlmsghdr *nlh;
+       char buf[4096];
+       struct nftnl_expr_iter *iter_a, *iter_b = NULL;
+       struct nftnl_expr *rule_a, *rule_b = NULL;
+
+       a = nftnl_rule_alloc();
+       b = nftnl_rule_alloc();
+       if (a == NULL || b == NULL)
+               print_err("lshift", "OOM");
+       ex = nftnl_expr_alloc("bitwise");
+       if (ex == NULL)
+               print_err("lshift", "OOM");
+
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_SREG, 0x12345678);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DREG, 0x78123456);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_OP, NFT_BITWISE_LSHIFT);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_LEN, 0x56781234);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DATA, 13);
+
+       nftnl_rule_add_expr(a, ex);
+
+       nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234);
+       nftnl_rule_nlmsg_build_payload(nlh, a);
+
+       if (nftnl_rule_nlmsg_parse(nlh, b) < 0)
+               print_err("lshift", "parsing problems");
 
        iter_a = nftnl_expr_iter_create(a);
        iter_b = nftnl_expr_iter_create(b);
        if (iter_a == NULL || iter_b == NULL)
-               print_err("OOM");
+               print_err("lshift", "OOM");
 
        rule_a = nftnl_expr_iter_next(iter_a);
        rule_b = nftnl_expr_iter_next(iter_b);
        if (rule_a == NULL || rule_b == NULL)
-               print_err("OOM");
+               print_err("lshift", "OOM");
 
        if (nftnl_expr_iter_next(iter_a) != NULL ||
            nftnl_expr_iter_next(iter_b) != NULL)
-               print_err("More 1 expr.");
+               print_err("lshift", "More 1 expr.");
 
        nftnl_expr_iter_destroy(iter_a);
        nftnl_expr_iter_destroy(iter_b);
 
-       cmp_nftnl_expr(rule_a,rule_b);
+       cmp_nftnl_expr_lshift(rule_a,rule_b);
 
        nftnl_rule_free(a);
        nftnl_rule_free(b);
+}
+
+static void test_rshift(void)
+{
+       struct nftnl_rule *a, *b = NULL;
+       struct nftnl_expr *ex = NULL;
+       struct nlmsghdr *nlh;
+       char buf[4096];
+       struct nftnl_expr_iter *iter_a, *iter_b = NULL;
+       struct nftnl_expr *rule_a, *rule_b = NULL;
+
+       a = nftnl_rule_alloc();
+       b = nftnl_rule_alloc();
+       if (a == NULL || b == NULL)
+               print_err("rshift", "OOM");
+       ex = nftnl_expr_alloc("bitwise");
+       if (ex == NULL)
+               print_err("rshift", "OOM");
+
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_SREG, 0x12345678);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DREG, 0x78123456);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_OP, NFT_BITWISE_RSHIFT);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_LEN, 0x56781234);
+       nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DATA, 17);
+
+       nftnl_rule_add_expr(a, ex);
+
+       nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234);
+       nftnl_rule_nlmsg_build_payload(nlh, a);
+
+       if (nftnl_rule_nlmsg_parse(nlh, b) < 0)
+               print_err("rshift", "parsing problems");
+
+       iter_a = nftnl_expr_iter_create(a);
+       iter_b = nftnl_expr_iter_create(b);
+       if (iter_a == NULL || iter_b == NULL)
+               print_err("rshift", "OOM");
+
+       rule_a = nftnl_expr_iter_next(iter_a);
+       rule_b = nftnl_expr_iter_next(iter_b);
+       if (rule_a == NULL || rule_b == NULL)
+               print_err("rshift", "OOM");
+
+       if (nftnl_expr_iter_next(iter_a) != NULL ||
+           nftnl_expr_iter_next(iter_b) != NULL)
+               print_err("rshift", "More 1 expr.");
+
+       nftnl_expr_iter_destroy(iter_a);
+       nftnl_expr_iter_destroy(iter_b);
+
+       cmp_nftnl_expr_rshift(rule_a,rule_b);
+
+       nftnl_rule_free(a);
+       nftnl_rule_free(b);
+}
+
+int main(int argc, char *argv[])
+{
+       test_bool();
+       if (!test_ok)
+               exit(EXIT_FAILURE);
+
+       test_lshift();
+       if (!test_ok)
+               exit(EXIT_FAILURE);
 
+       test_rshift();
        if (!test_ok)
                exit(EXIT_FAILURE);