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