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

Lukas Lihotzki lukas at lihotzki.de
Sat May 28 16:29:32 UTC 2022


This patch works great (both with and without Addon). Can it be upstreamed?


On 23.02.22 05:09, Ruslan Ermilov wrote:
> 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;
> _______________________________________________
> nginx-devel mailing list -- nginx-devel at nginx.org
> To unsubscribe send an email to nginx-devel-leave at nginx.org



More information about the nginx-devel mailing list