From nobody Wed Nov 24 02:53:45 2021 X-Original-To: freebsd-net@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id A2E6618ACF94 for ; Wed, 24 Nov 2021 02:53:53 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from kib.kiev.ua (kib.kiev.ua [IPv6:2001:470:d5e7:1::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4HzQZ92bwLz4q1c for ; Wed, 24 Nov 2021 02:53:53 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from tom.home (kib@localhost [127.0.0.1]) by kib.kiev.ua (8.16.1/8.16.1) with ESMTPS id 1AO2rj8w057267 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Wed, 24 Nov 2021 04:53:48 +0200 (EET) (envelope-from kostikbel@gmail.com) DKIM-Filter: OpenDKIM Filter v2.10.3 kib.kiev.ua 1AO2rj8w057267 Received: (from kostik@localhost) by tom.home (8.16.1/8.16.1/Submit) id 1AO2rjh3057266; Wed, 24 Nov 2021 04:53:45 +0200 (EET) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: tom.home: kostik set sender to kostikbel@gmail.com using -f Date: Wed, 24 Nov 2021 04:53:45 +0200 From: Konstantin Belousov To: jschauma@netmeister.org Cc: freebsd-net@freebsd.org Subject: Re: bind() to ::1 fails with EADDRNOTAVAIL / clang vs gcc Message-ID: References: <20211124020839.GZ11277@netmeister.org> List-Id: Networking and TCP/IP with FreeBSD List-Archive: https://lists.freebsd.org/archives/freebsd-net List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-freebsd-net@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20211124020839.GZ11277@netmeister.org> X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,BAYES_00, DKIM_ADSP_CUSTOM_MED,FORGED_GMAIL_RCVD,FREEMAIL_FROM, NML_ADSP_CUSTOM_MED autolearn=no autolearn_force=no version=3.4.5 X-Spam-Checker-Version: SpamAssassin 3.4.5 (2021-03-20) on tom.home X-Rspamd-Queue-Id: 4HzQZ92bwLz4q1c X-Spamd-Bar: ---- Authentication-Results: mx1.freebsd.org; none X-Spamd-Result: default: False [-4.00 / 15.00]; REPLY(-4.00)[] X-ThisMailContainsUnwantedMimeParts: N On Tue, Nov 23, 2021 at 09:08:39PM -0500, Jan Schaumann via freebsd-net wrote: > Hello, > > I'm observing the following strange behavior, where > trying to bind(2) a socket on "::1" fails with > EADDRNOTAVAIL, but binding in6addr_any will succeed > (and then yield a bound ::1). What's more, the > behavior is inconsistent depending on the compiler > used. > > Here's my sample program a.c: > > ---- > #include > #include > > #include > > #include > #include > > #define PORT 12345 > > int > main(int argc, char **argv) { > int sock; > socklen_t a, b; > struct sockaddr_storage server; > struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&server; > > if ((sock = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { > err(EXIT_FAILURE, "socket"); > /* NOTREACHED */ > } > > if (inet_pton(PF_INET6, "::1", &(sin->sin6_addr)) != 1) { > err(EXIT_FAILURE, "inet_pton"); > /* NOTREACHED */ > } > > sin->sin6_family = PF_INET6; > sin->sin6_port = htons(PORT); > > if (bind(sock, (struct sockaddr *)sin, sizeof(*sin)) != 0) { > err(EXIT_FAILURE, "bind"); > /* NOTREACHED */ > } > > return 0; > } > ---- > > This program succeeds in binding and returns 0, as > expected. However, note the declaration of the unused > socklen_t a and b. If I remove that declaration, the > call to bind(2) will fail: > > $ diff -bu [ab].c > --- a.c 2021-11-23 19:49:05.926884000 +0000 > +++ b.c 2021-11-23 19:48:51.409173000 +0000 > @@ -11,7 +11,6 @@ > int > main(int argc, char **argv) { > int sock; > - socklen_t a, b; > struct sockaddr_storage server; > struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&server; > > $ ./a.out > $ echo $? > 0 > $ cc b.c > $ ./a.out > a.out: bind: Can't assign requested address > $ > > This is on FreeBSD 13.0-RELEASE with FreeBSD clang > version 11.0.1. > > Compiling either with gcc version 10.3.0 fails. > > > So my questions are: > > - Why does _any_ of those fail? > - Why does a.c succeed when compiled with clang, but > b.c does not? Most likely because you did not fully initialized *sin. struct sockaddr_in6 is more complex than just address/port/family. There is also at least scope_id, and something called flow_id. You did not initialized these fields. By adding unused stack variables, you changed the place on stack where sockaddr_in6 structure was laid out, systematically chaning assigned values to these fields. Really it is UB, try to memset(sin, 0, sizeof(*sin)).