diff options
-rw-r--r-- | include/proto.h | 1 | ||||
-rw-r--r-- | src/meta.c | 14 | ||||
-rw-r--r-- | src/parser.y | 2 | ||||
-rw-r--r-- | src/payload.c | 6 | ||||
-rw-r--r-- | src/proto.c | 25 | ||||
-rw-r--r-- | src/scanner.l | 1 |
6 files changed, 49 insertions, 0 deletions
diff --git a/include/proto.h b/include/proto.h index 772f9ed7..bd3701e3 100644 --- a/include/proto.h +++ b/include/proto.h @@ -291,6 +291,7 @@ 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_inet_service; extern const struct proto_desc proto_arp; @@ -303,6 +303,8 @@ static const struct meta_template meta_templates[] = { 2 * 8, BYTEORDER_BIG_ENDIAN), [NFT_META_NFPROTO] = META_TEMPLATE("nfproto", &nfproto_type, 1 * 8, BYTEORDER_HOST_ENDIAN), + [NFT_META_L4PROTO] = META_TEMPLATE("l4proto", &inet_protocol_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, @@ -378,6 +380,14 @@ static void meta_expr_pctx_update(struct proto_ctx *ctx, proto_ctx_update(ctx, PROTO_BASE_NETWORK_HDR, &expr->location, desc); break; + case NFT_META_L4PROTO: + desc = proto_find_upper(&proto_inet_service, + mpz_get_uint8(right->value)); + if (desc == NULL) + desc = &proto_unknown; + + proto_ctx_update(ctx, PROTO_BASE_TRANSPORT_HDR, &expr->location, desc); + break; default: break; } @@ -408,6 +418,10 @@ struct expr *meta_expr_alloc(const struct location *loc, enum nft_meta_keys key) expr->flags |= EXPR_F_PROTOCOL; expr->meta.base = PROTO_BASE_LL_HDR; break; + case NFT_META_L4PROTO: + expr->flags |= EXPR_F_PROTOCOL; + expr->meta.base = PROTO_BASE_NETWORK_HDR; + break; default: break; } diff --git a/src/parser.y b/src/parser.y index aed00c7f..7c18875d 100644 --- a/src/parser.y +++ b/src/parser.y @@ -282,6 +282,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token META "meta" %token NFPROTO "nfproto" +%token L4PROTO "l4proto" %token MARK "mark" %token IIF "iif" %token IIFNAME "iifname" @@ -1378,6 +1379,7 @@ meta_expr : META meta_key meta_key : LENGTH { $$ = NFT_META_LEN; } | NFPROTO { $$ = NFT_META_NFPROTO; } + | L4PROTO { $$ = NFT_META_L4PROTO; } | PROTOCOL { $$ = NFT_META_PROTOCOL; } | PRIORITY { $$ = NFT_META_PRIORITY; } | MARK { $$ = NFT_META_MARK; } diff --git a/src/payload.c b/src/payload.c index ac441d4e..a312e079 100644 --- a/src/payload.c +++ b/src/payload.c @@ -174,6 +174,12 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr, } desc = ctx->pctx.protocol[expr->payload.base - 1].desc; + /* Special case for mixed IPv4/IPv6 tables: use meta L4 proto */ + if (desc == NULL && + ctx->pctx.family == NFPROTO_INET && + expr->payload.base == PROTO_BASE_TRANSPORT_HDR) + desc = &proto_inet_service; + if (desc == NULL) return expr_error(ctx, expr, "ambiguous payload specification: " diff --git a/src/proto.c b/src/proto.c index 81fe6cfd..56fb7930 100644 --- a/src/proto.c +++ b/src/proto.c @@ -626,6 +626,31 @@ const struct proto_desc proto_inet = { }; /* + * Dummy protocol for cases where the network layer protocol isn't known + * (IPv4 or IPv6), The higher layer protocols are the protocols common to + * both. + */ + +const struct proto_desc proto_inet_service = { + .name = "inet-service", + .base = PROTO_BASE_TRANSPORT_HDR, + .protocol_key = 0, + .protocols = { + PROTO_LINK(IPPROTO_ESP, &proto_esp), + PROTO_LINK(IPPROTO_AH, &proto_ah), + PROTO_LINK(IPPROTO_COMP, &proto_comp), + PROTO_LINK(IPPROTO_UDP, &proto_udp), + PROTO_LINK(IPPROTO_UDPLITE, &proto_udplite), + PROTO_LINK(IPPROTO_TCP, &proto_tcp), + PROTO_LINK(IPPROTO_DCCP, &proto_dccp), + PROTO_LINK(IPPROTO_SCTP, &proto_sctp), + }, + .templates = { + [0] = PROTO_META_TEMPLATE("l4proto", &inet_protocol_type, NFT_META_L4PROTO, 8), + }, +}; + +/* * ARP */ diff --git a/src/scanner.l b/src/scanner.l index 9541eb05..0b8abacb 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -372,6 +372,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "meta" { return META; } "nfproto" { return NFPROTO; } +"l4proto" { return L4PROTO; } "mark" { return MARK; } "iif" { return IIF; } "iifname" { return IIFNAME; } |