Index | Thread | Search

From:
YASUOKA Masahiko <yasuoka@openbsd.org>
Subject:
Re: "family inet[46]" and numeric address for getaddrinfo()
To:
florian@openbsd.org
Cc:
tech@openbsd.org
Date:
Wed, 17 Sep 2025 12:00:09 +0900

Download raw body.

Thread
Hello,

On Tue, 16 Sep 2025 13:27:36 +0200
Florian Obser <florian@openbsd.org> wrote:
> 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.

You are correct.  I missed the behaviour of _asr_sockaddr_from_str.

> OK?

ok yasuoka

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