[PATCH] Add ipv4=off option in resolver like ipv6=off (ticket #1330)

Ruslan Ermilov ru at nginx.com
Wed Feb 16 12:30:55 UTC 2022


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) {
@@ -273,6 +292,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 +863,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 +1290,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 +1791,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 +3674,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 +3683,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 +3765,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