-/* $OpenBSD: asr_private.h,v 1.48 2022/11/17 17:39:41 florian Exp $ */
+/* $OpenBSD: asr_private.h,v 1.49 2023/11/20 12:15:16 florian Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
ssize_t _asr_dname_from_fqdn(const char *, char *, size_t);
ssize_t _asr_addr_as_fqdn(const char *, int, char *, size_t);
int hnok_lenient(const char *);
+int _asr_is_localhost(const char*);
/* asr.c */
void _asr_resolver_done(void *);
-/* $OpenBSD: asr_utils.c,v 1.21 2023/03/15 22:12:00 millert Exp $ */
+/* $OpenBSD: asr_utils.c,v 1.22 2023/11/20 12:15:16 florian Exp $ */
/*
* Copyright (c) 2009-2012 Eric Faurot <eric@faurot.net>
*
}
return 1;
}
+
+/* Check if the hostname is localhost or if it's in the localhost domain */
+int
+_asr_is_localhost(const char *hn)
+{
+ size_t hnlen, localhostlen;
+
+ if (hn == NULL)
+ return 0;
+
+ if (strcasecmp(hn, "localhost") == 0 ||
+ strcasecmp(hn, "localhost.") == 0)
+ return 1;
+
+ hnlen = strlen(hn);
+ localhostlen = strlen(".localhost");
+
+ if (hnlen < localhostlen)
+ return 0;
+
+ if (strcasecmp(hn + hnlen - localhostlen, ".localhost") == 0)
+ return 1;
+
+ localhostlen++;
+ if (hnlen < localhostlen)
+ return 0;
+
+ if (strcasecmp(hn + hnlen - localhostlen, ".localhost.") == 0)
+ return 1;
+
+ return 0;
+}
-/* $OpenBSD: getaddrinfo_async.c,v 1.59 2022/12/27 17:10:06 jmc Exp $ */
+/* $OpenBSD: getaddrinfo_async.c,v 1.60 2023/11/20 12:15:16 florian Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
char fqdn[MAXDNAME];
const char *str;
struct addrinfo *ai;
- int i, family, r;
+ int i, family, r, is_localhost;
FILE *f;
union {
struct sockaddr sa;
ar->ar_gai_errno = 0;
- /* If hostname is NULL, use local address */
- if (as->as.ai.hostname == NULL) {
+ is_localhost = _asr_is_localhost(as->as.ai.hostname);
+ /*
+ * If hostname is NULL, "localhost" or falls within the
+ * ".localhost." domain, use local address.
+ * RFC 6761, 6.3:
+ * 3. Name resolution APIs and libraries SHOULD recognize
+ * localhost names as special and SHOULD always return the IP
+ * loopback address for address queries and negative responses
+ * for all other query types. Name resolution APIs SHOULD NOT
+ * send queries for localhost names to their configured caching
+ * DNS server(s).
+ */
+ if (as->as.ai.hostname == NULL || is_localhost) {
for (family = iter_family(as, 1);
family != -1;
family = iter_family(as, 0)) {
* those, rather than parsing over and over.
*/
if (family == PF_INET)
- str = (ai->ai_flags & AI_PASSIVE) ? \
- "0.0.0.0" : "127.0.0.1";
+ str = (ai->ai_flags & AI_PASSIVE &&
+ !is_localhost) ? "0.0.0.0" :
+ "127.0.0.1";
else /* PF_INET6 */
- str = (ai->ai_flags & AI_PASSIVE) ? \
- "::" : "::1";
+ str = (ai->ai_flags & AI_PASSIVE &&
+ !is_localhost) ? "::" : "::1";
/* This can't fail */
_asr_sockaddr_from_str(&sa.sa, family, str);
if ((r = addrinfo_add(as, &sa.sa, NULL))) {
-/* $OpenBSD: gethostnamadr_async.c,v 1.47 2023/11/14 08:27:33 florian Exp $ */
+/* $OpenBSD: gethostnamadr_async.c,v 1.48 2023/11/20 12:15:16 florian Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
async_set_state(as, ASR_STATE_HALT);
break;
}
+
+ /*
+ * If hostname is "localhost" or falls within the
+ * ".localhost." domain, use local address.
+ * RFC 6761, 6.3:
+ * 3. Name resolution APIs and libraries SHOULD
+ * recognize localhost names as special and SHOULD
+ * always return the IP loopback address for address
+ * queries and negative responses for all other query
+ * types. Name resolution APIs SHOULD NOT send queries
+ * for localhost names to their configured caching DNS
+ * server(s).
+ */
+
+ if (_asr_is_localhost(as->as.hostnamadr.name)) {
+ inet_pton(as->as.hostnamadr.family,
+ as->as.hostnamadr.family == AF_INET ?
+ "127.0.0.1" : "::1", addr);
+ h = hostent_from_addr(as->as.hostnamadr.family,
+ as->as.hostnamadr.name, addr);
+ if (h == NULL) {
+ ar->ar_errno = errno;
+ ar->ar_h_errno = NETDB_INTERNAL;
+ }
+ else {
+ ar->ar_hostent = &h->h;
+ ar->ar_h_errno = NETDB_SUCCESS;
+ }
+ async_set_state(as, ASR_STATE_HALT);
+ break;
+ }
}
async_set_state(as, ASR_STATE_NEXT_DB);
break;