[PATCH] Add ipv4=off option in resolver like ipv6=off (ticket #1330)
Ruslan Ermilov
ru at nginx.com
Wed Feb 23 04:09:34 UTC 2022
On Wed, Feb 16, 2022 at 03:30:55PM +0300, Ruslan Ermilov wrote:
> Hi Lukas,
>
> On Wed, Jan 19, 2022 at 07:47:44PM +0100, Lukas Lihotzki via nginx-devel wrote:
> > # HG changeset patch
> > # User Lukas Lihotzki <lukas at lihotzki.de>
> > # Date 1642618053 -3600
> > # Wed Jan 19 19:47:33 2022 +0100
> > # Node ID e9f06dc2d6a4a1aa61c15009b84ceedcaf5983b2
> > # Parent aeab41dfd2606dd36cabbf01f1472726e27e8aea
> > Add ipv4=off option in resolver like ipv6=off (ticket #1330).
> >
> > IPv6-only hosts (ticket #1330) and upstreams with IPv6 bind address
> > (ticket #1535) need to disable resolving to IPv4 addresses.
> >
> > Ticket #1330 mentions ipv4=off is the proper fix.
>
> There's a number of problems in your patch. Please try this
> one instead:
>
> # HG changeset patch
> # User Ruslan Ermilov <ru at nginx.com>
> # Date 1644873563 -10800
> # Tue Feb 15 00:19:23 2022 +0300
> # Node ID 5d2cb60a78dd32a10a0010ccff39974fd7605867
> # Parent 1add55d236522616ce34ffaa4dc697a76d3d41a4
> The "ipv4=" parameter of the "resolver" directive (ticket #2196).
>
> When set to "off", only IPv6 addresses will be resolved, and no
> A queries are ever sent.
>
> diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
> --- a/src/core/ngx_resolver.c
> +++ b/src/core/ngx_resolver.c
> @@ -157,6 +157,8 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
> cln->handler = ngx_resolver_cleanup;
> cln->data = r;
>
> + r->ipv4 = 1;
> +
> ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,
> ngx_resolver_rbtree_insert_value);
>
> @@ -225,6 +227,23 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
> }
>
> #if (NGX_HAVE_INET6)
> + if (ngx_strncmp(names[i].data, "ipv4=", 5) == 0) {
> +
> + if (ngx_strcmp(&names[i].data[5], "on") == 0) {
> + r->ipv4 = 1;
> +
> + } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
> + r->ipv4 = 0;
> +
> + } else {
> + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
> + "invalid parameter: %V", &names[i]);
> + return NULL;
> + }
> +
> + continue;
> + }
> +
> if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {
>
> if (ngx_strcmp(&names[i].data[5], "on") == 0) {
Addon to the patch:
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -229,10 +229,12 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
#if (NGX_HAVE_INET6)
if (ngx_strncmp(names[i].data, "ipv4=", 5) == 0) {
- if (ngx_strcmp(&names[i].data[5], "on") == 0) {
+ if (ngx_strcasecmp(&names[i].data[5], (u_char *) "on") == 0) {
r->ipv4 = 1;
- } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
+ } else if (ngx_strcasecmp(&names[i].data[5], (u_char *) "off")
+ == 0)
+ {
r->ipv4 = 0;
} else {
@@ -246,10 +248,12 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {
- if (ngx_strcmp(&names[i].data[5], "on") == 0) {
+ if (ngx_strcasecmp(&names[i].data[5], (u_char *) "on") == 0) {
r->ipv6 = 1;
- } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
+ } else if (ngx_strcasecmp(&names[i].data[5], (u_char *) "off")
+ == 0)
+ {
r->ipv6 = 0;
} else {
And a full updated patch:
# HG changeset patch
# User Ruslan Ermilov <ru at nginx.com>
# Date 1645589317 -10800
# Wed Feb 23 07:08:37 2022 +0300
# Node ID 1c19779448db2309d607c74e2628ff98f84569ff
# Parent 1add55d236522616ce34ffaa4dc697a76d3d41a4
The "ipv4=" parameter of the "resolver" directive (ticket #2196).
When set to "off", only IPv6 addresses will be resolved, and no
A queries are ever sent.
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -157,6 +157,8 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
cln->handler = ngx_resolver_cleanup;
cln->data = r;
+ r->ipv4 = 1;
+
ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,
ngx_resolver_rbtree_insert_value);
@@ -225,12 +227,33 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
}
#if (NGX_HAVE_INET6)
+ if (ngx_strncmp(names[i].data, "ipv4=", 5) == 0) {
+
+ if (ngx_strcasecmp(&names[i].data[5], (u_char *) "on") == 0) {
+ r->ipv4 = 1;
+
+ } else if (ngx_strcasecmp(&names[i].data[5], (u_char *) "off")
+ == 0)
+ {
+ r->ipv4 = 0;
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter: %V", &names[i]);
+ return NULL;
+ }
+
+ continue;
+ }
+
if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {
- if (ngx_strcmp(&names[i].data[5], "on") == 0) {
+ if (ngx_strcasecmp(&names[i].data[5], (u_char *) "on") == 0) {
r->ipv6 = 1;
- } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
+ } else if (ngx_strcasecmp(&names[i].data[5], (u_char *) "off")
+ == 0)
+ {
r->ipv6 = 0;
} else {
@@ -273,6 +296,14 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
}
}
+#if (NGX_HAVE_INET6)
+ if (r->ipv4 + r->ipv6 == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"ipv4\" and \"ipv6\" cannot both be \"off\"");
+ return NULL;
+ }
+#endif
+
if (n && r->connections.nelts == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no name servers defined");
return NULL;
@@ -836,7 +867,7 @@ ngx_resolve_name_locked(ngx_resolver_t *
r->last_connection = 0;
}
- rn->naddrs = (u_short) -1;
+ rn->naddrs = r->ipv4 ? (u_short) -1 : 0;
rn->tcp = 0;
#if (NGX_HAVE_INET6)
rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
@@ -1263,7 +1294,7 @@ ngx_resolver_send_query(ngx_resolver_t *
rec->log.action = "resolving";
}
- if (rn->naddrs == (u_short) -1) {
+ if (rn->query && rn->naddrs == (u_short) -1) {
rc = rn->tcp ? ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen)
: ngx_resolver_send_udp_query(r, rec, rn->query, rn->qlen);
@@ -1764,10 +1795,13 @@ ngx_resolver_process_response(ngx_resolv
q = ngx_queue_next(q))
{
rn = ngx_queue_data(q, ngx_resolver_node_t, queue);
- qident = (rn->query[0] << 8) + rn->query[1];
-
- if (qident == ident) {
- goto dns_error_name;
+
+ if (rn->query) {
+ qident = (rn->query[0] << 8) + rn->query[1];
+
+ if (qident == ident) {
+ goto dns_error_name;
+ }
}
#if (NGX_HAVE_INET6)
@@ -3644,7 +3678,7 @@ ngx_resolver_create_name_query(ngx_resol
len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
#if (NGX_HAVE_INET6)
- p = ngx_resolver_alloc(r, r->ipv6 ? len * 2 : len);
+ p = ngx_resolver_alloc(r, len * (r->ipv4 + r->ipv6));
#else
p = ngx_resolver_alloc(r, len);
#endif
@@ -3653,23 +3687,28 @@ ngx_resolver_create_name_query(ngx_resol
}
rn->qlen = (u_short) len;
- rn->query = p;
+
+ if (r->ipv4) {
+ rn->query = p;
+ }
#if (NGX_HAVE_INET6)
if (r->ipv6) {
- rn->query6 = p + len;
+ rn->query6 = r->ipv4 ? (p + len) : p;
}
#endif
query = (ngx_resolver_hdr_t *) p;
- ident = ngx_random();
-
- ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
- "resolve: \"%V\" A %i", name, ident & 0xffff);
-
- query->ident_hi = (u_char) ((ident >> 8) & 0xff);
- query->ident_lo = (u_char) (ident & 0xff);
+ if (r->ipv4) {
+ ident = ngx_random();
+
+ ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
+ "resolve: \"%V\" A %i", name, ident & 0xffff);
+
+ query->ident_hi = (u_char) ((ident >> 8) & 0xff);
+ query->ident_lo = (u_char) (ident & 0xff);
+ }
/* recursion query */
query->flags_hi = 1; query->flags_lo = 0;
@@ -3730,7 +3769,9 @@ ngx_resolver_create_name_query(ngx_resol
p = rn->query6;
- ngx_memcpy(p, rn->query, rn->qlen);
+ if (r->ipv4) {
+ ngx_memcpy(p, rn->query, rn->qlen);
+ }
query = (ngx_resolver_hdr_t *) p;
diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h
--- a/src/core/ngx_resolver.h
+++ b/src/core/ngx_resolver.h
@@ -175,8 +175,10 @@ struct ngx_resolver_s {
ngx_queue_t srv_expire_queue;
ngx_queue_t addr_expire_queue;
+ unsigned ipv4:1;
+
#if (NGX_HAVE_INET6)
- ngx_uint_t ipv6; /* unsigned ipv6:1; */
+ unsigned ipv6:1;
ngx_rbtree_t addr6_rbtree;
ngx_rbtree_node_t addr6_sentinel;
ngx_queue_t addr6_resend_queue;
More information about the nginx-devel
mailing list