diff options
-rw-r--r-- | lib/libc/net/name6.c | 348 |
1 files changed, 47 insertions, 301 deletions
diff --git a/lib/libc/net/name6.c b/lib/libc/net/name6.c index 9d2ceb1..fb3e988 100644 --- a/lib/libc/net/name6.c +++ b/lib/libc/net/name6.c @@ -310,6 +310,8 @@ _ghbyname(const char *name, int af, int flags, int *errp) if (flags & AI_ADDRCONFIG) { int s; + if ((s = _socket(af, SOCK_DGRAM, 0)) < 0) + return NULL; /* * TODO: * Note that implementation dependent test for address @@ -317,23 +319,7 @@ _ghbyname(const char *name, int af, int flags, int *errp) * (or apropriate interval), * because addresses will be dynamically assigned or deleted. */ - if (af == AF_UNSPEC) { - if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0) - af = AF_INET; - else { - _close(s); - if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0) - af = AF_INET6; - else - _close(s); - } - - } - if (af != AF_UNSPEC) { - if ((s = _socket(af, SOCK_DGRAM, 0)) < 0) - return NULL; - _close(s); - } + _close(s); } rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyname", default_src, @@ -341,19 +327,16 @@ _ghbyname(const char *name, int af, int flags, int *errp) return (rval == NS_SUCCESS) ? hp : NULL; } -/* getipnodebyname() internal routine for multiple query(PF_UNSPEC) support. */ -static struct hostent * -_getipnodebyname_multi(const char *name, int af, int flags, int *errp) +struct hostent * +getipnodebyname(const char *name, int af, int flags, int *errp) { struct hostent *hp; union inx_addr addrbuf; - /* XXX: PF_UNSPEC is only supposed to be passed from getaddrinfo() */ if (af != AF_INET #ifdef INET6 && af != AF_INET6 #endif - && af != PF_UNSPEC ) { *errp = NO_RECOVERY; @@ -405,21 +388,6 @@ _getipnodebyname_multi(const char *name, int af, int flags, int *errp) } struct hostent * -getipnodebyname(const char *name, int af, int flags, int *errp) -{ - if (af != AF_INET -#ifdef INET6 - && af != AF_INET6 -#endif - ) - { - *errp = NO_RECOVERY; - return NULL; - } - return(_getipnodebyname_multi(name, af ,flags, errp)); -} - -struct hostent * getipnodebyaddr(const void *src, size_t len, int af, int *errp) { struct hostent *hp; @@ -1320,7 +1288,6 @@ _files_ghbyname(void *rval, void *cb_data, va_list ap) char *aliases[MAXALIASES + 1], *addrs[2]; union inx_addr addrbuf; char buf[BUFSIZ]; - int af0; name = va_arg(ap, const char *); af = va_arg(ap, int); @@ -1332,7 +1299,6 @@ _files_ghbyname(void *rval, void *cb_data, va_list ap) return NS_UNAVAIL; rethp = hp = NULL; - af0 = af; while (fgets(buf, sizeof(buf), fp)) { line = buf; if ((addrstr = _hgetword(&line)) == NULL @@ -1348,14 +1314,13 @@ _files_ghbyname(void *rval, void *cb_data, va_list ap) } if (!match) continue; - switch (af0) { + switch (af) { case AF_INET: if (inet_aton(addrstr, (struct in_addr *)&addrbuf) != 1) { *errp = NO_DATA; /* name found */ continue; } - af = af0; break; #ifdef INET6 case AF_INET6: @@ -1363,24 +1328,8 @@ _files_ghbyname(void *rval, void *cb_data, va_list ap) *errp = NO_DATA; /* name found */ continue; } - af = af0; break; #endif - case AF_UNSPEC: - if (inet_aton(addrstr, (struct in_addr *)&addrbuf) - == 1) { - af = AF_INET; - break; - } -#ifdef INET6 - if (inet_pton(AF_INET6, addrstr, &addrbuf) == 1) { - af = AF_INET6; - break; - } -#endif - *errp = NO_DATA; /* name found */ - continue; - /* NOTREACHED */ } hp = &hpbuf; hp->h_name = cname; @@ -1472,9 +1421,7 @@ _nis_ghbyname(void *rval, void *cb_data, va_list ap) name = va_arg(ap, const char *); af = va_arg(ap, int); errp = va_arg(ap, int *); - - if (af == AF_UNSPEC) - af = AF_INET; + if (af == AF_INET) { THREAD_LOCK(); hp = _gethostbynisname(name, af); @@ -1513,11 +1460,6 @@ _nis_ghbyaddr(void *rval, void *cb_data, va_list ap) } #endif -struct __res_type_list { - SLIST_ENTRY(__res_type_list) rtl_entry; - int rtl_type; -}; - #define MAXPACKET (64*1024) typedef union { @@ -1801,259 +1743,63 @@ getanswer(answer, anslen, qname, qtype, template, errp) #undef DNS_FATAL } -/* res_search() variant with multiple query support. */ -static struct hostent * -_res_search_multi(name, rtl, errp) - const char *name; /* domain name */ - struct __res_type_list *rtl; /* list of query types */ - int *errp; -{ - const char *cp, * const *domain; - struct hostent *hp0 = NULL, *hp; - struct hostent hpbuf; - u_int dots; - int trailing_dot, ret, saved_herrno; - int got_nodata = 0, got_servfail = 0, tried_as_is = 0; - struct __res_type_list *rtl0 = rtl; - querybuf *buf; - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - *errp = NETDB_INTERNAL; - return (NULL); - } - dots = 0; - for (cp = name; *cp; cp++) - dots += (*cp == '.'); - trailing_dot = 0; - if (cp > name && *--cp == '.') - trailing_dot++; - - buf = malloc(sizeof(*buf)); - if (buf == NULL) { - *errp = NETDB_INTERNAL; - return NULL; - } - - /* If there aren't any dots, it could be a user-level alias */ - if (!dots && (cp = hostalias(name)) != NULL) { - for(rtl = rtl0; rtl != NULL; - rtl = SLIST_NEXT(rtl, rtl_entry)) { - ret = res_query(cp, C_IN, rtl->rtl_type, buf->buf, - sizeof(buf->buf)); - if (ret > 0 && ret < sizeof(buf->buf)) { - hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) - ? AF_INET6 : AF_INET; - hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); - hp = getanswer(buf, ret, name, rtl->rtl_type, - &hpbuf, errp); - if (!hp) - continue; - hp = _hpcopy(&hpbuf, errp); - hp0 = _hpmerge(hp0, hp, errp); - } else - *errp = h_errno; - } - free(buf); - return (hp0); - } - - /* - * If there are dots in the name already, let's just give it a try - * 'as is'. The threshold can be set with the "ndots" option. - */ - saved_herrno = -1; - if (dots >= _res.ndots) { - for(rtl = rtl0; rtl != NULL; - rtl = SLIST_NEXT(rtl, rtl_entry)) { - ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, - buf->buf, sizeof(buf->buf)); - if (ret > 0 && ret < sizeof(buf->buf)) { - hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) - ? AF_INET6 : AF_INET; - hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); - hp = getanswer(buf, ret, name, rtl->rtl_type, - &hpbuf, errp); - if (!hp) - continue; - hp = _hpcopy(&hpbuf, errp); - hp0 = _hpmerge(hp0, hp, errp); - } else - *errp = h_errno; - } - if (hp0 != NULL) { - free(buf); - return (hp0); - } - saved_herrno = *errp; - tried_as_is++; - } - - /* - * We do at least one level of search if - * - there is no dot and RES_DEFNAME is set, or - * - there is at least one dot, there is no trailing dot, - * and RES_DNSRCH is set. - */ - if ((!dots && (_res.options & RES_DEFNAMES)) || - (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { - int done = 0; - - for (domain = (const char * const *)_res.dnsrch; - *domain && !done; - domain++) { - - for(rtl = rtl0; rtl != NULL; - rtl = SLIST_NEXT(rtl, rtl_entry)) { - ret = res_querydomain(name, *domain, C_IN, - rtl->rtl_type, - buf->buf, sizeof(buf->buf)); - if (ret > 0 && ret < sizeof(buf->buf)) { - hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) - ? AF_INET6 : AF_INET; - hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); - hp = getanswer(buf, ret, name, - rtl->rtl_type, &hpbuf, errp); - if (!hp) - continue; - hp = _hpcopy(&hpbuf, errp); - hp0 = _hpmerge(hp0, hp, errp); - } else - *errp = h_errno; - } - if (hp0 != NULL) { - free(buf); - return (hp0); - } - - /* - * If no server present, give up. - * If name isn't found in this domain, - * keep trying higher domains in the search list - * (if that's enabled). - * On a NO_DATA error, keep trying, otherwise - * a wildcard entry of another type could keep us - * from finding this entry higher in the domain. - * If we get some other error (negative answer or - * server failure), then stop searching up, - * but try the input name below in case it's - * fully-qualified. - */ - if (errno == ECONNREFUSED) { - free(buf); - *errp = TRY_AGAIN; - return (NULL); - } - - switch (*errp) { - case NO_DATA: - got_nodata++; - /* FALLTHROUGH */ - case HOST_NOT_FOUND: - /* keep trying */ - break; - case TRY_AGAIN: - if (buf->hdr.rcode == SERVFAIL) { - /* try next search element, if any */ - got_servfail++; - break; - } - /* FALLTHROUGH */ - default: - /* anything else implies that we're done */ - done++; - } - - /* if we got here for some reason other than DNSRCH, - * we only wanted one iteration of the loop, so stop. - */ - if (!(_res.options & RES_DNSRCH)) - done++; - } - } - - /* - * If we have not already tried the name "as is", do that now. - * note that we do this regardless of how many dots were in the - * name or whether it ends with a dot unless NOTLDQUERY is set. - */ - if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) { - for(rtl = rtl0; rtl != NULL; - rtl = SLIST_NEXT(rtl, rtl_entry)) { - ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, - buf->buf, sizeof(buf->buf)); - if (ret > 0 && ret < sizeof(buf->buf)) { - hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) - ? AF_INET6 : AF_INET; - hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); - hp = getanswer(buf, ret, name, rtl->rtl_type, - &hpbuf, errp); - if (!hp) - continue; - hp = _hpcopy(&hpbuf, errp); - hp0 = _hpmerge(hp0, hp, errp); - } else - *errp = h_errno; - } - if (hp0 != NULL) { - free(buf); - return (hp0); - } - } - - free(buf); - - /* if we got here, we didn't satisfy the search. - * if we did an initial full query, return that query's h_errno - * (note that we wouldn't be here if that query had succeeded). - * else if we ever got a nodata, send that back as the reason. - * else send back meaningless h_errno, that being the one from - * the last DNSRCH we did. - */ - if (saved_herrno != -1) - *errp = saved_herrno; - else if (got_nodata) - *errp = NO_DATA; - else if (got_servfail) - *errp = TRY_AGAIN; - return (NULL); -} - static int _dns_ghbyname(void *rval, void *cb_data, va_list ap) { const char *name; int af; int *errp; - struct __res_type_list *rtl, rtl4; -#ifdef INET6 - struct __res_type_list rtl6; -#endif + int n; + struct hostent *hp; + int qtype; + struct hostent hbuf; + querybuf *buf; name = va_arg(ap, const char *); af = va_arg(ap, int); errp = va_arg(ap, int *); -#ifdef INET6 + if ((_res.options & RES_INIT) == 0) { + if (res_init() < 0) { + *errp = h_errno; + return NS_UNAVAIL; + } + } + memset(&hbuf, 0, sizeof(hbuf)); + hbuf.h_addrtype = af; + hbuf.h_length = ADDRLEN(af); + switch (af) { - case AF_UNSPEC: - SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; - SLIST_NEXT(&rtl6, rtl_entry) = &rtl4; rtl6.rtl_type = T_AAAA; - rtl = &rtl6; - break; +#ifdef INET6 case AF_INET6: - SLIST_NEXT(&rtl6, rtl_entry) = NULL; rtl6.rtl_type = T_AAAA; - rtl = &rtl6; + qtype = T_AAAA; break; +#endif case AF_INET: - SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; - rtl = &rtl4; + qtype = T_A; break; + default: + *errp = NO_RECOVERY; + return NS_NOTFOUND; } -#else - SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; - rtl = &rtl4; -#endif - *(struct hostent **)rval = _res_search_multi(name, rtl, errp); + buf = malloc(sizeof(*buf)); + if (buf == NULL) { + *errp = NETDB_INTERNAL; + return NS_UNAVAIL; + } + n = res_search(name, C_IN, qtype, buf->buf, sizeof(buf->buf)); + if (n < 0) { + free(buf); + *errp = h_errno; + return NS_UNAVAIL; + } + hp = getanswer(buf, n, name, qtype, &hbuf, errp); + free(buf); + if (!hp) { + *errp = NO_RECOVERY; + return NS_NOTFOUND; + } + *(struct hostent **)rval = _hpcopy(&hbuf, errp); if (*(struct hostent **)rval != NULL) return NS_SUCCESS; else if (*errp == TRY_AGAIN) |