Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libc/net to honor the search order defined by nsswitch.c...
details: https://anonhg.NetBSD.org/src/rev/be9437426b13
branches: trunk
changeset: 482733:be9437426b13
user: itojun <itojun%NetBSD.org@localhost>
date: Sun Feb 20 14:44:30 2000 +0000
description:
to honor the search order defined by nsswitch.conf,
getaddrinfo(3) now calls lower-layer resolver functions directly.
XXX code duplicate with gethnamaddr.c/res_search.c - future code
maintenance issue? Since BIND[89] does not address this issue either at
this moment, switching to BIND[89] does not help.
diffstat:
lib/libc/net/getaddrinfo.c | 1099 ++++++++++++++++++++++++++++++++++++++-----
1 files changed, 954 insertions(+), 145 deletions(-)
diffs (truncated from 1198 to 300 lines):
diff -r a493b65ab828 -r be9437426b13 lib/libc/net/getaddrinfo.c
--- a/lib/libc/net/getaddrinfo.c Sun Feb 20 14:39:28 2000 +0000
+++ b/lib/libc/net/getaddrinfo.c Sun Feb 20 14:44:30 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: getaddrinfo.c,v 1.31 2000/02/17 17:06:17 itojun Exp $ */
+/* $NetBSD: getaddrinfo.c,v 1.32 2000/02/20 14:44:30 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -54,21 +54,26 @@
* (1) what should we do against numeric hostname (2) what should we do
* against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
* non-loopback address configured? global address configured?
- * - The code makes use of following calls when asked to resolver with
- * ai_family = PF_UNSPEC:
- * getipnodebyname(host, AF_INET6);
- * getipnodebyname(host, AF_INET);
- * This will result in the following queries if the node is configure to
- * prefer /etc/hosts than DNS:
- * lookup /etc/hosts for IPv6 address
- * lookup DNS for IPv6 address
- * lookup /etc/hosts for IPv4 address
- * lookup DNS for IPv4 address
- * which may not meet people's requirement.
- * The right thing to happen is to have underlying layer which does
- * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
- * This would result in a bit of code duplicate with _dns_ghbyname() and
- * friends.
+ * - To avoid search order issue, we have a big amount of code duplicate
+ * from gethnamaddr.c and some other places. The issues that there's no
+ * lower layer function to lookup "IPv4 or IPv6" record. Calling
+ * gethostbyname2 from getaddrinfo will end up in wrong search order, as
+ * follows:
+ * - The code makes use of following calls when asked to resolver with
+ * ai_family = PF_UNSPEC:
+ * getipnodebyname(host, AF_INET6);
+ * getipnodebyname(host, AF_INET);
+ * This will result in the following queries if the node is configure to
+ * prefer /etc/hosts than DNS:
+ * lookup /etc/hosts for IPv6 address
+ * lookup DNS for IPv6 address
+ * lookup /etc/hosts for IPv4 address
+ * lookup DNS for IPv4 address
+ * which may not meet people's requirement.
+ * The right thing to happen is to have underlying layer which does
+ * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
+ * This would result in a bit of code duplicate with _dns_ghbyname() and
+ * friends.
*/
#include <sys/types.h>
@@ -88,6 +93,16 @@
#include <stdio.h>
#include <errno.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
#define SUCCESS 0
#define ANY 0
#define YES 1
@@ -154,6 +169,9 @@
{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
+ { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+ { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
{ -1, 0, 0, NULL, 0 },
};
@@ -163,6 +181,31 @@
#define PTON_MAX 4
#endif
+static const ns_src default_dns_files[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NSSRC_DNS, NS_SUCCESS },
+ { 0 }
+};
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+struct res_target {
+ struct res_target *next;
+ const char *name; /* domain name */
+ int class, type; /* class and type of query */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer buffer */
+ int n; /* result length */
+};
static int str_isnumber __P((const char *));
static int explore_fqdn __P((const struct addrinfo *, const char *,
@@ -185,6 +228,23 @@
static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *));
#endif
+static struct addrinfo *getanswer __P((const querybuf *, int, const char *, int,
+ const struct addrinfo *));
+static int _dns_getaddrinfo __P((void *, void *, va_list));
+static void _sethtent __P((void));
+static void _endhtent __P((void));
+static struct addrinfo *_gethtent __P((const char *, const struct addrinfo *));
+static int _files_getaddrinfo __P((void *, void *, va_list));
+#ifdef YP
+static struct addrinfo *_yphostent __P((char *, const struct addrinfo *));
+static int _yp_getaddrinfo __P((void *, void *, va_list));
+#endif
+
+static int res_queryN __P((const char *, struct res_target *));
+static int res_searchN __P((const char *, struct res_target *));
+static int res_querydomainN __P((const char *, const char *,
+ struct res_target *));
+
static char *ai_errlist[] = {
"Success",
"Address family for hostname not supported", /* EAI_ADDRFAMILY */
@@ -293,10 +353,9 @@
struct addrinfo ai;
struct addrinfo ai0;
struct addrinfo *pai;
- const struct afd *afd;
const struct explore *ex;
- sentinel.ai_next = NULL;
+ memset(&sentinel, 0, sizeof(sentinel));
cur = &sentinel;
pai = &ai;
pai->ai_flags = 0;
@@ -381,6 +440,10 @@
for (ex = explore; ex->e_af >= 0; ex++) {
*pai = ai0;
+ /* PF_UNSPEC entries are prepared for DNS queries only */
+ if (ex->e_af == PF_UNSPEC)
+ continue;
+
if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
continue;
if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
@@ -425,42 +488,32 @@
* we would like to prefer AF_INET6 than AF_INET, so we'll make a
* outer loop by AFs.
*/
- for (afd = afdl; afd->a_af; afd++) {
+ for (ex = explore; ex->e_af >= 0; ex++) {
*pai = ai0;
- if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
+ /* require exact match for family field */
+ if (pai->ai_family != ex->e_af)
continue;
- for (ex = explore; ex->e_af >= 0; ex++) {
- *pai = ai0;
-
- if (pai->ai_family == PF_UNSPEC)
- pai->ai_family = afd->a_af;
+ if (!MATCH(pai->ai_socktype, ex->e_socktype,
+ WILD_SOCKTYPE(ex))) {
+ continue;
+ }
+ if (!MATCH(pai->ai_protocol, ex->e_protocol,
+ WILD_PROTOCOL(ex))) {
+ continue;
+ }
- if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
- continue;
- if (!MATCH(pai->ai_socktype, ex->e_socktype,
- WILD_SOCKTYPE(ex))) {
- continue;
- }
- if (!MATCH(pai->ai_protocol, ex->e_protocol,
- WILD_PROTOCOL(ex))) {
- continue;
- }
+ if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+ pai->ai_socktype = ex->e_socktype;
+ if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+ pai->ai_protocol = ex->e_protocol;
- if (pai->ai_family == PF_UNSPEC)
- pai->ai_family = ex->e_af;
- if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
- pai->ai_socktype = ex->e_socktype;
- if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
- pai->ai_protocol = ex->e_protocol;
+ error = explore_fqdn(pai, hostname, servname,
+ &cur->ai_next);
- error = explore_fqdn(pai, hostname, servname,
- &cur->ai_next);
-
- while (cur && cur->ai_next)
- cur = cur->ai_next;
- }
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
}
/* XXX */
@@ -495,20 +548,17 @@
const char *servname;
struct addrinfo **res;
{
- struct hostent *hp;
- int h_error;
- int af;
- char **aplist = NULL, *apbuf = NULL;
- char *ap;
- struct addrinfo sentinel, *cur;
- int i;
- int naddrs;
- const struct afd *afd;
+ struct addrinfo *result;
+ struct addrinfo *cur;
int error = 0;
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_files_getaddrinfo, NULL)
+ { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
+ NS_NIS_CB(_yp_getaddrinfo, NULL)
+ { 0 }
+ };
- *res = NULL;
- sentinel.ai_next = NULL;
- cur = &sentinel;
+ result = NULL;
/*
* If AI_ADDRCONFIG is specified, check if we are expected to
@@ -523,99 +573,31 @@
if (get_portmatch(pai, servname) != 0)
return 0;
- afd = find_afd(pai->ai_family);
-
- hp = gethostbyname2(hostname, pai->ai_family);
- h_error = h_errno;
-
- if (hp == NULL) {
- switch (h_error) {
- case HOST_NOT_FOUND:
- case NO_DATA:
- error = EAI_NODATA;
- break;
- case TRY_AGAIN:
- error = EAI_AGAIN;
- break;
- case NO_RECOVERY:
- case NETDB_INTERNAL:
- default:
- error = EAI_FAIL;
- break;
+ switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
+ default_dns_files, hostname, pai)) {
+ case NS_TRYAGAIN:
+ error = EAI_AGAIN;
+ goto free;
+ case NS_UNAVAIL:
+ error = EAI_FAIL;
+ goto free;
+ case NS_NOTFOUND:
+ error = EAI_NODATA;
+ goto free;
+ case NS_SUCCESS:
+ error = 0;
+ for (cur = result; cur; cur = cur->ai_next) {
+ GET_PORT(cur, servname);
+ /* canonname should be filled already */
}
- } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
- || (hp->h_addr_list[0] == NULL)) {
- hp = NULL;
- error = EAI_FAIL;
+ break;
}
- if (hp == NULL)
- goto free;
-
- /*
Home |
Main Index |
Thread Index |
Old Index