]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
meta: add nfproto support
authorPatrick McHardy <kaber@trash.net>
Wed, 8 Jan 2014 13:02:16 +0000 (13:02 +0000)
committerPatrick McHardy <kaber@trash.net>
Wed, 8 Jan 2014 13:03:19 +0000 (13:03 +0000)
Add support for the meta nfproto type, which refers to the AF from the
netfilter hook ops. This is needed to get the actual family of a packet
in the dummy NFPROTO_INET family.

Signed-off-by: Patrick McHardy <kaber@trash.net>
include/datatype.h
include/proto.h
src/datatype.c
src/meta.c
src/parser.y
src/payload.c
src/proto.c
src/scanner.l

index 239d5ea5718bcf1540abea45495d6255494f2837..9f8b44ae2bd61b88876f8c67459d2ad9a7de5263 100644 (file)
@@ -6,6 +6,7 @@
  *
  * @TYPE_INVALID:      uninitialized
  * @TYPE_VERDICT:      nftables verdict
+ * @TYPE_NFPROTO:      netfilter protocol (integer subtype)
  * @TYPE_BITMASK:      bitmask
  * @TYPE_INTEGER:      integer
  * @TYPE_STRING:       string
@@ -37,6 +38,7 @@
 enum datatypes {
        TYPE_INVALID,
        TYPE_VERDICT,
+       TYPE_NFPROTO,
        TYPE_BITMASK,
        TYPE_INTEGER,
        TYPE_STRING,
@@ -168,6 +170,7 @@ extern void rt_symbol_table_free(struct symbol_table *tbl);
 
 extern const struct datatype invalid_type;
 extern const struct datatype verdict_type;
+extern const struct datatype nfproto_type;
 extern const struct datatype bitmask_type;
 extern const struct datatype integer_type;
 extern const struct datatype string_type;
index 6a280367801c6721c84eeab1313ac8d33d3fc597..772f9ed7429e2bdd9fe2f8cc2c06fdf4219aae2c 100644 (file)
@@ -290,6 +290,8 @@ extern const struct proto_desc proto_icmp6;
 extern const struct proto_desc proto_ip;
 extern const struct proto_desc proto_ip6;
 
+extern const struct proto_desc proto_inet;
+
 extern const struct proto_desc proto_arp;
 
 extern const struct proto_desc proto_vlan;
index 2e5788dc8a6aa8ca8093032ab3fbe97b7f6bdb74..fdcec8d166240c7f0ced6d6f126d786323d4d9b2 100644 (file)
@@ -26,6 +26,7 @@
 static const struct datatype *datatypes[TYPE_MAX + 1] = {
        [TYPE_INVALID]          = &invalid_type,
        [TYPE_VERDICT]          = &verdict_type,
+       [TYPE_NFPROTO]          = &nfproto_type,
        [TYPE_BITMASK]          = &bitmask_type,
        [TYPE_INTEGER]          = &integer_type,
        [TYPE_STRING]           = &string_type,
@@ -204,6 +205,23 @@ const struct datatype verdict_type = {
        .print          = verdict_type_print,
 };
 
+static const struct symbol_table nfproto_tbl = {
+       .symbols        = {
+               SYMBOL("ipv4",          NFPROTO_IPV4),
+               SYMBOL("ipv6",          NFPROTO_IPV6),
+               SYMBOL_LIST_END
+       },
+};
+
+const struct datatype nfproto_type = {
+       .type           = TYPE_NFPROTO,
+       .name           = "nfproto",
+       .desc           = "netfilter protocol",
+       .size           = 1 * BITS_PER_BYTE,
+       .basetype       = &integer_type,
+       .sym_tbl        = &nfproto_tbl,
+};
+
 const struct datatype bitmask_type = {
        .type           = TYPE_BITMASK,
        .name           = "bitmask",
index e0ae9502ed8ff5c6fe103d8c7b0542f2040a9dd3..1286569aefb24860025bc18e541b2361ecc47100 100644 (file)
@@ -301,6 +301,8 @@ static const struct meta_template meta_templates[] = {
                                                4 * 8, BYTEORDER_HOST_ENDIAN),
        [NFT_META_PROTOCOL]     = META_TEMPLATE("protocol",  &ethertype_type,
                                                2 * 8, BYTEORDER_BIG_ENDIAN),
+       [NFT_META_NFPROTO]      = META_TEMPLATE("nfproto",   &nfproto_type,
+                                               1 * 8, BYTEORDER_HOST_ENDIAN),
        [NFT_META_PRIORITY]     = META_TEMPLATE("priority",  &tchandle_type,
                                                4 * 8, BYTEORDER_HOST_ENDIAN),
        [NFT_META_MARK]         = META_TEMPLATE("mark",      &mark_type,
@@ -356,18 +358,29 @@ static void meta_expr_pctx_update(struct proto_ctx *ctx,
        const struct expr *left = expr->left, *right = expr->right;
        const struct proto_desc *desc;
 
-       if (left->meta.key != NFT_META_IIFTYPE)
-               return;
-
        assert(expr->op == OP_EQ);
-       if (h->base < PROTO_BASE_NETWORK_HDR)
-               return;
 
-       desc = proto_dev_desc(mpz_get_uint16(right->value));
-       if (desc == NULL)
-               desc = &proto_unknown;
+       switch (left->meta.key) {
+       case NFT_META_IIFTYPE:
+               if (h->base < PROTO_BASE_NETWORK_HDR)
+                       return;
+
+               desc = proto_dev_desc(mpz_get_uint16(right->value));
+               if (desc == NULL)
+                       desc = &proto_unknown;
+
+               proto_ctx_update(ctx, PROTO_BASE_LL_HDR, &expr->location, desc);
+               break;
+       case NFT_META_NFPROTO:
+               desc = proto_find_upper(h->desc, mpz_get_uint8(right->value));
+               if (desc == NULL)
+                       desc = &proto_unknown;
 
-       proto_ctx_update(ctx, PROTO_BASE_LL_HDR, &expr->location, desc);
+               proto_ctx_update(ctx, PROTO_BASE_NETWORK_HDR, &expr->location, desc);
+               break;
+       default:
+               break;
+       }
 }
 
 static const struct expr_ops meta_expr_ops = {
@@ -391,6 +404,10 @@ struct expr *meta_expr_alloc(const struct location *loc, enum nft_meta_keys key)
        case NFT_META_IIFTYPE:
                expr->flags |= EXPR_F_PROTOCOL;
                break;
+       case NFT_META_NFPROTO:
+               expr->flags |= EXPR_F_PROTOCOL;
+               expr->meta.base = PROTO_BASE_LL_HDR;
+               break;
        default:
                break;
        }
index 190733378b4db81359c35b25d897ab2cface5993..aed00c7fcd1aaa4544bd09717b9994103baafb96 100644 (file)
@@ -281,6 +281,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token MH                      "mh"
 
 %token META                    "meta"
+%token NFPROTO                 "nfproto"
 %token MARK                    "mark"
 %token IIF                     "iif"
 %token IIFNAME                 "iifname"
@@ -1376,6 +1377,7 @@ meta_expr         :       META    meta_key
                        ;
 
 meta_key               :       LENGTH          { $$ = NFT_META_LEN; }
+                       |       NFPROTO         { $$ = NFT_META_NFPROTO; }
                        |       PROTOCOL        { $$ = NFT_META_PROTOCOL; }
                        |       PRIORITY        { $$ = NFT_META_PRIORITY; }
                        |       MARK            { $$ = NFT_META_MARK; }
index 04a3455e38f0d7fc692109e8dadb6e8527a293c9..ac441d4e5795768e7936a28d0b5c2d8c0a40c3df 100644 (file)
@@ -197,7 +197,7 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
                                    tmpl->len, &protocol);
 
        dep = relational_expr_alloc(&expr->location, OP_EQ, left, right);
-       payload_expr_pctx_update(&ctx->pctx, dep);
+       left->ops->pctx_update(&ctx->pctx, dep);
        *res = dep;
        return 0;
 }
index c3fb7bf2968405813c0cccc972ee2d4b2ba452da..81fe6cfdab0ed67e559067da183800580fb4c792 100644 (file)
@@ -123,6 +123,7 @@ const struct proto_desc *proto_dev_desc(uint16_t type)
 
 const struct hook_proto_desc hook_proto_desc[] = {
        [NFPROTO_BRIDGE]        = HOOK_PROTO_DESC(PROTO_BASE_LL_HDR,      &proto_eth),
+       [NFPROTO_INET]          = HOOK_PROTO_DESC(PROTO_BASE_LL_HDR,      &proto_inet),
        [NFPROTO_IPV4]          = HOOK_PROTO_DESC(PROTO_BASE_NETWORK_HDR, &proto_ip),
        [NFPROTO_IPV6]          = HOOK_PROTO_DESC(PROTO_BASE_NETWORK_HDR, &proto_ip6),
        [NFPROTO_ARP]           = HOOK_PROTO_DESC(PROTO_BASE_NETWORK_HDR, &proto_arp),
@@ -607,6 +608,23 @@ const struct proto_desc proto_ip6 = {
        },
 };
 
+/*
+ * Dummy protocol for mixed IPv4/IPv6 tables. The protocol is set at the link
+ * layer header, the upper layer protocols are IPv4 and IPv6.
+ */
+
+const struct proto_desc proto_inet = {
+       .name           = "inet",
+       .base           = PROTO_BASE_LL_HDR,
+       .protocols      = {
+               PROTO_LINK(NFPROTO_IPV4,        &proto_ip),
+               PROTO_LINK(NFPROTO_IPV6,        &proto_ip6),
+       },
+       .templates      = {
+               [0]     = PROTO_META_TEMPLATE("nfproto", &nfproto_type, NFT_META_NFPROTO, 8),
+       },
+};
+
 /*
  * ARP
  */
index f075f820c138c54085d39d2d635367b595ce68b2..9541eb0524dd7565c74bdef9c28ac9450de64717 100644 (file)
@@ -371,6 +371,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "mh"                   { return MH; }
 
 "meta"                 { return META; }
+"nfproto"              { return NFPROTO; }
 "mark"                 { return MARK; }
 "iif"                  { return IIF; }
 "iifname"              { return IIFNAME; }