diff options
-rw-r--r-- | doc/libnftables.adoc | 10 | ||||
-rw-r--r-- | include/datatype.h | 1 | ||||
-rw-r--r-- | include/nftables.h | 5 | ||||
-rw-r--r-- | include/nftables/libnftables.h | 4 | ||||
-rw-r--r-- | src/datatype.c | 68 | ||||
-rw-r--r-- | src/evaluate.c | 10 |
6 files changed, 67 insertions, 31 deletions
diff --git a/doc/libnftables.adoc b/doc/libnftables.adoc index a0d3521e..62de75f3 100644 --- a/doc/libnftables.adoc +++ b/doc/libnftables.adoc @@ -84,7 +84,15 @@ The *nft_ctx_set_dry_run*() function sets the dry-run setting in 'ctx' to the va === nft_ctx_input_get_flags() and nft_ctx_input_set_flags() The flags setting controls the input format. -Currently no flags are implemented. +---- +enum { + NFT_CTX_INPUT_NO_DNS = (1 << 0), +}; +---- + +NFT_CTX_INPUT_NO_DNS:: + Avoid resolving IP addresses with blocking getaddrinfo(). In that case, + only plain IP addresses are accepted. The *nft_ctx_input_get_flags*() function returns the input flags setting's value in 'ctx'. diff --git a/include/datatype.h b/include/datatype.h index 4b59790b..be5c6d1b 100644 --- a/include/datatype.h +++ b/include/datatype.h @@ -182,6 +182,7 @@ struct datatype *dtype_clone(const struct datatype *orig_dtype); struct parse_ctx { struct symbol_tables *tbl; + const struct input_ctx *input; }; extern struct error_record *symbol_parse(struct parse_ctx *ctx, diff --git a/include/nftables.h b/include/nftables.h index 7d35a95a..666a17ae 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -27,6 +27,11 @@ struct input_ctx { unsigned int flags; }; +static inline bool nft_input_no_dns(const struct input_ctx *ictx) +{ + return ictx->flags & NFT_CTX_INPUT_NO_DNS; +} + struct output_ctx { unsigned int flags; union { diff --git a/include/nftables/libnftables.h b/include/nftables/libnftables.h index 9a05d3c4..e109805f 100644 --- a/include/nftables/libnftables.h +++ b/include/nftables/libnftables.h @@ -48,6 +48,10 @@ enum nft_optimize_flags { uint32_t nft_ctx_get_optimize(struct nft_ctx *ctx); void nft_ctx_set_optimize(struct nft_ctx *ctx, uint32_t flags); +enum { + NFT_CTX_INPUT_NO_DNS = (1 << 0), +}; + unsigned int nft_ctx_input_get_flags(struct nft_ctx *ctx); unsigned int nft_ctx_input_set_flags(struct nft_ctx *ctx, unsigned int flags); diff --git a/src/datatype.c b/src/datatype.c index 381320ea..64396db8 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -600,27 +600,33 @@ static struct error_record *ipaddr_type_parse(struct parse_ctx *ctx, const struct expr *sym, struct expr **res) { - struct addrinfo *ai, hints = { .ai_family = AF_INET, - .ai_socktype = SOCK_DGRAM}; - struct in_addr *addr; - int err; + struct in_addr addr; - err = getaddrinfo(sym->identifier, NULL, &hints, &ai); - if (err != 0) - return error(&sym->location, "Could not resolve hostname: %s", - gai_strerror(err)); + if (nft_input_no_dns(ctx->input)) { + if (inet_pton(AF_INET, sym->identifier, &addr) != 1) + return error(&sym->location, "Invalid IPv4 address"); + } else { + struct addrinfo *ai, hints = { .ai_family = AF_INET, + .ai_socktype = SOCK_DGRAM}; + int err; - if (ai->ai_next != NULL) { + err = getaddrinfo(sym->identifier, NULL, &hints, &ai); + if (err != 0) + return error(&sym->location, "Could not resolve hostname: %s", + gai_strerror(err)); + + if (ai->ai_next != NULL) { + freeaddrinfo(ai); + return error(&sym->location, + "Hostname resolves to multiple addresses"); + } + addr = ((struct sockaddr_in *)ai->ai_addr)->sin_addr; freeaddrinfo(ai); - return error(&sym->location, - "Hostname resolves to multiple addresses"); } - addr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr; *res = constant_expr_alloc(&sym->location, &ipaddr_type, BYTEORDER_BIG_ENDIAN, - sizeof(*addr) * BITS_PER_BYTE, addr); - freeaddrinfo(ai); + sizeof(addr) * BITS_PER_BYTE, &addr); return NULL; } @@ -659,27 +665,33 @@ static struct error_record *ip6addr_type_parse(struct parse_ctx *ctx, const struct expr *sym, struct expr **res) { - struct addrinfo *ai, hints = { .ai_family = AF_INET6, - .ai_socktype = SOCK_DGRAM}; - struct in6_addr *addr; - int err; + struct in6_addr addr; - err = getaddrinfo(sym->identifier, NULL, &hints, &ai); - if (err != 0) - return error(&sym->location, "Could not resolve hostname: %s", - gai_strerror(err)); + if (nft_input_no_dns(ctx->input)) { + if (inet_pton(AF_INET6, sym->identifier, &addr) != 1) + return error(&sym->location, "Invalid IPv6 address"); + } else { + struct addrinfo *ai, hints = { .ai_family = AF_INET6, + .ai_socktype = SOCK_DGRAM}; + int err; - if (ai->ai_next != NULL) { + err = getaddrinfo(sym->identifier, NULL, &hints, &ai); + if (err != 0) + return error(&sym->location, "Could not resolve hostname: %s", + gai_strerror(err)); + + if (ai->ai_next != NULL) { + freeaddrinfo(ai); + return error(&sym->location, + "Hostname resolves to multiple addresses"); + } + addr = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; freeaddrinfo(ai); - return error(&sym->location, - "Hostname resolves to multiple addresses"); } - addr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; *res = constant_expr_alloc(&sym->location, &ip6addr_type, BYTEORDER_BIG_ENDIAN, - sizeof(*addr) * BITS_PER_BYTE, addr); - freeaddrinfo(ai); + sizeof(addr) * BITS_PER_BYTE, &addr); return NULL; } diff --git a/src/evaluate.c b/src/evaluate.c index bdd3c651..2b158aee 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -277,7 +277,10 @@ static int flowtable_not_found(struct eval_ctx *ctx, const struct location *loc, */ static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr) { - struct parse_ctx parse_ctx = { .tbl = &ctx->nft->output.tbl, }; + struct parse_ctx parse_ctx = { + .tbl = &ctx->nft->output.tbl, + .input = &ctx->nft->input, + }; struct error_record *erec; struct table *table; struct set *set; @@ -3450,7 +3453,10 @@ static int stmt_evaluate_reject_default(struct eval_ctx *ctx, static int stmt_evaluate_reject_icmp(struct eval_ctx *ctx, struct stmt *stmt) { - struct parse_ctx parse_ctx = { .tbl = &ctx->nft->output.tbl, }; + struct parse_ctx parse_ctx = { + .tbl = &ctx->nft->output.tbl, + .input = &ctx->nft->input, + }; struct error_record *erec; struct expr *code; |