Index | Thread | Search

From:
YASUOKA Masahiko <yasuoka@openbsd.org>
Subject:
"family inet[46]" and numeric address for getaddrinfo()
To:
tech@openbsd.org
Date:
Fri, 07 Mar 2025 09:43:57 +0900

Download raw body.

Thread
Hello,

sshd's config has the following default values,

  #AddressFamily any
  #ListenAddress 0.0.0.0
  #ListenAddress ::

If we configure "family" in /etc/resolv.conf, sshd will stop listening
0.0.0.0 or :: following the "family" config.

  - "family inet4" => stop listening on ::
  - "family inet6" => stop listening on 0.0.0.0

This is because getaddrinfo() doesn't convert a numeric address if the
family is disabled and NI_NUMERIC_HOST is not specified.

I don't think this is correct behavior.

When a numeric address is given, I suppose it's expected that the
numeric address can be converted into an address object without a name
resolution.  (it's resolved from the beginning) Therefore any config
in resolv.conf should not effect the result.

I checked that our previous resolver (on 5.2, before asr) behaves as I
expected.

ok?


Index: lib/libc/asr/getaddrinfo_async.c
===================================================================
RCS file: /cvs/src/lib/libc/asr/getaddrinfo_async.c,v
diff -u -p -r1.63 getaddrinfo_async.c
--- lib/libc/asr/getaddrinfo_async.c	21 Aug 2024 05:53:10 -0000	1.63
+++ lib/libc/asr/getaddrinfo_async.c	7 Mar 2025 00:15:42 -0000
@@ -58,6 +58,8 @@ static const struct match matches[] = {
 	{ -1,		0,		0,		},
 };
 
+static const int families[] = { PF_INET, PF_INET6, -1 };
+
 #define MATCH_FAMILY(a, b) ((a) == matches[(b)].family || (a) == PF_UNSPEC)
 #define MATCH_PROTO(a, b) ((a) == matches[(b)].protocol || (a) == 0 || matches[(b)].protocol == 0)
 /* Do not match SOCK_RAW unless explicitly specified */
@@ -272,11 +274,12 @@ getaddrinfo_async_run(struct asr_query *
 		}
 
 		/* Try numeric addresses first */
-		for (family = iter_family(as, 1);
-		    family != -1;
-		    family = iter_family(as, 0)) {
+		for (i = 0; families[i] != -1; i++) {
 
-			if (_asr_sockaddr_from_str(&sa.sa, family,
+			if (as->as.ai.hints.ai_family != PF_UNSPEC &&
+			    as->as.ai.hints.ai_family != families[i])
+				continue;
+			if (_asr_sockaddr_from_str(&sa.sa, families[i],
 			    as->as.ai.hostname) == -1)
 				continue;