summaryrefslogtreecommitdiffstats
path: root/lib/libc/net/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/net/getaddrinfo.c')
-rw-r--r--lib/libc/net/getaddrinfo.c430
1 files changed, 275 insertions, 155 deletions
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
index e8c6d4f..026909a 100644
--- a/lib/libc/net/getaddrinfo.c
+++ b/lib/libc/net/getaddrinfo.c
@@ -1,4 +1,4 @@
-/* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $ */
+/* $KAME: getaddrinfo.c,v 1.160 2003/05/17 01:30:42 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -37,6 +37,10 @@
* - Return values. There are nonstandard return values defined and used
* in the source code. This is because RFC2553 is silent about which error
* code must be returned for which situation.
+ * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
+ * says to use inet_aton() to convert IPv4 numeric to binary (allows
+ * classful form as a result).
+ * current code - disallow classful form for IPv4 (due to use of inet_pton).
* - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
* invalid. current code - SEGV on freeaddrinfo(NULL)
*
@@ -71,11 +75,15 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
+#ifdef INET6
+#include <sys/queue.h>
+#include <net/if_var.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <netinet6/in6_var.h> /* XXX */
+#endif /* INET6 */
#include <arpa/inet.h>
#include <arpa/nameser.h>
-#include <rpc/rpc.h>
-#include <rpcsvc/yp_prot.h>
-#include <rpcsvc/ypclnt.h>
#include <netdb.h>
#include <pthread.h>
#include <resolv.h>
@@ -153,23 +161,24 @@ struct explore {
#define WILD_AF(ex) ((ex)->e_wild & 0x01)
#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
+#define WILD_ACTIVE(ex) ((ex)->e_wild & 0x08)
+#define WILD_PASSIVE(ex) ((ex)->e_wild & 0x10)
};
static const struct explore explore[] = {
#if 0
- { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
+ { PF_LOCAL, ANY, ANY, NULL, 0x01 },
#endif
#ifdef INET6
- { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
- { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
- { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
+ { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x1f },
+ { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x0f }, /* !PASSIVE */
+ { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x17 }, /* PASSIVE */
+ { PF_INET6, SOCK_RAW, ANY, NULL, 0x1d },
#endif
- { 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 },
+ { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x1f },
+ { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x0f }, /* !PASSIVE */
+ { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x17 }, /* PASSIVE */
+ { PF_INET, SOCK_RAW, ANY, NULL, 0x1d },
{ -1, 0, 0, NULL, 0 },
};
@@ -179,6 +188,8 @@ static const struct explore explore[] = {
#define PTON_MAX 4
#endif
+#define AIO_SRCFLAG_DEPRECATED 0x1
+
static const ns_src default_dns_files[] = {
{ NSSRC_FILES, NS_SUCCESS },
{ NSSRC_DNS, NS_SUCCESS },
@@ -202,20 +213,23 @@ typedef union {
} querybuf;
static int str_isnumber(const char *);
+static int explore_copy(const struct addrinfo *, const struct addrinfo *,
+ struct addrinfo **);
static int explore_null(const struct addrinfo *,
const char *, struct addrinfo **);
static int explore_numeric(const struct addrinfo *, const char *,
- const char *, struct addrinfo **);
+ const char *, struct addrinfo **, const char *);
static int explore_numeric_scope(const struct addrinfo *, const char *,
const char *, struct addrinfo **);
static int get_canonname(const struct addrinfo *,
struct addrinfo *, const char *);
static struct addrinfo *get_ai(const struct addrinfo *,
const struct afd *, const char *);
+static struct addrinfo *copy_ai(const struct addrinfo *);
static int get_portmatch(const struct addrinfo *, const char *);
static int get_port(struct addrinfo *, const char *, int);
static const struct afd *find_afd(int);
-static int addrconfig(struct addrinfo *);
+static int addrconfig(int);
#ifdef INET6
static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
#endif
@@ -373,10 +387,20 @@ getaddrinfo(hostname, servname, hints, res)
struct addrinfo sentinel;
struct addrinfo *cur;
int error = 0;
- struct addrinfo ai;
- struct addrinfo ai0;
+ struct addrinfo ai, ai0, *afai;
struct addrinfo *pai;
+ const struct afd *afd;
const struct explore *ex;
+ struct addrinfo *afailist[sizeof(afdl)/sizeof(afdl[0])];
+ struct addrinfo *afai_unspec;
+ int found;
+ int numeric = 0;
+
+ /* ensure we return NULL on errors */
+ *res = NULL;
+
+ memset(afailist, 0, sizeof(afailist));
+ afai_unspec = NULL;
memset(&sentinel, 0, sizeof(sentinel));
cur = &sentinel;
@@ -417,20 +441,27 @@ getaddrinfo(hostname, servname, hints, res)
*/
if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
for (ex = explore; ex->e_af >= 0; ex++) {
- if (pai->ai_family != ex->e_af)
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
+ WILD_AF(ex)))
continue;
- if (ex->e_socktype == ANY)
+ if (!MATCH(pai->ai_socktype, ex->e_socktype,
+ WILD_SOCKTYPE(ex)))
continue;
- if (ex->e_protocol == ANY)
+ if (!MATCH(pai->ai_protocol, ex->e_protocol,
+ WILD_PROTOCOL(ex)))
continue;
- if (pai->ai_socktype == ex->e_socktype &&
- pai->ai_protocol != ex->e_protocol) {
- ERR(EAI_BADHINTS);
- }
+
+ /* matched */
+ break;
+ }
+
+ if (ex->e_af < 0) {
+ ERR(EAI_BADHINTS);
}
}
}
+#if defined(AI_ALL) && defined(AI_V4MAPPED)
/*
* post-2553: AI_ALL and AI_V4MAPPED are effective only against
* AF_INET6 query. They need to be ignored if specified in other
@@ -451,6 +482,7 @@ getaddrinfo(hostname, servname, hints, res)
#endif
break;
}
+#endif
/*
* check for special cases. (1) numeric servname is disallowed if
@@ -459,7 +491,7 @@ getaddrinfo(hostname, servname, hints, res)
*/
if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
#ifdef PF_INET6
- || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
+ || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
#endif
) {
ai0 = *pai; /* backup *pai */
@@ -480,108 +512,182 @@ getaddrinfo(hostname, servname, hints, res)
ai0 = *pai;
- /* NULL hostname, or numeric hostname */
- for (ex = explore; ex->e_af >= 0; ex++) {
+ /*
+ * NULL hostname, or numeric hostname.
+ * If numreic representation of AF1 can be interpreted as FQDN
+ * representation of AF2, we need to think again about the code below.
+ */
+ found = 0;
+ for (afd = afdl; afd->a_af; afd++) {
*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)))
- continue;
- if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+ if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
continue;
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;
+ pai->ai_family = afd->a_af;
- if (hostname == NULL)
- error = explore_null(pai, servname, &cur->ai_next);
- else
- error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
-
- if (error)
- goto free;
+ if (hostname == NULL) {
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ if (!addrconfig(pai->ai_family))
+ continue;
+ error = explore_null(pai, servname,
+ &afailist[afd - afdl]);
+ } else
+ error = explore_numeric_scope(pai, hostname, servname,
+ &afailist[afd - afdl]);
- while (cur && cur->ai_next)
- cur = cur->ai_next;
+ if (!error && afailist[afd - afdl])
+ found++;
+ }
+ if (found) {
+ numeric = 1;
+ goto globcopy;
}
-
- /*
- * XXX
- * If numreic representation of AF1 can be interpreted as FQDN
- * representation of AF2, we need to think again about the code below.
- */
- if (sentinel.ai_next)
- goto good;
if (hostname == NULL)
ERR(EAI_NONAME); /* used to be EAI_NODATA */
if (pai->ai_flags & AI_NUMERICHOST)
ERR(EAI_NONAME);
- if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0))
- ERR(EAI_FAIL);
-
/*
* hostname as alphabetical name.
- * we would like to prefer AF_INET6 than AF_INET, so we'll make a
- * outer loop by AFs.
+ * first, try to query DNS for all possible address families.
*/
+ /*
+ * the operating systems support PF_UNSPEC lookup in explore_fqdn().
+ */
+ *pai = ai0;
+ error = explore_fqdn(pai, hostname, servname, &afai_unspec);
+
+globcopy:
for (ex = explore; ex->e_af >= 0; ex++) {
*pai = ai0;
- /* require exact match for family field */
- if (pai->ai_family != ex->e_af)
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
+
+ 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 (!MATCH(pai->ai_socktype, ex->e_socktype,
- WILD_SOCKTYPE(ex))) {
+#ifdef AI_ADDRCONFIG
+ /*
+ * If AI_ADDRCONFIG is specified, check if we are
+ * expected to return the address family or not.
+ */
+ if ((pai->ai_flags & AI_ADDRCONFIG) != 0 &&
+ !addrconfig(afd->a_af))
continue;
- }
- if (!MATCH(pai->ai_protocol, ex->e_protocol,
- WILD_PROTOCOL(ex))) {
+#endif
+
+ if ((pai->ai_flags & AI_PASSIVE) != 0 && WILD_PASSIVE(ex))
+ ;
+ else if ((pai->ai_flags & AI_PASSIVE) == 0 && WILD_ACTIVE(ex))
+ ;
+ else
continue;
- }
+ 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);
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ continue;
+
+ if (afai_unspec)
+ afai = afai_unspec;
+ else {
+ if ((afd = find_afd(pai->ai_family)) == NULL)
+ continue;
+ /* XXX assumes that afd points inside afdl[] */
+ afai = afailist[afd - afdl];
+ }
+ if (!afai)
+ continue;
+
+ error = explore_copy(pai, afai, &cur->ai_next);
while (cur && cur->ai_next)
cur = cur->ai_next;
}
- /* XXX */
+ /* XXX inhibit errors if we have the result */
if (sentinel.ai_next)
error = 0;
- if (error)
- goto free;
+ /*
+ * ensure we return either:
+ * - error == 0, non-NULL *res
+ * - error != 0, NULL *res
+ */
if (error == 0) {
if (sentinel.ai_next) {
- good:
*res = sentinel.ai_next;
- return SUCCESS;
+ error = 0;
} else
error = EAI_FAIL;
}
- free:
- bad:
- if (sentinel.ai_next)
- freeaddrinfo(sentinel.ai_next);
- *res = NULL;
+
+bad:
+ if (afai_unspec)
+ freeaddrinfo(afai_unspec);
+ for (afd = afdl; afd->a_af; afd++) {
+ if (afailist[afd - afdl])
+ freeaddrinfo(afailist[afd - afdl]);
+ }
+ if (!*res)
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
+static int
+explore_copy(pai, src0, res)
+ const struct addrinfo *pai; /* seed */
+ const struct addrinfo *src0; /* source */
+ struct addrinfo **res;
+{
+ int error;
+ struct addrinfo sentinel, *cur;
+ const struct addrinfo *src;
+
+ error = 0;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ for (src = src0; src != NULL; src = src->ai_next) {
+ if (src->ai_family != pai->ai_family)
+ continue;
+
+ cur->ai_next = copy_ai(src);
+ if (!cur->ai_next) {
+ error = EAI_MEMORY;
+ goto fail;
+ }
+
+ cur->ai_next->ai_socktype = pai->ai_socktype;
+ cur->ai_next->ai_protocol = pai->ai_protocol;
+ cur = cur->ai_next;
+ }
+
+ *res = sentinel.ai_next;
+ return 0;
+
+fail:
+ freeaddrinfo(sentinel.ai_next);
return error;
}
@@ -596,7 +702,6 @@ explore_null(pai, servname, res)
const char *servname;
struct addrinfo **res;
{
- int s;
const struct afd *afd;
struct addrinfo *cur;
struct addrinfo sentinel;
@@ -607,17 +712,6 @@ explore_null(pai, servname, res)
cur = &sentinel;
/*
- * filter out AFs that are not supported by the kernel
- * XXX errno?
- */
- s = _socket(pai->ai_family, SOCK_DGRAM, 0);
- if (s < 0) {
- if (errno != EMFILE)
- return 0;
- } else
- _close(s);
-
- /*
* if the servname does not match socktype/protocol, ignore it.
*/
if (get_portmatch(pai, servname) != 0)
@@ -655,11 +749,12 @@ free:
* numeric hostname
*/
static int
-explore_numeric(pai, hostname, servname, res)
+explore_numeric(pai, hostname, servname, res, canonname)
const struct addrinfo *pai;
const char *hostname;
const char *servname;
struct addrinfo **res;
+ const char *canonname;
{
const struct afd *afd;
struct addrinfo *cur;
@@ -671,12 +766,6 @@ explore_numeric(pai, hostname, servname, res)
sentinel.ai_next = NULL;
cur = &sentinel;
- /*
- * if the servname does not match socktype/protocol, ignore it.
- */
- if (get_portmatch(pai, servname) != 0)
- return 0;
-
afd = find_afd(pai->ai_family);
if (afd == NULL)
return 0;
@@ -689,6 +778,14 @@ explore_numeric(pai, hostname, servname, res)
pai->ai_family == PF_UNSPEC /*?*/) {
GET_AI(cur->ai_next, afd, pton);
GET_PORT(cur->ai_next, servname);
+ 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 && cur->ai_next)
cur = cur->ai_next;
} else
@@ -702,6 +799,14 @@ explore_numeric(pai, hostname, servname, res)
pai->ai_family == PF_UNSPEC /*?*/) {
GET_AI(cur->ai_next, afd, pton);
GET_PORT(cur->ai_next, servname);
+ 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 && cur->ai_next)
cur = cur->ai_next;
} else
@@ -731,7 +836,7 @@ explore_numeric_scope(pai, hostname, servname, res)
struct addrinfo **res;
{
#if !defined(SCOPE_DELIMITER) || !defined(INET6)
- return explore_numeric(pai, hostname, servname, res);
+ return explore_numeric(pai, hostname, servname, res, hostname);
#else
const struct afd *afd;
struct addrinfo *cur;
@@ -739,22 +844,16 @@ explore_numeric_scope(pai, hostname, servname, res)
char *cp, *hostname2 = NULL, *scope, *addr;
struct sockaddr_in6 *sin6;
- /*
- * if the servname does not match socktype/protocol, ignore it.
- */
- if (get_portmatch(pai, servname) != 0)
- return 0;
-
afd = find_afd(pai->ai_family);
if (afd == NULL)
return 0;
if (!afd->a_scoped)
- return explore_numeric(pai, hostname, servname, res);
+ return explore_numeric(pai, hostname, servname, res, hostname);
cp = strchr(hostname, SCOPE_DELIMITER);
if (cp == NULL)
- return explore_numeric(pai, hostname, servname, res);
+ return explore_numeric(pai, hostname, servname, res, hostname);
/*
* Handle special case of <scoped_address><delimiter><scope id>
@@ -767,7 +866,7 @@ explore_numeric_scope(pai, hostname, servname, res)
addr = hostname2;
scope = cp + 1;
- error = explore_numeric(pai, addr, servname, res);
+ error = explore_numeric(pai, addr, servname, res, hostname);
if (error == 0) {
u_int32_t scopeid;
@@ -777,6 +876,8 @@ explore_numeric_scope(pai, hostname, servname, res)
sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
free(hostname2);
+ freeaddrinfo(*res);
+ *res = NULL;
return(EAI_NONAME); /* XXX: is return OK? */
}
sin6->sin6_scope_id = scopeid;
@@ -785,6 +886,10 @@ explore_numeric_scope(pai, hostname, servname, res)
free(hostname2);
+ if (error && *res) {
+ freeaddrinfo(*res);
+ *res = NULL;
+ }
return error;
#endif
}
@@ -796,10 +901,9 @@ get_canonname(pai, ai, str)
const char *str;
{
if ((pai->ai_flags & AI_CANONNAME) != 0) {
- ai->ai_canonname = (char *)malloc(strlen(str) + 1);
+ ai->ai_canonname = strdup(str);
if (ai->ai_canonname == NULL)
return EAI_MEMORY;
- strlcpy(ai->ai_canonname, str, strlen(str) + 1);
}
return 0;
}
@@ -875,6 +979,39 @@ get_ai(pai, afd, addr)
return ai;
}
+/* XXX need to malloc() the same way we do from other functions! */
+static struct addrinfo *
+copy_ai(pai)
+ const struct addrinfo *pai;
+{
+ struct addrinfo *ai;
+ size_t l;
+
+ l = sizeof(*ai) + pai->ai_addrlen;
+ if ((ai = (struct addrinfo *)malloc(l)) == NULL)
+ return NULL;
+ memset(ai, 0, l);
+ memcpy(ai, pai, sizeof(*ai));
+ ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+ memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
+
+ if (pai->ai_canonname) {
+ l = strlen(pai->ai_canonname) + 1;
+ if ((ai->ai_canonname = malloc(l)) == NULL) {
+ free(ai);
+ return NULL;
+ }
+ strlcpy(ai->ai_canonname, pai->ai_canonname, l);
+ } else {
+ /* just to make sure */
+ ai->ai_canonname = NULL;
+ }
+
+ ai->ai_next = NULL;
+
+ return ai;
+}
+
static int
get_portmatch(ai, servname)
const struct addrinfo *ai;
@@ -914,6 +1051,7 @@ get_port(ai, servname, matchonly)
return EAI_SERVICE;
case SOCK_DGRAM:
case SOCK_STREAM:
+ case SOCK_SEQPACKET:
allownumeric = 1;
break;
case ANY:
@@ -931,11 +1069,11 @@ get_port(ai, servname, matchonly)
return EAI_SERVICE;
port = htons(port);
} else {
- switch (ai->ai_socktype) {
- case SOCK_DGRAM:
+ switch (ai->ai_protocol) {
+ case IPPROTO_UDP:
proto = "udp";
break;
- case SOCK_STREAM:
+ case IPPROTO_TCP:
proto = "tcp";
break;
default:
@@ -986,41 +1124,20 @@ find_afd(af)
* will take care of it.
* the semantics of AI_ADDRCONFIG is not defined well. we are not sure
* if the code is right or not.
- *
- * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
- * _dns_getaddrinfo.
*/
static int
-addrconfig(pai)
- struct addrinfo *pai;
+addrconfig(af)
+ int af;
{
- int s, af;
+ int s;
- /*
- * TODO:
- * Note that implementation dependent test for address
- * configuration should be done everytime called
- * (or apropriate interval),
- * because addresses will be dynamically assigned or deleted.
- */
- af = pai->ai_family;
- 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)
+ /* XXX errno */
+ s = socket(af, SOCK_DGRAM, 0);
+ if (s < 0) {
+ if (errno != EMFILE)
return 0;
- _close(s);
- }
- pai->ai_family = af;
+ } else
+ close(s);
return 1;
}
@@ -1033,16 +1150,15 @@ ip6_str2scopeid(scope, sin6, scopeid)
u_int32_t *scopeid;
{
u_long lscopeid;
- struct in6_addr *a6;
+ struct in6_addr *a6 = &sin6->sin6_addr;
char *ep;
- a6 = &sin6->sin6_addr;
-
/* empty scopeid portion is invalid */
if (*scope == '\0')
return -1;
- if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
+ if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
+ IN6_IS_ADDR_MC_NODELOCAL(a6)) {
/*
* We currently assume a one-to-one mapping between links
* and interfaces, so we simply use interface indices for
@@ -1063,7 +1179,7 @@ ip6_str2scopeid(scope, sin6, scopeid)
goto trynumeric; /* global */
/* try to convert to a numeric id as a last resort */
- trynumeric:
+trynumeric:
errno = 0;
lscopeid = strtoul(scope, &ep, 10);
*scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
@@ -1699,9 +1815,13 @@ nextline:
*cp++ = '\0';
}
- hints = *pai;
+ /* we should not glob socktype/protocol here */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pai->ai_family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = 0;
hints.ai_flags = AI_NUMERICHOST;
- error = getaddrinfo(addr, NULL, &hints, &res0);
+ error = getaddrinfo(addr, "0", &hints, &res0);
if (error == 0) {
for (res = res0; res; res = res->ai_next) {
/* cover it up */
OpenPOWER on IntegriCloud