diff options
author | Patrick McHardy <kaber@trash.net> | 2014-01-08 13:02:16 +0000 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2014-01-08 13:03:19 +0000 |
commit | 4180fba3821d13f06fde2d662d7000e99d140693 (patch) | |
tree | 3e097a6b44d24765ff7a9c842915eb9e0a7398f6 /src | |
parent | b90667a2ae941d2b79630d0344ef489c2bf9d9aa (diff) |
meta: add nfproto support
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/datatype.c | 18 | ||||
-rw-r--r-- | src/meta.c | 35 | ||||
-rw-r--r-- | src/parser.y | 2 | ||||
-rw-r--r-- | src/payload.c | 2 | ||||
-rw-r--r-- | src/proto.c | 18 | ||||
-rw-r--r-- | src/scanner.l | 1 |
6 files changed, 66 insertions, 10 deletions
diff --git a/src/datatype.c b/src/datatype.c index 2e5788dc..fdcec8d1 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -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", @@ -301,6 +301,8 @@ static const struct meta_template meta_templates[] = { 4 * 8, BYTEORDER_HOST_ENDIAN), [NFT_META_PROTOCOL] = META_TEMPLATE("protocol", ðertype_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; } diff --git a/src/parser.y b/src/parser.y index 19073337..aed00c7f 100644 --- a/src/parser.y +++ b/src/parser.y @@ -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; } diff --git a/src/payload.c b/src/payload.c index 04a3455e..ac441d4e 100644 --- a/src/payload.c +++ b/src/payload.c @@ -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; } diff --git a/src/proto.c b/src/proto.c index c3fb7bf2..81fe6cfd 100644 --- a/src/proto.c +++ b/src/proto.c @@ -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), @@ -608,6 +609,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 */ diff --git a/src/scanner.l b/src/scanner.l index f075f820..9541eb05 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -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; } |