Index | Thread | Search

From:
Florian Obser <florian@openbsd.org>
Subject:
Re: "family inet[46]" and numeric address for getaddrinfo()
To:
YASUOKA Masahiko <yasuoka@openbsd.org>
Cc:
tech@openbsd.org
Date:
Tue, 16 Sep 2025 13:27:36 +0200

Download raw body.

Thread
Coming back to an old email.

On 2025-03-07 09:43 +09, YASUOKA Masahiko <yasuoka@openbsd.org> wrote:
> 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.

I don't think this is correct behaviour either.

I *think* your diff is correct, but it's complicated, this is easier:

1. if hints.ai_family == AF_UNSPEC, _asr_sockaddr_from_str tries all
(both) AFs in sequence for us.
2. if hints.ai_family != AF_UNSPEC, _asr_sockaddr_from_str validates
that the hostname is a correct address in the specified family.

Therefore, we can just pass in hints.ai_family and it will do the right
thing.

OK?

diff --git lib/libc/asr/getaddrinfo_async.c lib/libc/asr/getaddrinfo_async.c
index 46245831f12..3ab92fc903c 100644
--- lib/libc/asr/getaddrinfo_async.c
+++ lib/libc/asr/getaddrinfo_async.c
@@ -272,17 +272,10 @@ getaddrinfo_async_run(struct asr_query *as, struct asr_result *ar)
 		}
 
 		/* Try numeric addresses first */
-		for (family = iter_family(as, 1);
-		    family != -1;
-		    family = iter_family(as, 0)) {
-
-			if (_asr_sockaddr_from_str(&sa.sa, family,
-			    as->as.ai.hostname) == -1)
-				continue;
-
+		if (_asr_sockaddr_from_str(&sa.sa, ai->ai_family,
+		    as->as.ai.hostname) != -1) {
 			if ((r = addrinfo_add(as, &sa.sa, as->as.ai.hostname)))
 				ar->ar_gai_errno = r;
-			break;
 		}
 		if (ar->ar_gai_errno || as->as_count) {
 			async_set_state(as, ASR_STATE_HALT);


>
> 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;
>  
>

-- 
In my defence, I have been left unsupervised.