[PATCH v5 1/2] resolv: implement ipv4+ipv6 flags in resolv.conf (bug 30544)
Petr Menšík
pemensik@redhat.com
Thu Oct 16 10:30:37 GMT 2025
Ah, AI_ALL flag cannot modify _nss_dns_gethostbyname4_r behavior,
because _nss_dns_gethostbyname4_r does not receive original hints data
passed into getaddrinfo call. Nor its ai_flags field at least.
I think new bug requesting more fields in some
new _nss_dns_gethostbyname5_r should mention also ai_flags should be
passed into gethostbyname4 successor. Ideally whole hints pointer.
So no, cannot implement it with current interface, will have to wait for
later improved interface.
Created bug https://sourceware.org/bugzilla/show_bug.cgi?id=33544 for this.
Is there is a bug for new _nss_dns_gethostbyname5_r requirements? Is it
tracked somewhere else?
Cheers, Petr
On 15/10/2025 20:29, Adhemerval Zanella Netto wrote:
>>> The name of new options is for a discussion. I like ipv4 and ipv6 as more beginner friendly. It might make sense to rename ipv4 to "a" and ipv6 to "aaaa" instead. But it would be a bit confusing that aaaa is not just negative of no-aaaa option, but something slightly different.
>>>
> I don't have a strong preference, but I tend to prefer 'ipv4'/'ipv6'
> instead of the historical 'a'/'aaaa'.
>
>>> Also, it might help adding supporting AI_ALL flag to get all addresses, just like ipv4 and ipv6 options were specified, but per request. Reverting to current behaviour regarless of flags.
> Would it be the same as the current behavior (without flags)? Not sure
> if this is an improvement.
>
>>> Or adding similar new flag AI_ALLAF instead? Allowing to ignore those flags per-request only? What do you think about this change itself?
> It is not clear to me how different it would be from AI_ALL.
>
> The patch is sound, although I don't have much experience in this area.
>
>> ---
>> resolv/nss_dns/dns-host.c | 50 +++++++++++++++++----------
>> resolv/res_debug.c | 2 ++
>> resolv/res_init.c | 2 ++
>> resolv/resolv.h | 2 ++
>> resolv/tst-resolv-res_init-skeleton.c | 2 ++
>> 5 files changed, 40 insertions(+), 18 deletions(-)
>>
>> diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
>> index 14da73ee1d..99e8e5ce4c 100644
>> --- a/resolv/nss_dns/dns-host.c
>> +++ b/resolv/nss_dns/dns-host.c
>> @@ -379,6 +379,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
>> {
>> enum nss_status status = check_name (name, herrnop);
>> char tmp[NS_MAXDNAME];
>> +
>> if (status != NSS_STATUS_SUCCESS)
>> return status;
>> struct resolv_context *ctx = __resolv_context_get ();
>> @@ -412,26 +413,39 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
>>
>> int olderr = errno;
>> int n;
>> + int res_options = ctx->resp->options & (RES_NOAAAA|RES_IPV4|RES_IPV6);
> The 'struct __res_state' option is an unsigned long, using int might be
> problem with flags that exceeds INT_MAX.
>
>> + int qtype;
>>
>> - if ((ctx->resp->options & RES_NOAAAA) == 0)
>> + switch (res_options)
>> {
>> - n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
>> - dns_packet_buffer, sizeof (dns_packet_buffer),
>> - &alt_dns_packet_buffer, &ans2p, &nans2p,
>> - &resplen2, &ans2p_malloced);
>> - if (n >= 0)
>> - status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2,
>> - &abuf, pat, errnop, herrnop, ttlp);
>> - }
>> - else
>> - {
>> - n = __res_context_search (ctx, name, C_IN, T_A,
>> - dns_packet_buffer, sizeof (dns_packet_buffer),
>> - &alt_dns_packet_buffer, NULL, NULL, NULL, NULL);
>> - if (n >= 0)
>> - status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
>> - &abuf, pat, errnop, herrnop, ttlp);
>> - }
>> + case RES_IPV4:
>> + case RES_IPV4|RES_NOAAAA:
>> + case RES_NOAAAA:
>> + case RES_IPV6|RES_NOAAAA: /*< this combination should never be used. */
> Double space after period.
>
>> + case RES_IPV4|RES_IPV6|RES_NOAAAA: /*< this does not make sense. */
>> + case RES_IPV6: /*< oh we want AAAA, but not A here. code is the same. */
>> + qtype = (res_options == RES_IPV6 ? T_AAAA : T_A);
>> + n = __res_context_search (ctx, name, C_IN, qtype,
>> + dns_packet_buffer, sizeof (dns_packet_buffer),
>> + &alt_dns_packet_buffer, NULL, NULL, NULL, NULL);
>> + if (n >= 0)
>> + status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
>> + &abuf, pat, errnop, herrnop, ttlp);
>> + break;
>> +
>> + case 0:
>> + case RES_IPV4|RES_IPV6:
>> + default:
>> + n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
>> + dns_packet_buffer, sizeof (dns_packet_buffer),
>> + &alt_dns_packet_buffer, &ans2p, &nans2p,
>> + &resplen2, &ans2p_malloced);
>> + if (n >= 0)
>> + status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2,
>> + &abuf, pat, errnop, herrnop, ttlp);
>> + break;
>> + }
>> +
>> if (n < 0)
>> {
>> switch (errno)
>> diff --git a/resolv/res_debug.c b/resolv/res_debug.c
>> index 73af0c72fe..f73bccd7bd 100644
>> --- a/resolv/res_debug.c
>> +++ b/resolv/res_debug.c
>> @@ -613,6 +613,8 @@ p_option(u_long option) {
>> case RES_NORELOAD: return "no-reload";
>> case RES_TRUSTAD: return "trust-ad";
>> case RES_NOAAAA: return "no-aaaa";
>> + case RES_IPV4: return "ipv4";
>> + case RES_IPV6: return "ipv6";
>> /* XXX nonreentrant */
>> default: sprintf(nbuf, "?0x%lx?", (u_long)option);
>> return (nbuf);
>> diff --git a/resolv/res_init.c b/resolv/res_init.c
>> index aed1902ec5..2e898d3fb3 100644
>> --- a/resolv/res_init.c
>> +++ b/resolv/res_init.c
>> @@ -696,6 +696,8 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
>> { STRnLEN ("trust-ad"), RES_TRUSTAD },
>> { STRnLEN ("no-aaaa"), RES_NOAAAA },
>> { STRnLEN ("strict-error"), RES_STRICTERR },
>> + { STRnLEN ("ipv4"), RES_IPV4 },
>> + { STRnLEN ("ipv6"), RES_IPV6 },
>> };
>> #define noptions (sizeof (options) / sizeof (options[0]))
>> bool negate_option = *cp == '-';
>> diff --git a/resolv/resolv.h b/resolv/resolv.h
>> index b8a0f66a5f..647881243d 100644
>> --- a/resolv/resolv.h
>> +++ b/resolv/resolv.h
>> @@ -134,6 +134,8 @@ struct res_sym {
>> #define RES_TRUSTAD 0x04000000 /* Request AD bit, keep it in responses. */
>> #define RES_NOAAAA 0x08000000 /* Suppress AAAA queries. */
>> #define RES_STRICTERR 0x10000000 /* Report more DNS errors as errors. */
>> +#define RES_IPV4 0x20000000 /* Query A records on PF_UNSPEC hints. */
>> +#define RES_IPV6 0x40000000 /* Query AAAA records on PF_UNSPEC hints. */
> Double space after period.
>
>>
>> #define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH)
>>
>> diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
>> index 3ccbe71db9..3d99f4b5e5 100644
>> --- a/resolv/tst-resolv-res_init-skeleton.c
>> +++ b/resolv/tst-resolv-res_init-skeleton.c
>> @@ -130,6 +130,8 @@ print_resp (FILE *fp, res_state resp)
>> print_option_flag (fp, &options, RES_TRUSTAD, "trust-ad");
>> print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa");
>> print_option_flag (fp, &options, RES_STRICTERR, "strict-error");
>> + print_option_flag (fp, &options, RES_IPV4, "ipv4");
>> + print_option_flag (fp, &options, RES_IPV6, "ipv6");
>> fputc ('\n', fp);
>> if (options != 0)
>> fprintf (fp, "; error: unresolved option bits: 0x%x\n", options);
--
Petr Menšík
Senior Software Engineer, RHEL
Red Hat,https://www.redhat.com/
PGP: DFCF908DB7C87E8E529925BC4931CA5B6C9FC5CB
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20251016/368de234/attachment.htm>
More information about the Libc-alpha
mailing list