On 03/31/22 15:14, Richard W.M. Jones wrote:
On Thu, Mar 31, 2022 at 09:22:11AM +0200, Laszlo Ersek wrote:
> (This patch is similar to nbdkit commit 9eec2335d630, "server/sockets: get
> rid of AI_ADDRCONFIG", 2022-01-19).
>
> Consider the following call tree:
>
> start_conversion() [conversion.c]
> start_nbd_server() [nbd.c]
> open_listening_socket() [nbd.c]
> bind_tcpip_socket() [nbd.c]
> getaddrinfo()
> socket()
> bind()
> wait_for_nbd_server_to_start() [nbd.c]
> connect_to_nbdkit() [nbd.c]
> getaddrinfo()
> socket()
> connect()
> open_data_connection() [ssh.c]
> /* "-R 0:localhost:<port>" */
>
> - For each of IPv4 and IPv6, if the network config on the host running
> virt-p2v supports that protocol, then bind_tcpip_socket() intends to
> bind the port for that protocol.
>
> - connect_to_nbdkit() connects to the port using *one* of IPv4 and IPv6;
> it just wants to see NBDMAGIC, regardless of IP version.
>
> - The ssh "-R 0:localhost:<port>" option, formatted by
> open_data_connection(), instructs ssh to create a reverse forwarding
> channel (a listening socket) per IP version (this can be verified with
> "netstat" on the conversion server). In case the reverse NBD connection
> on the conversion server were made to sshd over IPv6, then ssh on the
> p2v server would presumably want to connect to nbdkit over IPv6 too.
>
> The (theoretical) problem with using AI_ADDRCONFIG in bind_tcpip_socket()
> is that, in case the p2v server has no publicly routable IPv6 address
> assigned, then bind_tcpip_socket() will not bind ::1 from "localhost". And
> then the IPv6 reverse forwarding attempt, set up by
> open_data_connection(), *might* fail.
>
> Remove AI_ADDRCONFIG anyway. While at it, spell out AF_UNSPEC as well (in
> practice, this makes no difference, as Linux defines AF_UNSPEC as
> PF_UNSPEC as 0).
>
> While running the local test suite ("make -j10 check") on a host without a
> publicly routable IPv6 address, the "netstat -anp" output changes, due to
> this patch. Before:
>
>> Active Internet connections (servers and established)
>> Proto Recv-Q Send-Q Local Address Foreign Address State
PID/Program name
>> tcp 0 0 127.0.0.1:58273 0.0.0.0:* LISTEN
51057/nbdkit
>> tcp 0 0 127.0.0.1:58272 0.0.0.0:* LISTEN
51050/nbdkit
>> tcp 0 0 127.0.0.1:58272 127.0.0.1:35332 ESTABLISHED
51050/nbdkit
>> tcp 0 0 127.0.0.1:35332 127.0.0.1:58272 ESTABLISHED
51204/nbdkit
>
> We have two nbdkit processes (PIDs 51057 and 51050) listening over TCPv4,
> and a third one (PID 51204) connected to PID 51050 over TCPv4.
>
> After:
>
>> Active Internet connections (servers and established)
>> Proto Recv-Q Send-Q Local Address Foreign Address State
PID/Program name
>> tcp 0 0 127.0.0.1:54146 0.0.0.0:* LISTEN
49310/nbdkit
>> tcp 0 0 127.0.0.1:54145 0.0.0.0:* LISTEN
49303/nbdkit
>> tcp6 0 0 ::1:54145 :::* LISTEN
49303/nbdkit
>> tcp6 0 0 ::1:54146 :::* LISTEN
49310/nbdkit
>> tcp6 0 0 ::1:57432 ::1:54145 ESTABLISHED
49457/nbdkit
>> tcp6 0 0 ::1:54145 ::1:57432 ESTABLISHED
49303/nbdkit
>
> The two listening nbdkit processes (PIDs 49310 and 49303) are now doing so
> over both TCPv4 and TCPv6, and the third one (PID 49457) actually connects
> to PID 49303 over TCPv6!
Nice!
Thanks! BTW: do you have any comments about the following serial log
message (see the cover letter):
nbdkit: file[1]: error: reading initial client flags: conn->recv:
Connection reset by peer
I did not check if the same was issued *without* this patch in place; I
highlighted it in the cover letter because it could ring a bell with you
(regardless of AI_ADDRCONFIG / IPv6).
Thanks!
Laszlo
> Ref:
https://listman.redhat.com/archives/libguestfs/2022-March/028475.html
> Suggested-by: Richard W.M. Jones <rjones(a)redhat.com>
> Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
> ---
> nbd.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/nbd.c b/nbd.c
> index dcedd0a52dce..92fad34c0e32 100644
> --- a/nbd.c
> +++ b/nbd.c
> @@ -262,90 +262,91 @@ static int
> bind_tcpip_socket (const char *port, int **fds_rtn, size_t *nr_fds_rtn)
> {
> struct addrinfo *ai = NULL;
> struct addrinfo hints;
> struct addrinfo *a;
> int err;
> int *fds = NULL;
> size_t nr_fds;
> int addr_in_use = 0;
>
> memset (&hints, 0, sizeof hints);
> - hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
> + hints.ai_family = AF_UNSPEC;
> + hints.ai_flags = AI_PASSIVE;
> hints.ai_socktype = SOCK_STREAM;
>
> err = getaddrinfo ("localhost", port, &hints, &ai);
> if (err != 0) {
Reviewed-by: Richard W.M. Jones <rjones(a)redhat.com>
Rich.