1ba7a69bc2
resolves: rhbz#2011709
205 lines
6.4 KiB
Diff
205 lines
6.4 KiB
Diff
From 222bce6b83421db1afdad24cf4e8ab7b1aa7b273 Mon Sep 17 00:00:00 2001
|
|
From: Laszlo Ersek <lersek@redhat.com>
|
|
Date: Tue, 18 Jan 2022 14:48:33 +0100
|
|
Subject: [PATCH] server/sockets: get rid of AI_ADDRCONFIG
|
|
|
|
The AI_ADDRCONFIG hint of getaddrinfo() is supposed to restrict the name
|
|
resolution to such address families (IPv4 vs. IPv6) for which the
|
|
resolving host has publicly routable addresses assigned.
|
|
|
|
The main problem with AI_ADDRCONFIG can be shown with the following
|
|
command line:
|
|
|
|
$ nbdkit -f -p 32776 -P pidfile -i ::1 --exit-with-parent null
|
|
|
|
On a host where ::1 is the only IPv6 address assigned (namely to the
|
|
loopback interface), the command fails with
|
|
|
|
> nbdkit: getaddrinfo: ::1: 32776: Address family for hostname not
|
|
> supported
|
|
|
|
due to the "publicly routable" requirement.
|
|
|
|
Remove AI_ADDRCONFIG from the getaddrinfo() hints, and as a replacement,
|
|
introduce the "-4" and "-6" options, similarly to netcat and ssh.
|
|
|
|
(1) This makes options of the form:
|
|
|
|
-i 127.0.0.1
|
|
-i ::1
|
|
|
|
work regardless of "public" IPv6 / IPv4 connectivity;
|
|
|
|
(2) options of the form
|
|
|
|
-i localhost
|
|
-i FQDN
|
|
|
|
will bind both IPv4 and IPv6 addresses of the desired interface(s);
|
|
|
|
(3) omitting the option "-i" will bind both IPv4 and IPv6 wildcard
|
|
addresses (0.0.0.0 and ::);
|
|
|
|
(4) the configurations in (2) and (3) can be restricted to IPv4 or IPv6
|
|
addresses by adding the "-4" or "-6" option, respectively.
|
|
|
|
Importantly, this change allows the "connect-tcp6" test case of libnbd to
|
|
pass on such hosts that have no IPv6 connectivity (i.e., where the only
|
|
assigned IPv6 address is ::1, namely on the loopback interface).
|
|
|
|
Ref: https://listman.redhat.com/archives/libguestfs/2022-January/msg00110.html
|
|
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
|
Message-Id: <20220118134833.13246-3-lersek@redhat.com>
|
|
[lersek@redhat.com: fix typo in "--exit-with-parent" (Eric)]
|
|
Acked-by: Eric Blake <eblake@redhat.com>
|
|
(cherry picked from commit 9eec2335d630ae8ef947a927c1922d725d482f4a)
|
|
---
|
|
common/utils/windows-compat.h | 7 -------
|
|
docs/nbdkit.pod | 20 +++++++++++++++++++-
|
|
docs/synopsis.txt | 3 ++-
|
|
server/internal.h | 1 +
|
|
server/main.c | 9 +++++++++
|
|
server/options.h | 4 +++-
|
|
server/sockets.c | 3 ++-
|
|
7 files changed, 36 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/common/utils/windows-compat.h b/common/utils/windows-compat.h
|
|
index 7695bf7e..658c1d8b 100644
|
|
--- a/common/utils/windows-compat.h
|
|
+++ b/common/utils/windows-compat.h
|
|
@@ -75,13 +75,6 @@ struct sockaddr_un
|
|
#define O_NOCTTY 0
|
|
#endif
|
|
|
|
-/* AI_ADDRCONFIG is not available on Windows. It enables a rather
|
|
- * obscure feature of getaddrinfo to do with IPv6.
|
|
- */
|
|
-#ifndef AI_ADDRCONFIG
|
|
-#define AI_ADDRCONFIG 0
|
|
-#endif
|
|
-
|
|
/* Windows <errno.h> lacks certain errnos, so replace them here as
|
|
* best we can.
|
|
*/
|
|
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
|
|
index 99cfb362..042607fb 100644
|
|
--- a/docs/nbdkit.pod
|
|
+++ b/docs/nbdkit.pod
|
|
@@ -173,6 +173,24 @@ Display information about nbdkit or a specific plugin:
|
|
|
|
Display brief command line usage information and exit.
|
|
|
|
+=item B<-4>
|
|
+
|
|
+=item B<--ipv4-only>
|
|
+
|
|
+=item B<-6>
|
|
+
|
|
+=item B<--ipv6-only>
|
|
+
|
|
+When a non-numeric argument is passed to the I<-i> option (such as a
|
|
+Fully Qualified Domain Name, or a host name from C</etc/hosts>),
|
|
+restrict the name resolution to IPv4 or IPv6 addresses.
|
|
+
|
|
+When the I<-i> option is omitted, listen on only the IPv4 or IPv6
|
|
+address of all interfaces (C<0.0.0.0> or C<::>, respectively).
|
|
+
|
|
+When both I<-4> and I<-6> options are present on the command line, the
|
|
+last one takes effect.
|
|
+
|
|
=item B<-D> PLUGIN.FLAG=N
|
|
|
|
=item B<-D> FILTER.FLAG=N
|
|
@@ -265,7 +283,7 @@ See also I<-u>.
|
|
=item B<--ipaddr> IPADDR
|
|
|
|
Listen on the specified interface. The default is to listen on all
|
|
-interfaces. See also I<-p>.
|
|
+interfaces. See also I<-4>, I<-6>, and I<-p>.
|
|
|
|
=item B<--log=stderr>
|
|
|
|
diff --git a/docs/synopsis.txt b/docs/synopsis.txt
|
|
index 07b9dcff..6154bb2e 100644
|
|
--- a/docs/synopsis.txt
|
|
+++ b/docs/synopsis.txt
|
|
@@ -1,4 +1,5 @@
|
|
-nbdkit [-D|--debug PLUGIN|FILTER|nbdkit.FLAG=N]
|
|
+nbdkit [-4|--ipv4-only] [-6|--ipv6-only]
|
|
+ [-D|--debug PLUGIN|FILTER|nbdkit.FLAG=N]
|
|
[-e|--exportname EXPORTNAME] [--exit-with-parent]
|
|
[--filter FILTER ...] [-f|--foreground]
|
|
[-g|--group GROUP] [-i|--ipaddr IPADDR]
|
|
diff --git a/server/internal.h b/server/internal.h
|
|
index bc81b786..46fcdd46 100644
|
|
--- a/server/internal.h
|
|
+++ b/server/internal.h
|
|
@@ -113,6 +113,7 @@ enum log_to {
|
|
LOG_TO_NULL, /* --log=null forced on the command line */
|
|
};
|
|
|
|
+extern int tcpip_sock_af;
|
|
extern struct debug_flag *debug_flags;
|
|
extern const char *export_name;
|
|
extern bool foreground;
|
|
diff --git a/server/main.c b/server/main.c
|
|
index 225258de..8e7ac149 100644
|
|
--- a/server/main.c
|
|
+++ b/server/main.c
|
|
@@ -86,6 +86,7 @@ static void error_if_stdio_closed (void);
|
|
static void switch_stdio (void);
|
|
static void winsock_init (void);
|
|
|
|
+int tcpip_sock_af = AF_UNSPEC; /* -4, -6 */
|
|
struct debug_flag *debug_flags; /* -D */
|
|
bool exit_with_parent; /* --exit-with-parent */
|
|
const char *export_name; /* -e */
|
|
@@ -367,6 +368,14 @@ main (int argc, char *argv[])
|
|
exit (EXIT_FAILURE);
|
|
#endif
|
|
|
|
+ case '4':
|
|
+ tcpip_sock_af = AF_INET;
|
|
+ break;
|
|
+
|
|
+ case '6':
|
|
+ tcpip_sock_af = AF_INET6;
|
|
+ break;
|
|
+
|
|
case 'D':
|
|
add_debug_flag (optarg);
|
|
break;
|
|
diff --git a/server/options.h b/server/options.h
|
|
index e59ef17f..39299b9d 100644
|
|
--- a/server/options.h
|
|
+++ b/server/options.h
|
|
@@ -59,8 +59,10 @@ enum {
|
|
VSOCK_OPTION,
|
|
};
|
|
|
|
-static const char *short_options = "D:e:fg:i:nop:P:rst:u:U:vV";
|
|
+static const char *short_options = "46D:e:fg:i:nop:P:rst:u:U:vV";
|
|
static const struct option long_options[] = {
|
|
+ { "ipv4-only", no_argument, NULL, '4' },
|
|
+ { "ipv6-only", no_argument, NULL, '6' },
|
|
{ "debug", required_argument, NULL, 'D' },
|
|
{ "dump-config", no_argument, NULL, DUMP_CONFIG_OPTION },
|
|
{ "dump-plugin", no_argument, NULL, DUMP_PLUGIN_OPTION },
|
|
diff --git a/server/sockets.c b/server/sockets.c
|
|
index 15a26f69..4e4ccbc4 100644
|
|
--- a/server/sockets.c
|
|
+++ b/server/sockets.c
|
|
@@ -179,7 +179,8 @@ bind_tcpip_socket (sockets *socks)
|
|
port = "10809";
|
|
|
|
memset (&hints, 0, sizeof hints);
|
|
- hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
|
|
+ hints.ai_flags = AI_PASSIVE;
|
|
+ hints.ai_family = tcpip_sock_af;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
err = getaddrinfo (ipaddr, port, &hints, &ai);
|
|
--
|
|
2.31.1
|
|
|