Revert "netresolv: Add support for AI_V4MAPPED in ai_flags in getaddrinfo"

This reverts commit 902921a554.

This broke resolution of CNAMEs, including the Haiku package repos.
Since pkgman uses our own HTTP implementation, which doesn't set
AI_V4MAPPED at all, this shouldn't have been a behavioral change for
it at all, much less having broken it.

Change-Id: If38b6a81c1144101ddea7d1f8d401326675479e3
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10388
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
waddlesplash
2026-02-26 20:54:16 +00:00
parent 3214eedc80
commit 8f3276e838
5 changed files with 53 additions and 271 deletions
+3 -3
View File
@@ -83,9 +83,9 @@ const char *hstrerror(int);
#define AI_ADDRCONFIG 0x00000400 #define AI_ADDRCONFIG 0x00000400
#define AI_V4MAPPED 0x00000800 #define AI_V4MAPPED 0x00000800
#define AI_MASK \ #define AI_MASK \
(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG | AI_ALL \ (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG)
| AI_V4MAPPED)
/* getnameinfo */ /* getnameinfo */
#if defined(_DEFAULT_SOURCE) #if defined(_DEFAULT_SOURCE)
-1
View File
@@ -64,7 +64,6 @@ for architectureObject in [ MultiArchSubDirSetup ] {
getservent.c getservent.c
getservent_r.c getservent_r.c
hesiod.c hesiod.c
map_v4v6.c
nsdispatch.c nsdispatch.c
nslexer.l nslexer.l
nsparser.y nsparser.y
+50 -160
View File
@@ -88,10 +88,9 @@ __RCSID("$NetBSD: getaddrinfo.c,v 1.119.2.1 2020/11/29 11:25:31 martin Exp $");
#include <FindDirectory.h> #include <FindDirectory.h>
#include "netdb_private.h" #include <libutil.h>
#include "nsswitch.h" #include "nsswitch.h"
#include "servent.h" #include "servent.h"
#include <libutil.h>
#ifndef RUMP_ACTION #ifndef RUMP_ACTION
#ifdef __weak_alias #ifdef __weak_alias
@@ -137,19 +136,17 @@ static const struct afd {
const char *a_addrany; const char *a_addrany;
const char *a_loopback; const char *a_loopback;
int a_scoped; int a_scoped;
} afdl[] = { } afdl [] = {
#ifdef INET6 #ifdef INET6
#define N_INET6 0 {PF_INET6, sizeof(struct in6_addr),
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), sizeof(struct sockaddr_in6),
offsetof(struct sockaddr_in6, sin6_addr), in6_addrany, in6_loopback, 1}, offsetof(struct sockaddr_in6, sin6_addr),
#define N_INET 1 in6_addrany, in6_loopback, 1},
#define N_LOCAL 2
#else
#define N_INET 0
#define N_LOCAL 1
#endif #endif
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), {PF_INET, sizeof(struct in_addr),
offsetof(struct sockaddr_in, sin_addr), in_addrany, in_loopback, 0}, sizeof(struct sockaddr_in),
offsetof(struct sockaddr_in, sin_addr),
in_addrany, in_loopback, 0},
{0, 0, 0, 0, NULL, NULL, 0}, {0, 0, 0, 0, NULL, NULL, 0},
}; };
@@ -525,24 +522,6 @@ getaddrinfo(const char *hostname, const char *servname,
} }
} }
/*
* RFC 3493: AI_ALL and AI_V4MAPPED are effective only against
* AF_INET6 query. They need to be ignored if specified in other
* occassions.
*/
switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) {
case AI_V4MAPPED:
case AI_ALL | AI_V4MAPPED:
#ifdef INET6
if (pai->ai_family != AF_INET6)
pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
break;
#endif
case AI_ALL:
pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
break;
}
if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && addrconfig(&mask) == -1) if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && addrconfig(&mask) == -1)
ERR(EAI_FAIL); ERR(EAI_FAIL);
@@ -946,17 +925,6 @@ set_source(struct ai_order *aio, struct policyhead *ph,
if ((s = socket(ai.ai_family, ai.ai_socktype | SOCK_CLOEXEC, if ((s = socket(ai.ai_family, ai.ai_socktype | SOCK_CLOEXEC,
ai.ai_protocol)) < 0) ai.ai_protocol)) < 0)
return; /* give up */ return; /* give up */
#ifdef INET6
if (ai.ai_family == AF_INET6) {
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ai.ai_addr;
int off = 0;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
(void)setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off));
}
#endif
#if SOCK_CLOEXEC == 0 #if SOCK_CLOEXEC == 0
fcntl(s, F_SETFD, FD_CLOEXEC); fcntl(s, F_SETFD, FD_CLOEXEC);
#endif #endif
@@ -1340,7 +1308,7 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
struct servent_data *svd) struct servent_data *svd)
{ {
const struct afd *afd; const struct afd *afd;
struct addrinfo *cur, ai0; struct addrinfo *cur;
struct addrinfo sentinel; struct addrinfo sentinel;
int error; int error;
char pton[PTON_MAX]; char pton[PTON_MAX];
@@ -1401,35 +1369,26 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
} }
break; break;
default: default:
if (inet_pton(afd->a_af, hostname, pton) != 1) { if (inet_pton(afd->a_af, hostname, pton) == 1) {
if (pai->ai_family != AF_INET6 || (pai->ai_flags & AI_V4MAPPED) != AI_V4MAPPED) if (pai->ai_family == afd->a_af ||
return 0; pai->ai_family == PF_UNSPEC /*?*/) {
if (inet_aton(hostname, (struct in_addr*)pton) != 1) GET_AI(cur->ai_next, afd, pton);
return 0; GET_PORT(cur->ai_next, servname, svd);
afd = &afdl[N_INET]; if ((pai->ai_flags & AI_CANONNAME)) {
ai0 = *pai; /*
ai0.ai_family = AF_INET; * Set the numeric address itself as
pai = &ai0; * the canonical name, based on a
* clarification in rfc2553bis-03.
*/
GET_CANONNAME(cur->ai_next, canonname);
}
while (cur->ai_next)
cur = cur->ai_next;
} else
ERR(EAI_FAMILY); /*xxx*/
} }
break; break;
} }
if (pai->ai_family == afd->a_af || pai->ai_family == PF_UNSPEC /*?*/) {
GET_AI(cur->ai_next, afd, pton);
GET_PORT(cur->ai_next, servname, svd);
if (pai->ai_flags & AI_CANONNAME) {
/*
* Set the numeric address itself as
* the canonical name, based on a
* clarification in rfc2553bis-03.
*/
GET_CANONNAME(cur->ai_next, canonname);
}
while (cur->ai_next)
cur = cur->ai_next;
} else {
ERR(EAI_FAMILY); /*xxx*/
}
*res = sentinel.ai_next; *res = sentinel.ai_next;
return 0; return 0;
@@ -1544,7 +1503,6 @@ allocaddrinfo(socklen_t addrlen)
return ai; return ai;
} }
static struct addrinfo * static struct addrinfo *
get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
{ {
@@ -1552,22 +1510,10 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
struct addrinfo *ai; struct addrinfo *ai;
struct sockaddr *save; struct sockaddr *save;
#ifdef INET6
struct in6_addr mapaddr;
#endif
_DIAGASSERT(pai != NULL); _DIAGASSERT(pai != NULL);
_DIAGASSERT(afd != NULL); _DIAGASSERT(afd != NULL);
_DIAGASSERT(addr != NULL); _DIAGASSERT(addr != NULL);
#ifdef INET6
if (afd->a_af == AF_INET && (pai->ai_flags & AI_V4MAPPED) != 0) {
afd = &afdl[N_INET6];
_map_v4v6_address(addr, (char*)&mapaddr);
addr = (char*)&mapaddr;
}
#endif
ai = allocaddrinfo((socklen_t)afd->a_socklen); ai = allocaddrinfo((socklen_t)afd->a_socklen);
if (ai == NULL) if (ai == NULL)
return NULL; return NULL;
@@ -2151,13 +2097,10 @@ _dns_query(struct res_target *q, const struct addrinfo *pai,
cur = cur->ai_next; cur = cur->ai_next;
} }
if (q2) { if (q2) {
if (!ai || pai->ai_family != AF_UNSPEC ai = getanswer(res, buf2, q2->n, q2->name, q2->qtype, pai);
|| (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) != AI_V4MAPPED) { if (ai)
ai = getanswer(res, buf2, q2->n, q2->name, q2->qtype, pai); cur->ai_next = ai;
if (ai) }
cur->ai_next = ai;
}
}
free(buf); free(buf);
free(buf2); free(buf2);
return sentinel.ai_next; return sentinel.ai_next;
@@ -2302,7 +2245,7 @@ _dns_host_lookup(const char *name, const struct addrinfo *pai)
static int static int
_dns_getaddrinfo(void *rv, void *cb_data, va_list ap) _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
{ {
struct addrinfo ai0, *ai = NULL; struct addrinfo *ai = NULL;
const char *name, *servname; const char *name, *servname;
const struct addrinfo *pai; const struct addrinfo *pai;
@@ -2310,12 +2253,6 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
pai = va_arg(ap, const struct addrinfo *); pai = va_arg(ap, const struct addrinfo *);
servname = va_arg(ap, char *); servname = va_arg(ap, char *);
if (pai->ai_family == AF_INET6 && (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) {
ai0 = *pai;
ai0.ai_family = AF_UNSPEC;
pai = &ai0;
}
/* /*
* Try doing SRV lookup on service first. * Try doing SRV lookup on service first.
*/ */
@@ -2433,10 +2370,6 @@ _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
found: found:
hints = *pai; hints = *pai;
hints.ai_flags = AI_NUMERICHOST; hints.ai_flags = AI_NUMERICHOST;
if (pai->ai_family == AF_INET6 && (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED)
hints.ai_flags |= AI_V4MAPPED;
error = getaddrinfo(addr, NULL, &hints, &res0); error = getaddrinfo(addr, NULL, &hints, &res0);
if (error) if (error)
goto again; goto again;
@@ -2454,20 +2387,6 @@ found:
return res0; return res0;
} }
static struct addrinfo*
_getht(FILE** hostf, const char* name, const struct addrinfo* pai, struct addrinfo* cur)
{
struct addrinfo* p;
while ((p = _gethtent(hostf, name, pai)) != NULL) {
cur->ai_next = p;
while (cur && cur->ai_next)
cur = cur->ai_next;
}
return cur;
}
/*ARGSUSED*/ /*ARGSUSED*/
static int static int
_files_getaddrinfo(void *rv, void *cb_data, va_list ap) _files_getaddrinfo(void *rv, void *cb_data, va_list ap)
@@ -2475,6 +2394,7 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap)
const char *name; const char *name;
const struct addrinfo *pai; const struct addrinfo *pai;
struct addrinfo sentinel, *cur; struct addrinfo sentinel, *cur;
struct addrinfo *p;
#ifndef _REENTRANT #ifndef _REENTRANT
static static
#endif #endif
@@ -2487,18 +2407,10 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap)
cur = &sentinel; cur = &sentinel;
_sethtent(&hostf); _sethtent(&hostf);
if (pai->ai_family == AF_INET6 && (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) == AI_V4MAPPED) { while ((p = _gethtent(&hostf, name, pai)) != NULL) {
struct addrinfo ai0 = *pai; cur->ai_next = p;
while (cur && cur->ai_next)
ai0.ai_flags &= ~AI_V4MAPPED; cur = cur->ai_next;
cur = _getht(&hostf, name, &ai0, cur);
if (sentinel.ai_next == NULL) {
_sethtent(&hostf);
ai0.ai_flags |= AI_V4MAPPED;
cur = _getht(&hostf, name, &ai0, cur);
}
} else {
cur = _getht(&hostf, name, pai, cur);
} }
_endhtent(&hostf); _endhtent(&hostf);
@@ -2563,8 +2475,6 @@ nextline:
hints = *pai; hints = *pai;
hints.ai_flags = AI_NUMERICHOST; hints.ai_flags = AI_NUMERICHOST;
if (pai->ai_family == AF_INET6 && (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED)
hints.ai_flags |= AI_V4MAPPED;
error = getaddrinfo(addr, NULL, &hints, &res0); error = getaddrinfo(addr, NULL, &hints, &res0);
if (error == 0) { if (error == 0) {
for (res = res0; res; res = res->ai_next) { for (res = res0; res; res = res->ai_next) {
@@ -2612,44 +2522,15 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
memset(&sentinel, 0, sizeof(sentinel)); memset(&sentinel, 0, sizeof(sentinel));
cur = &sentinel; cur = &sentinel;
/* ipnodes.byname can hold both IPv4/v6 */
r = yp_match(ypdomain, "ipnodes.byname", name, (int)strlen(name), &ypbuf, &ypbuflen);
if (r == 0) {
ai = _yphostent(ypbuf, pai);
if (ai) {
cur->ai_next = ai;
while (cur && cur->ai_next)
cur = cur->ai_next;
}
free(ypbuf);
}
if (ai != NULL) {
struct sockaddr_in6* sin6;
switch (ai->ai_family) {
case AF_INET:
goto done;
case AF_INET6:
sin6 = (struct sockaddr_in6*)ai->ai_addr;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
goto done;
break;
}
}
/* hosts.byname is only for IPv4 (Solaris8) */ /* hosts.byname is only for IPv4 (Solaris8) */
if (pai->ai_family == AF_UNSPEC || pai->ai_family == AF_INET if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
|| ((pai->ai_family == AF_INET6 && (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED)
&& (ai == NULL || (pai->ai_flags & AI_ALL) == AI_ALL))) {
r = yp_match(ypdomain, "hosts.byname", name, r = yp_match(ypdomain, "hosts.byname", name,
(int)strlen(name), &ypbuf, &ypbuflen); (int)strlen(name), &ypbuf, &ypbuflen);
if (r == 0) { if (r == 0) {
struct addrinfo ai4; struct addrinfo ai4;
ai4 = *pai; ai4 = *pai;
if (pai->ai_family == AF_UNSPEC) ai4.ai_family = AF_INET;
ai4.ai_family = AF_INET;
ai = _yphostent(ypbuf, &ai4); ai = _yphostent(ypbuf, &ai4);
if (ai) { if (ai) {
cur->ai_next = ai; cur->ai_next = ai;
@@ -2660,7 +2541,16 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
free(ypbuf); free(ypbuf);
} }
done: /* ipnodes.byname can hold both IPv4/v6 */
r = yp_match(ypdomain, "ipnodes.byname", name,
(int)strlen(name), &ypbuf, &ypbuflen);
if (r == 0) {
ai = _yphostent(ypbuf, pai);
if (ai)
cur->ai_next = ai;
free(ypbuf);
}
if (sentinel.ai_next == NULL) { if (sentinel.ai_next == NULL) {
h_errno = HOST_NOT_FOUND; h_errno = HOST_NOT_FOUND;
return NS_NOTFOUND; return NS_NOTFOUND;
@@ -1,80 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* ++Copyright++ 1985, 1988, 1993
* -
* Copyright (c) 1985, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/socket.h>
#include "netdb_private.h"
#include <netdb.h>
#include <resolv.h>
#include <string.h>
#include <syslog.h>
typedef union {
int32_t al;
char ac;
} align;
void
_map_v4v6_address(const char* src, char* dst)
{
/* Our caller may update in place. */
memmove(&dst[12], src, NS_INADDRSZ);
/* Mark this ipv6 addr as a mapped ipv4. */
memset(&dst[10], 0xff, 2);
memset(&dst[0], 0, 10);
}
@@ -1,27 +0,0 @@
/*-
* Copyright (C) 2005 The FreeBSD Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
void _map_v4v6_address(const char*, char*);