Implement ipv4+ipv6 flags in resolv.conf

Message ID 197abaa9-0d8c-4b27-a462-d50e73048d4e@redhat.com
State Failed CI
Headers
Series Implement ipv4+ipv6 flags in resolv.conf |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch fail Patch failed to apply to master at the time it was sent
redhat-pt-bot/TryBot-32bit fail Patch series failed to apply

Commit Message

Petr Menšík Nov. 21, 2024, 9:13 p.m. UTC
  Hi!

I have made a rebase of my older attempt and would like some comments, 
if possible. The problem is described at bug #30544 [1]. My proposal 
would be simple disabling of sending A or AAAA queries on hosts. This is 
a bit modified previous patch.

What I want is to have getent ahosts example.com to resolve only IPv4 
address, if I added ipv4 option into /etc/resolv.conf. But at the same 
time it should tell me IPv6 address if I do getent ahostsv6 example.com. 
It does not have to lie, just does not ask unless asked explicitly.

That would make ping example.com try only IPv4 address, but ping -6 
example.com try IPv6 address. That is main change compared to noaaaa 
option. It should not prohibit query, just avoid unless someone asked.

Expected into future would be that NetworkManager or any service 
managing /etc/resolv.conf would add ipv4 when it has non-link local 
route to ipv4 and similar with ipv6 flag. But even if set manually now 
it can be useful, IMO.

I would like some pointers, how to make this feature tested. This is my 
first change proposed to glibc and I have no experience with making 
tests for it. Help with desired.

What do you think of that change?

Best Regards,
Petr

1. https://sourceware.org/bugzilla/show_bug.cgi?id=30544

-- 
Petr Menšík
Senior Software Engineer, RHEL
Red Hat, http://www.redhat.com/
PGP: DFCF908DB7C87E8E529925BC4931CA5B6C9FC5CB
  

Comments

Petr Menšík Nov. 21, 2024, 10:11 p.m. UTC | #1
Ah, but omitted IPV4 flag only. Second version attached here.

On 21. 11. 24 22:13, Petr Menšík wrote:
> Hi!
>
> I have made a rebase of my older attempt and would like some comments, 
> if possible. The problem is described at bug #30544 [1]. My proposal 
> would be simple disabling of sending A or AAAA queries on hosts. This 
> is a bit modified previous patch.
>
> What I want is to have getent ahosts example.com to resolve only IPv4 
> address, if I added ipv4 option into /etc/resolv.conf. But at the same 
> time it should tell me IPv6 address if I do getent ahostsv6 
> example.com. It does not have to lie, just does not ask unless asked 
> explicitly.
>
> That would make ping example.com try only IPv4 address, but ping -6 
> example.com try IPv6 address. That is main change compared to noaaaa 
> option. It should not prohibit query, just avoid unless someone asked.
>
> Expected into future would be that NetworkManager or any service 
> managing /etc/resolv.conf would add ipv4 when it has non-link local 
> route to ipv4 and similar with ipv6 flag. But even if set manually now 
> it can be useful, IMO.
>
> I would like some pointers, how to make this feature tested. This is 
> my first change proposed to glibc and I have no experience with making 
> tests for it. Help with desired.
>
> What do you think of that change?
>
> Best Regards,
> Petr
>
> 1. https://sourceware.org/bugzilla/show_bug.cgi?id=30544
>
-- 
Petr Menšík
Senior Software Engineer, RHEL
Red Hat, http://www.redhat.com/
PGP: DFCF908DB7C87E8E529925BC4931CA5B6C9FC5CB
  
Carlos O'Donell Nov. 25, 2024, 2:39 p.m. UTC | #2
On 11/21/24 4:13 PM, Petr Menšík wrote:
> What do you think of that change?

May you please repost this as a distinct v2?

Note that the v1 currently fails pre-commit CI:
https://patchwork.sourceware.org/project/glibc/patch/197abaa9-0d8c-4b27-a462-d50e73048d4e@redhat.com/
  
Petr Menšík Nov. 25, 2024, 6:23 p.m. UTC | #3
I have re-posted with subject: [PATCH] resolv.conf: implement ipv4+ipv6 
flags (bug 30544)

Sorry, added [PATCH v2] at first, but then regenerated patch and forgot 
to update version. Anyway, Thunderbird has broken that patch, v3 is the 
same as v2, just better formatted.

Is there a good way to send inline patches using Thunderbird client? 
Haven't found non-breaking way yet. But at least Patchwork understands 
attached patch files too.

On 25. 11. 24 15:39, Carlos O'Donell wrote:
> On 11/21/24 4:13 PM, Petr Menšík wrote:
>> What do you think of that change?
> May you please repost this as a distinct v2?
>
> Note that the v1 currently fails pre-commit CI:
> https://patchwork.sourceware.org/project/glibc/patch/197abaa9-0d8c-4b27-a462-d50e73048d4e@redhat.com/
>
  

Patch

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(-)

diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 1d60c51f5e..7161a802eb 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -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)
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index b0fe69b1aa..86a6e9e115 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -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);
diff --git a/resolv/res_init.c b/resolv/res_init.c
index cce842fa93..6cdeaf4e97 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 ("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)
diff --git a/resolv/resolv.h b/resolv/resolv.h
index f40d6c58ce..878692ffaa 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -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)
 
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
index cbdf377b84..155c5a7ffe 100644
--- a/resolv/tst-resolv-res_init-skeleton.c
+++ b/resolv/tst-resolv-res_init-skeleton.c
@@ -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