From 54871094aa2843416696384dd1dca97a4cd9cce3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
Date: Mon, 3 Jul 2023 08:32:20 +0200
Subject: [PATCH] First attempt to implement ipv4+ipv6 flags
Add separate flags to mark support of address family. Its intention is
to react dynamically to changing network conditions. If the host has
IPv4 connectivity only, it would set ipv4 option. If it has also IPv6
connectivity, it would set ipv6 option. If it connects IPv6-only
network, then it set ipv6 only.
For backward compatibility it will keep old behaviour when both ipv4 and
ipv6 flags are missing. In this case it behaves the same way as if both
were present.
Resolves: https://sourceware.org/bugzilla/show_bug.cgi?id=30544
---
resolv/nss_dns/dns-host.c | 54 ++++++++++++++++++---------
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, 44 insertions(+), 18 deletions(-)
@@ -413,25 +413,43 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
int olderr = errno;
int n;
- if ((ctx->resp->options & RES_NOAAAA) == 0)
+ switch (ctx->resp->options & (RES_NOAAAA|RES_IPV4|RES_IPV6))
{
- 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),
- NULL, 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. */
+ case RES_IPV4|RES_IPV6|RES_NOAAAA: /*< this does not make sense either. */
+ n = __res_context_search (ctx, name, C_IN, T_A,
+ dns_packet_buffer, sizeof (dns_packet_buffer),
+ NULL, NULL, NULL, NULL, NULL);
+ if (n >= 0)
+ status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
+ &abuf, pat, errnop, herrnop, ttlp);
+ break;
+
+ case RES_IPV6:
+ n = __res_context_search (ctx, name, C_IN, T_AAAA,
+ dns_packet_buffer, sizeof (dns_packet_buffer),
+ NULL, 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)
@@ -614,6 +614,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);
@@ -696,6 +696,8 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
{ STRnLEN ("use-vc"), 0, RES_USEVC },
{ STRnLEN ("trust-ad"), 0, RES_TRUSTAD },
{ STRnLEN ("no-aaaa"), 0, RES_NOAAAA },
+ { STRnLEN ("ipv4"), 0, RES_IPV4 },
+ { STRnLEN ("ipv6"), 0, RES_IPV6 },
};
#define noptions (sizeof (options) / sizeof (options[0]))
for (int i = 0; i < noptions; ++i)
@@ -133,6 +133,8 @@ struct res_sym {
#define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */
#define RES_TRUSTAD 0x04000000 /* Request AD bit, keep it in responses. */
#define RES_NOAAAA 0x08000000 /* Suppress AAAA queries. */
+#define RES_IPV4 0x10000000 /* Query A records on PF_UNSPEC hints. */
+#define RES_IPV6 0x20000000 /* Query AAAA records on PF_UNSPEC hints. */
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH)
@@ -129,6 +129,8 @@ print_resp (FILE *fp, res_state resp)
print_option_flag (fp, &options, RES_NORELOAD, "no-reload");
print_option_flag (fp, &options, RES_TRUSTAD, "trust-ad");
print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa");
+ 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);
--
2.41.0