diff options
author | ume <ume@FreeBSD.org> | 2006-04-15 16:20:27 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2006-04-15 16:20:27 +0000 |
commit | b6bb84cf9e6c9d871a17bcf962cf63180af70e95 (patch) | |
tree | 7f8977d8ba3a31812862992c940fc48d67e9a71c | |
parent | 65a640e4f05dfa0b6ed9cf426628b7a1106b767b (diff) | |
download | FreeBSD-src-b6bb84cf9e6c9d871a17bcf962cf63180af70e95.zip FreeBSD-src-b6bb84cf9e6c9d871a17bcf962cf63180af70e95.tar.gz |
- make reentrant version of netdb functions glibc style API, and
expose them to outside of libc.
- make netdb functions NSS friendly.
Reviewed by: arch@ and current@ (no objection)
-rw-r--r-- | include/netdb.h | 26 | ||||
-rw-r--r-- | lib/libc/net/Symbol.map | 13 | ||||
-rw-r--r-- | lib/libc/net/gethostbydns.c | 258 | ||||
-rw-r--r-- | lib/libc/net/gethostbyht.c | 162 | ||||
-rw-r--r-- | lib/libc/net/gethostbynis.c | 140 | ||||
-rw-r--r-- | lib/libc/net/gethostnamadr.c | 411 | ||||
-rw-r--r-- | lib/libc/net/getnetbydns.c | 115 | ||||
-rw-r--r-- | lib/libc/net/getnetbyht.c | 125 | ||||
-rw-r--r-- | lib/libc/net/getnetbynis.c | 84 | ||||
-rw-r--r-- | lib/libc/net/getnetnamadr.c | 162 | ||||
-rw-r--r-- | lib/libc/net/getproto.c | 28 | ||||
-rw-r--r-- | lib/libc/net/getprotoent.c | 122 | ||||
-rw-r--r-- | lib/libc/net/getprotoname.c | 32 | ||||
-rw-r--r-- | lib/libc/net/getservbyname.c | 34 | ||||
-rw-r--r-- | lib/libc/net/getservbyport.c | 32 | ||||
-rw-r--r-- | lib/libc/net/getservent.c | 135 | ||||
-rw-r--r-- | lib/libc/net/netdb_private.h | 110 |
17 files changed, 1284 insertions, 705 deletions
diff --git a/include/netdb.h b/include/netdb.h index 9d1b005..218bee3 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -221,21 +221,47 @@ void endprotoent(void); void endservent(void); void freehostent(struct hostent *); struct hostent *gethostbyaddr(const char *, int, int); +int gethostbyaddr_r(const char *, int, int, struct hostent *, + char *, size_t, struct hostent **, int *); struct hostent *gethostbyname(const char *); +int gethostbyname_r(const char *, struct hostent *, char *, size_t, + struct hostent **, int *); struct hostent *gethostbyname2(const char *, int); +int gethostbyname2_r(const char *, int, struct hostent *, char *, + size_t, struct hostent **, int *); struct hostent *gethostent(void); +int gethostent_r(struct hostent *, char *, size_t, + struct hostent **, int *); struct hostent *getipnodebyaddr(const void *, size_t, int, int *); struct hostent *getipnodebyname(const char *, int, int, int *); struct netent *getnetbyaddr(uint32_t, int); +int getnetbyaddr_r(uint32_t, int, struct netent *, char *, size_t, + struct netent**, int *); struct netent *getnetbyname(const char *); +int getnetbyname_r(const char *, struct netent *, char *, size_t, + struct netent **, int *); struct netent *getnetent(void); +int getnetent_r(struct netent *, char *, size_t, struct netent **, + int *); int getnetgrent(char **, char **, char **); struct protoent *getprotobyname(const char *); +int getprotobyname_r(const char *, struct protoent *, char *, + size_t, struct protoent **); struct protoent *getprotobynumber(int); +int getprotobynumber_r(int, struct protoent *, char *, size_t, + struct protoent **); struct protoent *getprotoent(void); +int getprotoent_r(struct protoent *, char *, size_t, + struct protoent **); struct servent *getservbyname(const char *, const char *); +int getservbyname_r(const char *, const char *, struct servent *, + char *, size_t, struct servent **); struct servent *getservbyport(int, const char *); +int getservbyport_r(int, const char *, struct servent *, char *, + size_t, struct servent **); struct servent *getservent(void); +int getservent_r(struct servent *, char *, size_t, + struct servent **); void herror(const char *); __const char *hstrerror(int); int innetgr(const char *, const char *, const char *, const char *); diff --git a/lib/libc/net/Symbol.map b/lib/libc/net/Symbol.map index c5e4866..849d392 100644 --- a/lib/libc/net/Symbol.map +++ b/lib/libc/net/Symbol.map @@ -19,9 +19,13 @@ FBSD_1.0 { getaddrinfo; endhostdnsent; gethostent; + gethostent_r; gethostbyname; + gethostbyname_r; gethostbyname2; + gethostbyname2_r; gethostbyaddr; + gethostbyaddr_r; sethostent; endhostent; getifaddrs; @@ -30,20 +34,29 @@ FBSD_1.0 { freeifmaddrs; getnameinfo; getnetent; + getnetent_r; getnetbyname; + getnetbyname_r; getnetbyaddr; + getnetbyaddr_r; setnetent; endnetent; getprotobynumber; + getprotobynumber_r; setprotoent; endprotoent; getprotoent; + getprotoent_r; getprotobyname; + getprotobyname_r; getservbyname; + getservbyname_r; getservbyport; + getservbyport_r; setservent; endservent; getservent; + getservent_r; hesiod_init; hesiod_end; hesiod_to_bind; diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c index b4c80d4..8558513 100644 --- a/lib/libc/net/gethostbydns.c +++ b/lib/libc/net/gethostbydns.c @@ -131,22 +131,22 @@ dprintf(msg, num, res) do { \ cp += x; \ if (cp > eom) { \ - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); \ - return -1; \ + RES_SET_H_ERRNO(statp, NO_RECOVERY); \ + return (-1); \ } \ } while (0) #define BOUNDS_CHECK(ptr, count) \ do { \ if ((ptr) + (count) > eom) { \ - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); \ - return -1; \ + RES_SET_H_ERRNO(statp, NO_RECOVERY); \ + return (-1); \ } \ } while (0) static int gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, - struct hostent *he, struct hostent_data *hed) + struct hostent *he, struct hostent_data *hed, res_state statp) { const HEADER *hp; const u_char *cp; @@ -172,8 +172,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, name_ok = res_dnok; break; default: - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; /* XXX should be abort(); */ + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); /* XXX should be abort(); */ } /* * find first satisfactory answer @@ -186,13 +186,13 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } BOUNDED_INCR(n + QFIXEDSZ); if (qtype == T_A || qtype == T_AAAA) { @@ -202,8 +202,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, */ n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } he->h_name = bp; bp += n; @@ -253,8 +253,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, } cp += n; if (cp != erdata) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } /* Store alias. */ *ap++ = bp; @@ -283,8 +283,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, } cp += n; if (cp != erdata) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ @@ -322,8 +322,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, #if MULTI_PTRS_ARE_ALIASES cp += n; if (cp != erdata) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } if (!haveanswer) he->h_name = bp; @@ -342,7 +342,7 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, break; #else he->h_name = bp; - if (hed->res->options & RES_USE_INET6) { + if (statp->options & RES_USE_INET6) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { had_error++; @@ -351,8 +351,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, bp += n; _map_v4v6_hostent(he, &bp, ep); } - RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS); - return 0; + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + return (0); #endif case T_A: case T_AAAA: @@ -377,14 +377,14 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, bp += sizeof(align) - ((u_long)bp % sizeof(align)); if (bp + n >= ep) { - dprintf("size (%d) too big\n", n, hed->res); + dprintf("size (%d) too big\n", n, statp); had_error++; continue; } if (hap >= &hed->h_addr_ptrs[_MAXADDRS-1]) { if (!toobig++) dprintf("Too many addresses (%d)\n", - _MAXADDRS, hed->res); + _MAXADDRS, statp); cp += n; continue; } @@ -392,15 +392,15 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, bp += n; cp += n; if (cp != erdata) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } break; default: dprintf("Impossible condition (type=%d)\n", type, - hed->res); - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + statp); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); /* BIND has abort() here, too risky on bad data */ } if (!had_error) @@ -415,8 +415,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, * in its return structures - should give it the "best" * address in that case, not some random one */ - if (hed->res->nsort && haveanswer > 1 && qtype == T_A) - addrsort(hed->h_addr_ptrs, haveanswer, hed->res); + if (statp->nsort && haveanswer > 1 && qtype == T_A) + addrsort(hed->h_addr_ptrs, haveanswer, statp); # endif /*RESOLVSORT*/ if (!he->h_name) { n = strlen(qname) + 1; /* for the \0 */ @@ -426,45 +426,46 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, he->h_name = bp; bp += n; } - if (hed->res->options & RES_USE_INET6) + if (statp->options & RES_USE_INET6) _map_v4v6_hostent(he, &bp, ep); - RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS); - return 0; + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + return (0); } no_recovery: - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } /* XXX: for async DNS resolver in ypserv */ struct hostent * __dns_getanswer(const char *answer, int anslen, const char *qname, int qtype) { - struct hostdata *hd; + struct hostent *he; + struct hostent_data *hed; int error; res_state statp; statp = __res_state(); - if ((hd = __hostdata_init()) == NULL) { + if ((he = __hostent_init()) == NULL || + (hed = __hostent_data_init()) == NULL) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); - return NULL; + return (NULL); } - hd->data.res = statp; switch (qtype) { case T_AAAA: - hd->host.h_addrtype = AF_INET6; - hd->host.h_length = IN6ADDRSZ; + he->h_addrtype = AF_INET6; + he->h_length = NS_IN6ADDRSZ; break; case T_A: default: - hd->host.h_addrtype = AF_INET; - hd->host.h_length = INADDRSZ; + he->h_addrtype = AF_INET; + he->h_length = NS_INADDRSZ; break; } error = gethostanswer((const querybuf *)answer, anslen, qname, qtype, - &hd->host, &hd->data); - return (error == 0) ? &hd->host : NULL; + he, hed, statp); + return (error == 0) ? he : NULL; } int @@ -472,51 +473,78 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap) { const char *name; int af; - struct hostent *he; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; struct hostent_data *hed; querybuf *buf; - int n, size, type, error; + int n, type, error; + res_state statp; name = va_arg(ap, const char *); af = va_arg(ap, int); - he = va_arg(ap, struct hostent *); - hed = va_arg(ap, struct hostent_data *); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + he.h_addrtype = af; switch (af) { case AF_INET: - size = INADDRSZ; + he.h_length = NS_INADDRSZ; type = T_A; break; case AF_INET6: - size = IN6ADDRSZ; + he.h_length = NS_IN6ADDRSZ; type = T_AAAA; break; default: - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; errno = EAFNOSUPPORT; - return NS_UNAVAIL; + return (NS_UNAVAIL); } - he->h_addrtype = af; - he->h_length = size; - if ((buf = malloc(sizeof(*buf))) == NULL) { - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return NS_NOTFOUND; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } - n = res_nsearch(hed->res, name, C_IN, type, buf->buf, sizeof(buf->buf)); + n = res_nsearch(statp, name, C_IN, type, buf->buf, sizeof(buf->buf)); if (n < 0) { free(buf); - dprintf("res_nsearch failed (%d)\n", n, hed->res); + dprintf("res_nsearch failed (%d)\n", n, statp); + *h_errnop = statp->res_h_errno; return (0); } else if (n > sizeof(buf->buf)) { free(buf); - dprintf("static buffer is too small (%d)\n", n, hed->res); + dprintf("static buffer is too small (%d)\n", n, statp); + *h_errnop = statp->res_h_errno; return (0); } - error = gethostanswer(buf, n, name, type, he, hed); + error = gethostanswer(buf, n, name, type, &he, hed, statp); free(buf); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); } int @@ -524,24 +552,41 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) { const u_char *uaddr; int len, af; - struct hostent *he; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; struct hostent_data *hed; - int n, error; + int n; querybuf *buf; char qbuf[MAXDNAME+1], *qp; + res_state statp; #ifdef SUNSECURITY struct hostdata rhd; struct hostent *rhe; char **haddr; u_long old_options; char hname2[MAXDNAME+1], numaddr[46]; + int ret_h_error; #endif /*SUNSECURITY*/ uaddr = va_arg(ap, const u_char *); len = va_arg(ap, int); af = va_arg(ap, int); - he = va_arg(ap, struct hostent *); - hed = va_arg(ap, struct hostent_data *); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } switch (af) { case AF_INET: @@ -553,7 +598,7 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) break; case AF_INET6: qp = qbuf; - for (n = IN6ADDRSZ - 1; n >= 0; n--) { + for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) { qp += SPRINTF((qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf)); @@ -564,24 +609,28 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) abort(); } if ((buf = malloc(sizeof(*buf))) == NULL) { - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; return NS_NOTFOUND; } - n = res_nquery(hed->res, qbuf, C_IN, T_PTR, (u_char *)buf->buf, + n = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf->buf, sizeof buf->buf); if (n < 0) { free(buf); - dprintf("res_nquery failed (%d)\n", n, hed->res); - return NS_UNAVAIL; + dprintf("res_nquery failed (%d)\n", n, statp); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } if (n > sizeof buf->buf) { free(buf); - dprintf("static buffer is too small (%d)\n", n, hed->res); - return NS_UNAVAIL; + dprintf("static buffer is too small (%d)\n", n, statp); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } - if ((error = gethostanswer(buf, n, qbuf, T_PTR, he, hed)) != 0) { + if (gethostanswer(buf, n, qbuf, T_PTR, &he, hed, statp) != 0) { free(buf); - return NS_NOTFOUND; /* h_errno was set by gethostanswer() */ + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); /* h_errno was set by gethostanswer() */ } free(buf); #ifdef SUNSECURITY @@ -590,25 +639,28 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) * turn off search as the name should be absolute, * 'localhost' should be matched by defnames */ - strncpy(hname2, he->h_name, MAXDNAME); + strncpy(hname2, he.h_name, MAXDNAME); hname2[MAXDNAME] = '\0'; - old_options = hed->res->options; - hed->res->options &= ~RES_DNSRCH; - hed->res->options |= RES_DEFNAMES; + old_options = statp->options; + statp->options &= ~RES_DNSRCH; + statp->options |= RES_DEFNAMES; memset(&rhd, 0, sizeof rhd); - if (!(rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data))) { + rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data, + sizeof(rhd.data), &ret_h_error); + if (rhe == NULL) { if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) strlcpy(numaddr, "UNKNOWN", sizeof(numaddr)); syslog(LOG_NOTICE|LOG_AUTH, "gethostbyaddr: No A record for %s (verifying [%s])", hname2, numaddr); - hed->res->options = old_options; - RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND); - return NS_NOTFOUND; + statp->options = old_options; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } - hed->res->options = old_options; + statp->options = old_options; for (haddr = rhe->h_addr_list; *haddr; haddr++) - if (!memcmp(*haddr, addr, INADDRSZ)) + if (!memcmp(*haddr, addr, NS_INADDRSZ)) break; if (!*haddr) { if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) @@ -616,31 +668,34 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) syslog(LOG_NOTICE|LOG_AUTH, "gethostbyaddr: A record of %s != PTR record [%s]", hname2, numaddr); - RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND); - return NS_NOTFOUND; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } } #endif /*SUNSECURITY*/ - he->h_addrtype = af; - he->h_length = len; + he.h_addrtype = af; + he.h_length = len; memcpy(hed->host_addr, uaddr, len); hed->h_addr_ptrs[0] = (char *)hed->host_addr; hed->h_addr_ptrs[1] = NULL; - if (af == AF_INET && (hed->res->options & RES_USE_INET6)) { + if (af == AF_INET && (statp->options & RES_USE_INET6)) { _map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr); - he->h_addrtype = AF_INET6; - he->h_length = IN6ADDRSZ; + he.h_addrtype = AF_INET6; + he.h_length = NS_IN6ADDRSZ; + } + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } - RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); } #ifdef RESOLVSORT static void -addrsort(ap, num, res) - char **ap; - int num; - res_state res; +addrsort(char **ap, int num, res_state res) { int i, j; char **p; @@ -682,8 +737,7 @@ addrsort(ap, num, res) #endif void -_sethostdnsent(stayopen) - int stayopen; +_sethostdnsent(int stayopen) { res_state statp; diff --git a/lib/libc/net/gethostbyht.c b/lib/libc/net/gethostbyht.c index 462cd5c..0782518 100644 --- a/lib/libc/net/gethostbyht.c +++ b/lib/libc/net/gethostbyht.c @@ -91,7 +91,8 @@ _endhosthtent(struct hostent_data *hed) } static int -gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped) +gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped, + res_state statp) { char *p, *bp, *ep; char *cp, **q; @@ -99,13 +100,13 @@ gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped) char hostbuf[BUFSIZ + 1]; if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) { - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); } again: if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) { - RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND); - return -1; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + return (-1); } if (*p == '#') goto again; @@ -146,8 +147,8 @@ gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped) *p++ = '\0'; len = strlen(cp) + 1; if (ep - bp < len) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } strlcpy(bp, cp, ep - bp); bp += len; @@ -170,31 +171,50 @@ gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped) cp = p; } *q = NULL; - RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS); - return 0; + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + return (0); } int -gethostent_r(struct hostent *he, struct hostent_data *hed) +gethostent_r(struct hostent *hptr, char *buffer, size_t buflen, + struct hostent **result, int *h_errnop) { - hed->res = __res_state(); - if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) { - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + struct hostent_data *hed; + struct hostent he; + res_state statp; + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); + } + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); } - return gethostent_p(he, hed, hed->res->options & RES_USE_INET6); + if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0) + return (-1); + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) + return (-1); + *result = hptr; + return (0); } struct hostent * gethostent(void) { struct hostdata *hd; + struct hostent *rval; + int ret_h_errno; if ((hd = __hostdata_init()) == NULL) - return NULL; - if (gethostent_r(&hd->host, &hd->data) != 0) - return NULL; - return &hd->host; + return (NULL); + if (gethostent_r(&hd->host, hd->data, sizeof(hd->data), &rval, + &ret_h_errno) != 0) + return (NULL); + return (rval); } int @@ -202,36 +222,61 @@ _ht_gethostbyname(void *rval, void *cb_data, va_list ap) { const char *name; int af; - struct hostent *he; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; struct hostent_data *hed; char **cp; + res_state statp; int error; name = va_arg(ap, const char *); af = va_arg(ap, int); - he = va_arg(ap, struct hostent *); - hed = va_arg(ap, struct hostent_data *); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } - sethostent_r(0, hed); - while ((error = gethostent_p(he, hed, 0)) == 0) { - if (he->h_addrtype != af) + _sethosthtent(0, hed); + while ((error = gethostent_p(&he, hed, 0, statp)) == 0) { + if (he.h_addrtype != af) continue; - if (he->h_addrtype == AF_INET && - hed->res->options & RES_USE_INET6) { - _map_v4v6_address(he->h_addr, he->h_addr); - he->h_length = IN6ADDRSZ; - he->h_addrtype = AF_INET6; + if (he.h_addrtype == AF_INET && + statp->options & RES_USE_INET6) { + _map_v4v6_address(he.h_addr, he.h_addr); + he.h_length = IN6ADDRSZ; + he.h_addrtype = AF_INET6; } - if (strcasecmp(he->h_name, name) == 0) + if (strcasecmp(he.h_name, name) == 0) break; - for (cp = he->h_aliases; *cp != 0; cp++) + for (cp = he.h_aliases; *cp != 0; cp++) if (strcasecmp(*cp, name) == 0) goto found; } found: - endhostent_r(hed); + _endhosthtent(hed); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); } int @@ -239,28 +284,51 @@ _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap) { const char *addr; int len, af; - struct hostent *he; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; struct hostent_data *hed; + res_state statp; int error; addr = va_arg(ap, const char *); len = va_arg(ap, int); af = va_arg(ap, int); - he = va_arg(ap, struct hostent *); - hed = va_arg(ap, struct hostent_data *); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; - sethostent_r(0, hed); - while ((error = gethostent_p(he, hed, 0)) == 0) - if (he->h_addrtype == af && !bcmp(he->h_addr, addr, len)) { - if (he->h_addrtype == AF_INET && - hed->res->options & RES_USE_INET6) { - _map_v4v6_address(he->h_addr, he->h_addr); - he->h_length = IN6ADDRSZ; - he->h_addrtype = AF_INET6; + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + + _sethosthtent(0, hed); + while ((error = gethostent_p(&he, hed, 0, statp)) == 0) + if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) { + if (he.h_addrtype == AF_INET && + statp->options & RES_USE_INET6) { + _map_v4v6_address(he.h_addr, he.h_addr); + he.h_length = IN6ADDRSZ; + he.h_addrtype = AF_INET6; } break; } - endhostent_r(hed); + _endhosthtent(hed); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + if (error != 0) + return (NS_NOTFOUND); + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); } diff --git a/lib/libc/net/gethostbynis.c b/lib/libc/net/gethostbynis.c index 1475d84..5ce6097 100644 --- a/lib/libc/net/gethostbynis.c +++ b/lib/libc/net/gethostbynis.c @@ -57,7 +57,9 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he, char *result; int resultlen, size, addrok = 0; char ypbuf[YPMAXRECORD + 2]; + res_state statp; + statp = __res_state(); switch(af) { case AF_INET: size = NS_INADDRSZ; @@ -67,20 +69,20 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he, break; default: errno = EAFNOSUPPORT; - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); } if (hed->yp_domain == (char *)NULL) if (yp_get_default_domain (&hed->yp_domain)) { - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); } if (yp_match(hed->yp_domain, map, name, strlen(name), &result, &resultlen)) { - RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND); - return -1; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + return (-1); } /* avoid potential memory leak */ @@ -101,7 +103,7 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he, addrok = inet_aton(result, (struct in_addr *)hed->host_addr); if (addrok != 1) break; - if (hed->res->options & RES_USE_INET6) { + if (statp->options & RES_USE_INET6) { _map_v4v6_address((char *)hed->host_addr, (char *)hed->host_addr); af = AF_INET6; @@ -113,8 +115,8 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he, break; } if (addrok != 1) { - RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND); - return -1; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + return (-1); } he->h_addr_list[1] = NULL; he->h_length = size; @@ -130,8 +132,8 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he, *p++ = '\0'; size = strlen(cp) + 1; if (ep - bp < size) { - RES_SET_H_ERRNO(hed->res, NO_RECOVERY); - return -1; + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } strlcpy(bp, cp, ep - bp); bp += size; @@ -155,7 +157,7 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he, cp = p; } *q = NULL; - return 0; + return (0); } static int @@ -172,7 +174,7 @@ _gethostbynisname_r(const char *name, int af, struct hostent *he, map = "ipnodes.byname"; break; } - return _gethostbynis(name, map, af, he, hed); + return (_gethostbynis(name, map, af, he, hed)); } static int @@ -191,8 +193,8 @@ _gethostbynisaddr_r(const char *addr, int len, int af, struct hostent *he, break; } if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) - return -1; - return _gethostbynis(numaddr, map, af, he, hed); + return (-1); + return (_gethostbynis(numaddr, map, af, he, hed)); } #endif /* YP */ @@ -201,24 +203,26 @@ struct hostent * _gethostbynisname(const char *name, int af) { #ifdef YP - struct hostdata *hd; + struct hostent *he; + struct hostent_data *hed; u_long oresopt; int error; res_state statp; statp = __res_state(); - if ((hd = __hostdata_init()) == NULL) { + if ((he = __hostent_init()) == NULL || + (hed = __hostent_data_init()) == NULL) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); - return NULL; + return (NULL); } - hd->data.res = statp; + oresopt = statp->options; statp->options &= ~RES_USE_INET6; - error = _gethostbynisname_r(name, af, &hd->host, &hd->data); + error = _gethostbynisname_r(name, af, he, hed); statp->options = oresopt; - return (error == 0) ? &hd->host : NULL; + return (error == 0) ? he : NULL; #else - return NULL; + return (NULL); #endif } @@ -226,24 +230,26 @@ struct hostent * _gethostbynisaddr(const char *addr, int len, int af) { #ifdef YP - struct hostdata *hd; + struct hostent *he; + struct hostent_data *hed; u_long oresopt; int error; res_state statp; statp = __res_state(); - if ((hd = __hostdata_init()) == NULL) { + if ((he = __hostent_init()) == NULL || + (hed = __hostent_data_init()) == NULL) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); - return NULL; + return (NULL); } - hd->data.res = statp; + oresopt = statp->options; statp->options &= ~RES_USE_INET6; - error = _gethostbynisaddr_r(addr, len, af, &hd->host, &hd->data); + error = _gethostbynisaddr_r(addr, len, af, he, hed); statp->options = oresopt; - return (error == 0) ? &hd->host : NULL; + return (error == 0) ? he : NULL; #else - return NULL; + return (NULL); #endif } @@ -253,19 +259,43 @@ _nis_gethostbyname(void *rval, void *cb_data, va_list ap) #ifdef YP const char *name; int af; - struct hostent *he; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; struct hostent_data *hed; - int error; + res_state statp; name = va_arg(ap, const char *); af = va_arg(ap, int); - he = va_arg(ap, struct hostent *); - hed = va_arg(ap, struct hostent_data *); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); - error = _gethostbynisname_r(name, af, he, hed); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + + if (_gethostbynisname_r(name, af, &he, hed) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); #else - return NS_UNAVAIL; + *((struct hostent **)rval) = NULL; + return (NS_UNAVAIL); #endif } @@ -276,19 +306,43 @@ _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap) const char *addr; int len; int af; - struct hostent *he; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; struct hostent_data *hed; - int error; + res_state statp; addr = va_arg(ap, const char *); len = va_arg(ap, int); af = va_arg(ap, int); - he = va_arg(ap, struct hostent *); - hed = va_arg(ap, struct hostent_data *); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); - error = _gethostbynisaddr_r(addr, len, af, he, hed); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + + if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); #else - return NS_UNAVAIL; + *((struct hostent **)rval) = NULL; + return (NS_UNAVAIL); #endif } diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c index b641f73..c8867e5 100644 --- a/lib/libc/net/gethostnamadr.c +++ b/lib/libc/net/gethostnamadr.c @@ -52,8 +52,8 @@ extern int _ht_gethostbyaddr(void *, void *, va_list); extern int _dns_gethostbyaddr(void *, void *, va_list); extern int _nis_gethostbyaddr(void *, void *, va_list); -static int gethostbyname_internal(const char *, int, struct hostent *, - struct hostent_data *); +static int gethostbyname_internal(const char *, int, struct hostent *, char *, + size_t, struct hostent **, int *, res_state); /* Host lookup order if nsswitch.conf is broken or nonexistant */ static const ns_src default_src[] = { @@ -62,87 +62,190 @@ static const ns_src default_src[] = { { 0 } }; -static struct hostdata hostdata; -static thread_key_t hostdata_key; -static once_t hostdata_init_once = ONCE_INITIALIZER; -static int hostdata_thr_keycreated = 0; +NETDB_THREAD_ALLOC(hostent) +NETDB_THREAD_ALLOC(hostent_data) +NETDB_THREAD_ALLOC(hostdata) static void -hostdata_free(void *ptr) +hostent_free(void *ptr) +{ + free(ptr); +} + +static void +hostent_data_free(void *ptr) { - struct hostdata *hd = ptr; + struct hostent_data *hed = ptr; - if (hd == NULL) + if (hed == NULL) return; - hd->data.stayopen = 0; - _endhosthtent(&hd->data); - free(hd); + hed->stayopen = 0; + _endhosthtent(hed); + free(hed); } static void -hostdata_keycreate(void) +hostdata_free(void *ptr) { - hostdata_thr_keycreated = - (thr_keycreate(&hostdata_key, hostdata_free) == 0); + free(ptr); } -struct hostdata * -__hostdata_init(void) +int +__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf, + size_t buflen) { - struct hostdata *hd; + char *cp; + char **ptr; + int i, n; + int nptr, len; + + /* Find out the amount of space required to store the answer. */ + nptr = 2; /* NULL ptrs */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; he->h_addr_list[i]; i++, nptr++) { + len += he->h_length; + } + for (i = 0; he->h_aliases[i]; i++, nptr++) { + len += strlen(he->h_aliases[i]) + 1; + } + len += strlen(he->h_name) + 1; + len += nptr * sizeof(char*); + + if (len > buflen) { + errno = ERANGE; + return (-1); + } - if (thr_main() != 0) - return &hostdata; - if (thr_once(&hostdata_init_once, hostdata_keycreate) != 0 || - !hostdata_thr_keycreated) - return NULL; - if ((hd = thr_getspecific(hostdata_key)) != NULL) - return hd; - if ((hd = calloc(1, sizeof(*hd))) == NULL) - return NULL; - if (thr_setspecific(hostdata_key, hd) == 0) - return hd; - free(hd); - return NULL; + /* copy address size and type */ + hptr->h_addrtype = he->h_addrtype; + n = hptr->h_length = he->h_length; + + ptr = (char **)ALIGN(buf); + cp = (char *)ALIGN(buf) + nptr * sizeof(char *); + + /* copy address list */ + hptr->h_addr_list = ptr; + for (i = 0; he->h_addr_list[i]; i++ , ptr++) { + memcpy(cp, he->h_addr_list[i], n); + hptr->h_addr_list[i] = cp; + cp += n; + } + hptr->h_addr_list[i] = NULL; + ptr++; + + /* copy official name */ + n = strlen(he->h_name) + 1; + strcpy(cp, he->h_name); + hptr->h_name = cp; + cp += n; + + /* copy aliases */ + hptr->h_aliases = ptr; + for (i = 0 ; he->h_aliases[i]; i++) { + n = strlen(he->h_aliases[i]) + 1; + strcpy(cp, he->h_aliases[i]); + hptr->h_aliases[i] = cp; + cp += n; + } + hptr->h_aliases[i] = NULL; + + return (0); +} + +static int +fakeaddr(const char *name, int af, struct hostent *hp, char *buf, +size_t buflen, res_state statp) +{ + struct hostent_data *hed; + struct hostent he; + + if ((hed = __hostent_data_init()) == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); + } + + if ((af != AF_INET || + inet_aton(name, (struct in_addr *)hed->host_addr) != 1) && + inet_pton(af, name, hed->host_addr) != 1) { + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + return (-1); + } + strncpy(hed->hostbuf, name, MAXDNAME); + hed->hostbuf[MAXDNAME] = '\0'; + if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) { + _map_v4v6_address((char *)hed->host_addr, + (char *)hed->host_addr); + af = AF_INET6; + } + he.h_addrtype = af; + switch(af) { + case AF_INET: + he.h_length = NS_INADDRSZ; + break; + case AF_INET6: + he.h_length = NS_IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); + } + he.h_name = hed->hostbuf; + he.h_aliases = hed->host_aliases; + hed->host_aliases[0] = NULL; + hed->h_addr_ptrs[0] = (char *)hed->host_addr; + hed->h_addr_ptrs[1] = NULL; + he.h_addr_list = hed->h_addr_ptrs; + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + return (__copy_hostent(&he, hp, buf, buflen)); } int -gethostbyname_r(const char *name, struct hostent *he, struct hostent_data *hed) +gethostbyname_r(const char *name, struct hostent *he, char *buffer, + size_t buflen, struct hostent **result, int *h_errnop) { - int error; + res_state statp; - hed->res = __res_state(); - if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) { - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); } - if (hed->res->options & RES_USE_INET6) { - error = gethostbyname_internal(name, AF_INET6, he, hed); - if (error == 0) - return 0; + if (statp->options & RES_USE_INET6) { + if (fakeaddr(name, AF_INET, he, buffer, buflen, statp) == 0) { + *result = he; + return (0); + } + if (gethostbyname_internal(name, AF_INET6, he, buffer, buflen, + result, h_errnop, statp) == 0) + return (0); } - return gethostbyname_internal(name, AF_INET, he, hed); + return (gethostbyname_internal(name, AF_INET, he, buffer, buflen, + result, h_errnop, statp)); } int -gethostbyname2_r(const char *name, int af, struct hostent *he, - struct hostent_data *hed) +gethostbyname2_r(const char *name, int af, struct hostent *he, char *buffer, + size_t buflen, struct hostent **result, int *h_errnop) { - hed->res = __res_state(); - if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) { - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + res_state statp; + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); } - return gethostbyname_internal(name, af, he, hed); + return (gethostbyname_internal(name, af, he, buffer, buflen, result, + h_errnop, statp)); } -static int -gethostbyname_internal(const char *name, int af, struct hostent *he, - struct hostent_data *hed) +int +gethostbyname_internal(const char *name, int af, struct hostent *hp, char *buf, + size_t buflen, struct hostent **result, int *h_errnop, res_state statp) { const char *cp; - char *bp, *ep; - int size, rval; + int rval, ret_errno; char abuf[MAXDNAME]; static const ns_dtab dtab[] = { @@ -154,111 +257,45 @@ gethostbyname_internal(const char *name, int af, struct hostent *he, switch (af) { case AF_INET: - size = INADDRSZ; - break; case AF_INET6: - size = IN6ADDRSZ; break; default: - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; errno = EAFNOSUPPORT; - return -1; + return (-1); } - he->h_addrtype = af; - he->h_length = size; - /* * if there aren't any dots, it could be a user-level alias. * this is also done in res_query() since we are not the only * function that looks up host names. */ if (!strchr(name, '.') && - (cp = res_hostalias(hed->res, name, abuf, sizeof abuf))) + (cp = res_hostalias(statp, name, abuf, sizeof abuf))) name = cp; - /* - * disallow names consisting only of digits/dots, unless - * they end in a dot. - */ - if (isdigit((u_char)name[0])) - for (cp = name;; ++cp) { - if (!*cp) { - if (*--cp == '.') - break; - /* - * All-numeric, no dot at the end. - * Fake up a hostent as if we'd actually - * done a lookup. - */ - if (inet_pton(af, name, hed->host_addr) <= 0) { - RES_SET_H_ERRNO(hed->res, - HOST_NOT_FOUND); - return -1; - } - strncpy(hed->hostbuf, name, MAXDNAME); - hed->hostbuf[MAXDNAME] = '\0'; - bp = hed->hostbuf + MAXDNAME + 1; - ep = hed->hostbuf + sizeof hed->hostbuf; - he->h_name = hed->hostbuf; - he->h_aliases = hed->host_aliases; - hed->host_aliases[0] = NULL; - hed->h_addr_ptrs[0] = (char *)hed->host_addr; - hed->h_addr_ptrs[1] = NULL; - he->h_addr_list = hed->h_addr_ptrs; - if (hed->res->options & RES_USE_INET6) - _map_v4v6_hostent(he, &bp, ep); - RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS); - return 0; - } - if (!isdigit((u_char)*cp) && *cp != '.') - break; - } - if ((isxdigit((u_char)name[0]) && strchr(name, ':') != NULL) || - name[0] == ':') - for (cp = name;; ++cp) { - if (!*cp) { - if (*--cp == '.') - break; - /* - * All-IPv6-legal, no dot at the end. - * Fake up a hostent as if we'd actually - * done a lookup. - */ - if (inet_pton(af, name, hed->host_addr) <= 0) { - RES_SET_H_ERRNO(hed->res, - HOST_NOT_FOUND); - return -1; - } - strncpy(hed->hostbuf, name, MAXDNAME); - hed->hostbuf[MAXDNAME] = '\0'; - he->h_name = hed->hostbuf; - he->h_aliases = hed->host_aliases; - hed->host_aliases[0] = NULL; - hed->h_addr_ptrs[0] = (char *)hed->host_addr; - hed->h_addr_ptrs[1] = NULL; - he->h_addr_list = hed->h_addr_ptrs; - RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS); - return 0; - } - if (!isxdigit((u_char)*cp) && *cp != ':' && *cp != '.') - break; - } + if (fakeaddr(name, af, hp, buf, buflen, statp) == 0) { + *result = hp; + return (0); + } - rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyname", - default_src, name, af, he, hed); + rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS, + "gethostbyname2_r", default_src, name, af, hp, buf, buflen, + &ret_errno, h_errnop); - return (rval == NS_SUCCESS) ? 0 : -1; + return ((rval == NS_SUCCESS) ? 0 : -1); } int -gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he, - struct hostent_data *hed) +gethostbyaddr_r(const char *addr, int len, int af, struct hostent *hp, + char *buf, size_t buflen, struct hostent **result, int *h_errnop) { const u_char *uaddr = (const u_char *)addr; const struct in6_addr *addr6; socklen_t size; - int rval; + int rval, ret_errno; + res_state statp; static const ns_dtab dtab[] = { NS_FILES_CB(_ht_gethostbyaddr, NULL) @@ -267,116 +304,118 @@ gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he, { 0 } }; - hed->res = __res_state(); - if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) { - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); } - if (af == AF_INET6 && len == IN6ADDRSZ) { + if (af == AF_INET6 && len == NS_IN6ADDRSZ) { addr6 = (const struct in6_addr *)(const void *)uaddr; if (IN6_IS_ADDR_LINKLOCAL(addr6)) { - RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND); - return -1; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + *h_errnop = statp->res_h_errno; + return (-1); } if (IN6_IS_ADDR_V4MAPPED(addr6) || IN6_IS_ADDR_V4COMPAT(addr6)) { /* Unmap. */ - uaddr += IN6ADDRSZ - INADDRSZ; + uaddr += NS_IN6ADDRSZ - NS_INADDRSZ; af = AF_INET; - len = INADDRSZ; + len = NS_INADDRSZ; } } switch (af) { case AF_INET: - size = INADDRSZ; + size = NS_INADDRSZ; break; case AF_INET6: - size = IN6ADDRSZ; + size = NS_IN6ADDRSZ; break; default: errno = EAFNOSUPPORT; - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); } if (size != len) { errno = EINVAL; - RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); - return -1; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); } - rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyaddr", - default_src, uaddr, len, af, he, hed); - - return (rval == NS_SUCCESS) ? 0 : -1; -} - -void -sethostent_r(int stayopen, struct hostent_data *hed) -{ - _sethosthtent(stayopen, hed); - _sethostdnsent(stayopen); -} + rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS, + "gethostbyaddr_r", default_src, uaddr, len, af, hp, buf, buflen, + &ret_errno, h_errnop); -void -endhostent_r(struct hostent_data *hed) -{ - _endhosthtent(hed); - _endhostdnsent(); + return ((rval == NS_SUCCESS) ? 0 : -1); } struct hostent * gethostbyname(const char *name) { struct hostdata *hd; + struct hostent *rval; + int ret_h_errno; if ((hd = __hostdata_init()) == NULL) - return NULL; - if (gethostbyname_r(name, &hd->host, &hd->data) != 0) - return NULL; - return &hd->host; + return (NULL); + if (gethostbyname_r(name, &hd->host, hd->data, sizeof(hd->data), &rval, + &ret_h_errno) != 0) + return (NULL); + return (rval); } struct hostent * gethostbyname2(const char *name, int af) { struct hostdata *hd; + struct hostent *rval; + int ret_h_errno; if ((hd = __hostdata_init()) == NULL) - return NULL; - if (gethostbyname2_r(name, af, &hd->host, &hd->data) != 0) - return NULL; - return &hd->host; + return (NULL); + if (gethostbyname2_r(name, af, &hd->host, hd->data, sizeof(hd->data), + &rval, &ret_h_errno) != 0) + return (NULL); + return (rval); } struct hostent * gethostbyaddr(const char *addr, int len, int af) { struct hostdata *hd; + struct hostent *rval; + int ret_h_errno; if ((hd = __hostdata_init()) == NULL) - return NULL; - if (gethostbyaddr_r(addr, len, af, &hd->host, &hd->data) != 0) - return NULL; - return &hd->host; + return (NULL); + if (gethostbyaddr_r(addr, len, af, &hd->host, hd->data, + sizeof(hd->data), &rval, &ret_h_errno) != 0) + return (NULL); + return (rval); } void sethostent(int stayopen) { - struct hostdata *hd; + struct hostent_data *hed; - if ((hd = __hostdata_init()) == NULL) + if ((hed = __hostent_data_init()) == NULL) return; - sethostent_r(stayopen, &hd->data); + _sethosthtent(stayopen, hed); + _sethostdnsent(stayopen); } void endhostent(void) { - struct hostdata *hd; + struct hostent_data *hed; - if ((hd = __hostdata_init()) == NULL) + if ((hed = __hostent_data_init()) == NULL) return; - endhostent_r(&hd->data); + _endhosthtent(hed); + _endhostdnsent(); } diff --git a/lib/libc/net/getnetbydns.c b/lib/libc/net/getnetbydns.c index 06f4243..23c9c45 100644 --- a/lib/libc/net/getnetbydns.c +++ b/lib/libc/net/getnetbydns.c @@ -196,7 +196,7 @@ getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne, RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); else RES_SET_H_ERRNO(statp, TRY_AGAIN); - return -1; + return (-1); } while (qdcount-- > 0) cp += __dn_skipname(cp, eom) + QFIXEDSZ; @@ -220,9 +220,9 @@ getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne, n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !res_hnok(bp)) { cp += n; - return -1; + return (-1); } - cp += n; + cp += n; *ap++ = bp; n = strlen(bp) + 1; bp += n; @@ -243,24 +243,24 @@ getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne, if (ep - bp < n) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); errno = ENOBUFS; - return -1; + return (-1); } strlcpy(bp, ans, ep - bp); ne->n_name = bp; if (strlen(in) + 1 > sizeof(aux)) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); errno = ENOBUFS; - return -1; + return (-1); } ipreverse(in, aux); ne->n_net = inet_network(aux); break; } ne->n_aliases++; - return 0; + return (0); } RES_SET_H_ERRNO(statp, TRY_AGAIN); - return -1; + return (-1); } int @@ -268,7 +268,10 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) { uint32_t net; int net_type; - struct netent *ne; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; struct netent_data *ned; unsigned int netbr[4]; int nn, anslen, error; @@ -279,16 +282,31 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) net = va_arg(ap, uint32_t); net_type = va_arg(ap, int); - ne = va_arg(ap, struct netent *); - ned = va_arg(ap, struct netent_data *); - - if (net_type != AF_INET) - return NS_UNAVAIL; + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); statp = __res_state(); if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); - return NS_UNAVAIL; + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + + *((struct netent **)rval) = NULL; + + if (net_type != AF_INET) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } for (nn = 4, net2 = net; net2; net2 >>= 8) @@ -311,7 +329,8 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) } if ((buf = malloc(sizeof(*buf))) == NULL) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); - return NS_NOTFOUND; + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } anslen = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf, sizeof(*buf)); @@ -321,32 +340,43 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) if (statp->options & RES_DEBUG) printf("res_nsearch failed\n"); #endif - return NS_UNAVAIL; + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } else if (anslen > sizeof(*buf)) { free(buf); #ifdef DEBUG if (statp->options & RES_DEBUG) printf("res_nsearch static buffer too small\n"); #endif - return NS_UNAVAIL; + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } - error = getnetanswer(buf, anslen, BYADDR, ne, ned, statp); + error = getnetanswer(buf, anslen, BYADDR, &ne, ned, statp); free(buf); if (error == 0) { /* Strip trailing zeros */ while ((net & 0xff) == 0 && net != 0) net >>= 8; - ne->n_net = net; - return NS_SUCCESS; + ne.n_net = net; + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); } - return NS_NOTFOUND; + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } int _dns_getnetbyname(void *rval, void *cb_data, va_list ap) { const char *net; - struct netent *ne; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; struct netent_data *ned; int anslen, error; querybuf *buf; @@ -354,18 +384,31 @@ _dns_getnetbyname(void *rval, void *cb_data, va_list ap) res_state statp; net = va_arg(ap, const char *); - ne = va_arg(ap, struct netent *); - ned = va_arg(ap, struct netent_data *); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); statp = __res_state(); if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); - return NS_UNAVAIL; + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } if ((buf = malloc(sizeof(*buf))) == NULL) { RES_SET_H_ERRNO(statp, NETDB_INTERNAL); - return NS_NOTFOUND; + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } + + *((struct netent **)rval) = NULL; + strncpy(qbuf, net, sizeof(qbuf) - 1); qbuf[sizeof(qbuf) - 1] = '\0'; anslen = res_nsearch(statp, qbuf, C_IN, T_PTR, (u_char *)buf, @@ -376,23 +419,31 @@ _dns_getnetbyname(void *rval, void *cb_data, va_list ap) if (statp->options & RES_DEBUG) printf("res_nsearch failed\n"); #endif - return NS_UNAVAIL; + return (NS_UNAVAIL); } else if (anslen > sizeof(*buf)) { free(buf); #ifdef DEBUG if (statp->options & RES_DEBUG) printf("res_search static buffer too small\n"); #endif - return NS_UNAVAIL; + return (NS_UNAVAIL); } - error = getnetanswer(buf, anslen, BYNAME, ne, ned, statp); + error = getnetanswer(buf, anslen, BYNAME, &ne, ned, statp); free(buf); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); } void -_setnetdnsent(stayopen) - int stayopen; +_setnetdnsent(int stayopen) { res_state statp; diff --git a/lib/libc/net/getnetbyht.c b/lib/libc/net/getnetbyht.c index 30422d5..580345a 100644 --- a/lib/libc/net/getnetbyht.c +++ b/lib/libc/net/getnetbyht.c @@ -83,8 +83,8 @@ _endnethtent(struct netent_data *ned) ned->stayopen = 0; } -int -getnetent_r(struct netent *ne, struct netent_data *ned) +static int +getnetent_p(struct netent *ne, struct netent_data *ned) { char *p, *bp, *ep; char *cp, **q; @@ -93,11 +93,11 @@ getnetent_r(struct netent *ne, struct netent_data *ned) if (ned->netf == NULL && (ned->netf = fopen(_PATH_NETWORKS, "r")) == NULL) - return -1; + return (-1); again: p = fgets(line, sizeof line, ned->netf); if (p == NULL) - return -1; + return (-1); if (*p == '#') goto again; cp = strpbrk(p, "#\n"); @@ -113,7 +113,7 @@ again: len = strlen(p) + 1; if (ep - bp < len) { RES_SET_H_ERRNO(__res_state(), NO_RECOVERY); - return -1; + return (-1); } strlcpy(bp, p, ep - bp); bp += len; @@ -147,46 +147,94 @@ again: } } *q = NULL; - return 0; + return (0); +} + +int +getnetent_r(struct netent *nptr, char *buffer, size_t buflen, + struct netent **result, int *h_errnop) +{ + struct netent_data *ned; + struct netent ne; + res_state statp; + + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); + } + if (getnetent_p(&ne, ned) != 0) + return (-1); + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) + return (-1); + *result = nptr; + return (0); } struct netent * getnetent(void) { struct netdata *nd; + struct netent *rval; + int ret_h_errno; if ((nd = __netdata_init()) == NULL) - return NULL; - if (getnetent_r(&nd->net, &nd->data) != 0) - return NULL; - return &nd->net; + return (NULL); + if (getnetent_r(&nd->net, nd->data, sizeof(nd->data), &rval, + &ret_h_errno) != 0) + return (NULL); + return (rval); } int _ht_getnetbyname(void *rval, void *cb_data, va_list ap) { const char *name; - struct netent *ne; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; struct netent_data *ned; char **cp; + res_state statp; int error; name = va_arg(ap, const char *); - ne = va_arg(ap, struct netent *); - ned = va_arg(ap, struct netent_data *); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); - setnetent_r(ned->stayopen, ned); - while ((error = getnetent_r(ne, ned)) == 0) { - if (strcasecmp(ne->n_name, name) == 0) + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + + _setnethtent(ned->stayopen, ned); + while ((error = getnetent_p(&ne, ned)) == 0) { + if (strcasecmp(ne.n_name, name) == 0) break; - for (cp = ne->n_aliases; *cp != 0; cp++) + for (cp = ne.n_aliases; *cp != 0; cp++) if (strcasecmp(*cp, name) == 0) goto found; } found: if (!ned->stayopen) - endnetent_r(ned); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + _endnethtent(ned); + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); } int @@ -194,20 +242,43 @@ _ht_getnetbyaddr(void *rval, void *cb_data, va_list ap) { uint32_t net; int type; - struct netent *ne; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; struct netent_data *ned; + res_state statp; int error; net = va_arg(ap, uint32_t); type = va_arg(ap, int); - ne = va_arg(ap, struct netent *); - ned = va_arg(ap, struct netent_data *); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); - setnetent_r(ned->stayopen, ned); - while ((error = getnetent_r(ne, ned)) == 0) - if (ne->n_addrtype == type && ne->n_net == net) + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + + _setnethtent(ned->stayopen, ned); + while ((error = getnetent_p(&ne, ned)) == 0) + if (ne.n_addrtype == type && ne.n_net == net) break; if (!ned->stayopen) - endnetent_r(ned); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + _endnethtent(ned); + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); } diff --git a/lib/libc/net/getnetbynis.c b/lib/libc/net/getnetbynis.c index ea7c3d4..d00c7f2 100644 --- a/lib/libc/net/getnetbynis.c +++ b/lib/libc/net/getnetbynis.c @@ -64,16 +64,16 @@ _getnetbynis(const char *name, char *map, int af, struct netent *ne, default: case AF_INET6: errno = EAFNOSUPPORT; - return -1; + return (-1); } if (ned->yp_domain == (char *)NULL) if (yp_get_default_domain (&ned->yp_domain)) - return -1; + return (-1); if (yp_match(ned->yp_domain, map, name, strlen(name), &result, &resultlen)) - return -1; + return (-1); bcopy((char *)result, (char *)&ypbuf, resultlen); ypbuf[resultlen] = '\0'; @@ -90,7 +90,7 @@ _getnetbynis(const char *name, char *map, int af, struct netent *ne, len = strlen(result) + 1; if (ep - bp < len) { RES_SET_H_ERRNO(__res_state(), NO_RECOVERY); - return -1; + return (-1); } strlcpy(bp, result, ep - bp); ne->n_name = bp; @@ -125,7 +125,7 @@ _getnetbynis(const char *name, char *map, int af, struct netent *ne, cp = p; } *q = NULL; - return 0; + return (0); } #endif /* YP */ @@ -134,18 +134,39 @@ _nis_getnetbyname(void *rval, void *cb_data, va_list ap) { #ifdef YP const char *name; - struct netent *ne; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; struct netent_data *ned; - int error; + res_state statp; name = va_arg(ap, const char *); - ne = va_arg(ap, struct netent *); - ned = va_arg(ap, struct netent_data *); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } - error = _getnetbynis(name, "networks.byname", AF_INET, ne, ned); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + if (_getnetbynis(name, "networks.byname", AF_INET, &ne, ned) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); #else - return NS_UNAVAIL; + return (NS_UNAVAIL); #endif } @@ -156,23 +177,38 @@ _nis_getnetbyaddr(void *rval, void *cb_data, va_list ap) #ifdef YP uint32_t addr; int af; - struct netent *ne; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; struct netent_data *ned; char *str, *cp; uint32_t net2; int nn; unsigned int netbr[4]; char buf[MAXDNAME]; - int error; + res_state statp; addr = va_arg(ap, uint32_t); af = va_arg(ap, int); - ne = va_arg(ap, struct netent *); - ned = va_arg(ap, struct netent_data *); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } if (af != AF_INET) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; errno = EAFNOSUPPORT; - return NS_UNAVAIL; + return (NS_UNAVAIL); } for (nn = 4, net2 = addr; net2; net2 >>= 8) { @@ -203,9 +239,17 @@ _nis_getnetbyaddr(void *rval, void *cb_data, va_list ap) cp = str + (strlen(str) - 2); } - error = _getnetbynis(str, "networks.byaddr", af, ne, ned); - return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; + if (_getnetbynis(str, "networks.byaddr", af, &ne, ned) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); #else - return NS_UNAVAIL; + return (NS_UNAVAIL); #endif /* YP */ } diff --git a/lib/libc/net/getnetnamadr.c b/lib/libc/net/getnetnamadr.c index ef982bc..633cb30 100644 --- a/lib/libc/net/getnetnamadr.c +++ b/lib/libc/net/getnetnamadr.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <netdb.h> #include <stdio.h> #include <ctype.h> +#include <errno.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> @@ -50,61 +51,84 @@ extern int _dns_getnetbyaddr(void *, void *, va_list); extern int _nis_getnetbyaddr(void *, void *, va_list); /* Network lookup order if nsswitch.conf is broken or nonexistant */ -static const ns_src default_src[] = { +static const ns_src default_src[] = { { NSSRC_FILES, NS_SUCCESS }, { NSSRC_DNS, NS_SUCCESS }, { 0 } }; -static struct netdata netdata; -static thread_key_t netdata_key; -static once_t netdata_init_once = ONCE_INITIALIZER; -static int netdata_thr_keycreated = 0; +NETDB_THREAD_ALLOC(netent_data) +NETDB_THREAD_ALLOC(netdata) static void -netdata_free(void *ptr) +netent_data_free(void *ptr) { - struct netdata *nd = ptr; + struct netent_data *ned = ptr; - if (nd == NULL) + if (ned == NULL) return; - nd->data.stayopen = 0; - _endnethtent(&nd->data); - free(nd); + ned->stayopen = 0; + _endnethtent(ned); + free(ned); } static void -netdata_keycreate(void) +netdata_free(void *ptr) { - netdata_thr_keycreated = - (thr_keycreate(&netdata_key, netdata_free) == 0); + free(ptr); } -struct netdata * -__netdata_init(void) +int +__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen) { - struct netdata *nd; - - if (thr_main() != 0) - return &netdata; - if (thr_once(&netdata_init_once, netdata_keycreate) != 0 || - !netdata_thr_keycreated) - return NULL; - if ((nd = thr_getspecific(netdata_key)) != NULL) - return nd; - if ((nd = calloc(1, sizeof(*nd))) == NULL) - return NULL; - if (thr_setspecific(netdata_key, nd) == 0) - return nd; - free(nd); - return NULL; + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; ne->n_aliases[i]; i++, numptr++) { + len += strlen(ne->n_aliases[i]) + 1; + } + len += strlen(ne->n_name) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (-1); + } + + /* copy net value and type */ + nptr->n_addrtype = ne->n_addrtype; + nptr->n_net = ne->n_net; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(ne->n_name) + 1; + strcpy(cp, ne->n_name); + nptr->n_name = cp; + cp += n; + + /* copy aliases */ + nptr->n_aliases = (char **)ALIGN(buf); + for (i = 0 ; ne->n_aliases[i]; i++) { + n = strlen(ne->n_aliases[i]) + 1; + strcpy(cp, ne->n_aliases[i]); + nptr->n_aliases[i] = cp; + cp += n; + } + nptr->n_aliases[i] = NULL; + + return (0); } int -getnetbyname_r(const char *name, struct netent *ne, struct netent_data *ned) +getnetbyname_r(const char *name, struct netent *ne, char *buffer, + size_t buflen, struct netent **result, int *h_errorp) { - int rval; - + int rval, ret_errno; static const ns_dtab dtab[] = { NS_FILES_CB(_ht_getnetbyname, NULL) @@ -113,17 +137,18 @@ getnetbyname_r(const char *name, struct netent *ne, struct netent_data *ned) { 0 } }; - rval = _nsdispatch(NULL, dtab, NSDB_NETWORKS, "getnetbyname", - default_src, name, ne, ned); + rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS, + "getnetbyname_r", default_src, name, ne, buffer, buflen, + &ret_errno, h_errorp); - return (rval == NS_SUCCESS) ? 0 : -1; + return ((rval == NS_SUCCESS) ? 0 : -1); } int -getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, - struct netent_data *ned) +getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer, + size_t buflen, struct netent **result, int *h_errorp) { - int rval; + int rval, ret_errno; static const ns_dtab dtab[] = { NS_FILES_CB(_ht_getnetbyaddr, NULL) @@ -132,66 +157,61 @@ getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, { 0 } }; - rval = _nsdispatch(NULL, dtab, NSDB_NETWORKS, "getnetbyaddr", - default_src, addr, af, ne, ned); + rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS, + "getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen, + &ret_errno, h_errorp); - return (rval == NS_SUCCESS) ? 0 : -1; -} - -void -setnetent_r(int stayopen, struct netent_data *ned) -{ - _setnethtent(stayopen, ned); - _setnetdnsent(stayopen); -} - -void -endnetent_r(struct netent_data *ned) -{ - _endnethtent(ned); - _endnetdnsent(); + return ((rval == NS_SUCCESS) ? 0 : -1); } struct netent * getnetbyname(const char *name) { struct netdata *nd; + struct netent *rval; + int ret_h_errno; if ((nd = __netdata_init()) == NULL) - return NULL; - if (getnetbyname_r(name, &nd->net, &nd->data) != 0) - return NULL; - return &nd->net; + return (NULL); + if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval, + &ret_h_errno) != 0) + return (NULL); + return (rval); } struct netent * getnetbyaddr(uint32_t addr, int af) { struct netdata *nd; + struct netent *rval; + int ret_h_errno; if ((nd = __netdata_init()) == NULL) - return NULL; - if (getnetbyaddr_r(addr, af, &nd->net, &nd->data) != 0) - return NULL; - return &nd->net; + return (NULL); + if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data), + &rval, &ret_h_errno) != 0) + return (NULL); + return (rval); } void setnetent(int stayopen) { - struct netdata *nd; + struct netent_data *ned; - if ((nd = __netdata_init()) == NULL) + if ((ned = __netent_data_init()) == NULL) return; - setnetent_r(stayopen, &nd->data); + _setnethtent(stayopen, ned); + _setnetdnsent(stayopen); } void endnetent(void) { - struct netdata *nd; + struct netent_data *ned; - if ((nd = __netdata_init()) == NULL) + if ((ned = __netent_data_init()) == NULL) return; - endnetent_r(&nd->data); + _endnethtent(ned); + _endnetdnsent(); } diff --git a/lib/libc/net/getproto.c b/lib/libc/net/getproto.c index 400fa7c..9a32983 100644 --- a/lib/libc/net/getproto.c +++ b/lib/libc/net/getproto.c @@ -41,27 +41,39 @@ __FBSDID("$FreeBSD$"); #include "netdb_private.h" int -getprotobynumber_r(int proto, struct protoent *pe, struct protoent_data *ped) +getprotobynumber_r(int proto, struct protoent *pptr, char *buffer, + size_t buflen, struct protoent **result) { + struct protoent pe; + struct protoent_data *ped; int error; - setprotoent_r(ped->stayopen, ped); - while ((error = getprotoent_r(pe, ped)) == 0) - if (pe->p_proto == proto) + if ((ped = __protoent_data_init()) == NULL) + return (-1); + __setprotoent_p(ped->stayopen, ped); + while ((error = __getprotoent_p(&pe, ped)) == 0) + if (pe.p_proto == proto) break; if (!ped->stayopen) - endprotoent_r(ped); - return (error); + __endprotoent_p(ped); + if (error != 0) + return (-1); + if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) + return (-1); + *result = pptr; + return (0); } struct protoent * getprotobynumber(int proto) { struct protodata *pd; + struct protoent *rval; if ((pd = __protodata_init()) == NULL) return (NULL); - if (getprotobynumber_r(proto, &pd->proto, &pd->data) != 0) + if (getprotobynumber_r(proto, &pd->proto, pd->data, sizeof(pd->data), + &rval) != 0) return (NULL); - return (&pd->proto); + return (rval); } diff --git a/lib/libc/net/getprotoent.c b/lib/libc/net/getprotoent.c index a6c2be8..28f055b 100644 --- a/lib/libc/net/getprotoent.c +++ b/lib/libc/net/getprotoent.c @@ -37,8 +37,10 @@ static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93"; #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/param.h> #include <sys/types.h> #include <sys/socket.h> +#include <errno.h> #include <limits.h> #include <netdb.h> #include <stdio.h> @@ -49,10 +51,8 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "netdb_private.h" -static struct protodata protodata; -static thread_key_t protodata_key; -static once_t protodata_init_once = ONCE_INITIALIZER; -static int protodata_thr_keycreated = 0; +NETDB_THREAD_ALLOC(protoent_data) +NETDB_THREAD_ALLOC(protodata) static void protoent_data_clear(struct protoent_data *ped) @@ -64,45 +64,68 @@ protoent_data_clear(struct protoent_data *ped) } static void -protodata_free(void *ptr) +protoent_data_free(void *ptr) { - struct protodata *pd = ptr; + struct protoent_data *ped = ptr; - if (pd == NULL) - return; - protoent_data_clear(&pd->data); - free(pd); + protoent_data_clear(ped); + free(ped); } static void -protodata_keycreate(void) +protodata_free(void *ptr) { - protodata_thr_keycreated = - (thr_keycreate(&protodata_key, protodata_free) == 0); + free(ptr); } -struct protodata * -__protodata_init(void) +int +__copy_protoent(struct protoent *pe, struct protoent *pptr, char *buf, + size_t buflen) { - struct protodata *pd; + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; pe->p_aliases[i]; i++, numptr++) { + len += strlen(pe->p_aliases[i]) + 1; + } + len += strlen(pe->p_name) + 1; + len += numptr * sizeof(char*); - if (thr_main() != 0) - return (&protodata); - if (thr_once(&protodata_init_once, protodata_keycreate) != 0 || - !protodata_thr_keycreated) - return (NULL); - if ((pd = thr_getspecific(protodata_key)) != NULL) - return (pd); - if ((pd = calloc(1, sizeof(*pd))) == NULL) - return (NULL); - if (thr_setspecific(protodata_key, pd) == 0) - return (pd); - free(pd); - return (NULL); + if (len > (int)buflen) { + errno = ERANGE; + return (-1); + } + + /* copy protocol value*/ + pptr->p_proto = pe->p_proto; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(pe->p_name) + 1; + strcpy(cp, pe->p_name); + pptr->p_name = cp; + cp += n; + + /* copy aliases */ + pptr->p_aliases = (char **)ALIGN(buf); + for (i = 0 ; pe->p_aliases[i]; i++) { + n = strlen(pe->p_aliases[i]) + 1; + strcpy(cp, pe->p_aliases[i]); + pptr->p_aliases[i] = cp; + cp += n; + } + pptr->p_aliases[i] = NULL; + + return (0); } void -setprotoent_r(int f, struct protoent_data *ped) +__setprotoent_p(int f, struct protoent_data *ped) { if (ped->fp == NULL) ped->fp = fopen(_PATH_PROTOCOLS, "r"); @@ -112,7 +135,7 @@ setprotoent_r(int f, struct protoent_data *ped) } void -endprotoent_r(struct protoent_data *ped) +__endprotoent_p(struct protoent_data *ped) { if (ped->fp) { fclose(ped->fp); @@ -122,7 +145,7 @@ endprotoent_r(struct protoent_data *ped) } int -getprotoent_r(struct protoent *pe, struct protoent_data *ped) +__getprotoent_p(struct protoent *pe, struct protoent_data *ped) { char *p; char *cp, **q, *endp; @@ -171,34 +194,53 @@ again: return (0); } +int +getprotoent_r(struct protoent *pptr, char *buffer, size_t buflen, + struct protoent **result) +{ + struct protoent pe; + struct protoent_data *ped; + + if ((ped = __protoent_data_init()) == NULL) + return (-1); + + if (__getprotoent_p(&pe, ped) != 0) + return (-1); + if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) + return (-1); + *result = pptr; + return (0); +} + void setprotoent(int f) { - struct protodata *pd; + struct protoent_data *ped; - if ((pd = __protodata_init()) == NULL) + if ((ped = __protoent_data_init()) == NULL) return; - setprotoent_r(f, &pd->data); + __setprotoent_p(f, ped); } void endprotoent(void) { - struct protodata *pd; + struct protoent_data *ped; - if ((pd = __protodata_init()) == NULL) + if ((ped = __protoent_data_init()) == NULL) return; - endprotoent_r(&pd->data); + __endprotoent_p(ped); } struct protoent * getprotoent(void) { struct protodata *pd; + struct protoent *rval; if ((pd = __protodata_init()) == NULL) return (NULL); - if (getprotoent_r(&pd->proto, &pd->data) != 0) + if (getprotoent_r(&pd->proto, pd->data, sizeof(pd->data), &rval) != 0) return (NULL); - return (&pd->proto); + return (rval); } diff --git a/lib/libc/net/getprotoname.c b/lib/libc/net/getprotoname.c index 99232a2..afe3f9d47 100644 --- a/lib/libc/net/getprotoname.c +++ b/lib/libc/net/getprotoname.c @@ -42,34 +42,46 @@ __FBSDID("$FreeBSD$"); #include "netdb_private.h" int -getprotobyname_r(const char *name, struct protoent *pe, - struct protoent_data *ped) +getprotobyname_r(const char *name, struct protoent *pptr, char *buffer, + size_t buflen, struct protoent **result) { + struct protoent pe; + struct protoent_data *ped; char **cp; int error; - setprotoent_r(ped->stayopen, ped); - while ((error = getprotoent_r(pe, ped)) == 0) { - if (strcmp(pe->p_name, name) == 0) + if ((ped = __protoent_data_init()) == NULL) + return (-1); + + __setprotoent_p(ped->stayopen, ped); + while ((error = __getprotoent_p(&pe, ped)) == 0) { + if (strcmp(pe.p_name, name) == 0) break; - for (cp = pe->p_aliases; *cp != 0; cp++) + for (cp = pe.p_aliases; *cp != 0; cp++) if (strcmp(*cp, name) == 0) goto found; } found: if (!ped->stayopen) - endprotoent_r(ped); - return (error); + __endprotoent_p(ped); + if (error != 0) + return (-1); + if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) + return (-1); + *result = pptr; + return (0); } struct protoent * getprotobyname(const char *name) { struct protodata *pd; + struct protoent *rval; if ((pd = __protodata_init()) == NULL) return (NULL); - if (getprotobyname_r(name, &pd->proto, &pd->data) != 0) + if (getprotobyname_r(name, &pd->proto, pd->data, sizeof(pd->data), + &rval) != 0) return (NULL); - return (&pd->proto); + return (rval); } diff --git a/lib/libc/net/getservbyname.c b/lib/libc/net/getservbyname.c index efc3c26..8870c6c 100644 --- a/lib/libc/net/getservbyname.c +++ b/lib/libc/net/getservbyname.c @@ -42,48 +42,60 @@ __FBSDID("$FreeBSD$"); #include "netdb_private.h" int -getservbyname_r(const char *name, const char *proto, struct servent *se, - struct servent_data *sed) +getservbyname_r(const char *name, const char *proto, struct servent *sptr, + char *buffer, size_t buflen, struct servent **result) { + struct servent se; + struct servent_data *sed; char **cp; int error; + if ((sed = __servent_data_init()) == NULL) + return (-1); + #ifdef YP sed->yp_name = (char *)name; sed->yp_proto = (char *)proto; #endif - setservent_r(sed->stayopen, sed); - while ((error = getservent_r(se, sed)) == 0) { - if (strcmp(name, se->s_name) == 0) + __setservent_p(sed->stayopen, sed); + while ((error = __getservent_p(&se, sed)) == 0) { + if (strcmp(name, se.s_name) == 0) goto gotname; - for (cp = se->s_aliases; *cp; cp++) + for (cp = se.s_aliases; *cp; cp++) if (strcmp(name, *cp) == 0) goto gotname; continue; gotname: - if (proto == 0 || strcmp(se->s_proto, proto) == 0) + if (proto == 0 || strcmp(se.s_proto, proto) == 0) break; } if (!sed->stayopen) - endservent_r(sed); + __endservent_p(sed); #ifdef YP sed->yp_name = NULL; sed->yp_proto = NULL; #endif - return (error); + if (error != 0) + return (-1); + if (__copy_servent(&se, sptr, buffer, buflen) != 0) + return (-1); + *result = sptr; + return (0); } struct servent * getservbyname(const char *name, const char *proto) { struct servdata *sd; + struct servent *rval; if ((sd = __servdata_init()) == NULL) return (NULL); - if (getservbyname_r(name, proto, &sd->serv, &sd->data) != 0) + if (getservbyname_r(name, proto, &sd->serv, sd->data, sizeof(sd->data), + &rval) != 0) return (NULL); - return (&sd->serv); + return (rval); } diff --git a/lib/libc/net/getservbyport.c b/lib/libc/net/getservbyport.c index 33524a2..827e5bf 100644 --- a/lib/libc/net/getservbyport.c +++ b/lib/libc/net/getservbyport.c @@ -42,42 +42,54 @@ __FBSDID("$FreeBSD$"); #include "netdb_private.h" int -getservbyport_r(int port, const char *proto, struct servent *se, - struct servent_data *sed) +getservbyport_r(int port, const char *proto, struct servent *sptr, + char *buffer, size_t buflen, struct servent **result) { + struct servent se; + struct servent_data *sed; int error; + if ((sed = __servent_data_init()) == NULL) + return (-1); + #ifdef YP sed->yp_port = port; sed->yp_proto = (char *)proto; #endif - setservent_r(sed->stayopen, sed); - while ((error = getservent_r(se, sed)) == 0) { - if (se->s_port != port) + __setservent_p(sed->stayopen, sed); + while ((error = __getservent_p(&se, sed)) == 0) { + if (se.s_port != port) continue; - if (proto == 0 || strcmp(se->s_proto, proto) == 0) + if (proto == 0 || strcmp(se.s_proto, proto) == 0) break; } if (!sed->stayopen) - endservent_r(sed); + __endservent_p(sed); #ifdef YP sed->yp_port = 0; sed->yp_proto = NULL; #endif - return (error); + if (error != 0) + return (-1); + if (__copy_servent(&se, sptr, buffer, buflen) != 0) + return (-1); + *result = sptr; + return (0); } struct servent * getservbyport(int port, const char *proto) { struct servdata *sd; + struct servent *rval; if ((sd = __servdata_init()) == NULL) return (NULL); - if (getservbyport_r(port, proto, &sd->serv, &sd->data) != 0) + if (getservbyport_r(port, proto, &sd->serv, sd->data, + sizeof(sd->data), &rval) != 0) return (NULL); - return (&sd->serv); + return (rval); } diff --git a/lib/libc/net/getservent.c b/lib/libc/net/getservent.c index 310bd78..ff4864a9 100644 --- a/lib/libc/net/getservent.c +++ b/lib/libc/net/getservent.c @@ -37,9 +37,11 @@ static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/param.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> +#include <errno.h> #include <limits.h> #include <netdb.h> #include <stdio.h> @@ -55,10 +57,8 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "netdb_private.h" -static struct servdata servdata; -static thread_key_t servdata_key; -static once_t servdata_init_once = ONCE_INITIALIZER; -static int servdata_thr_keycreated = 0; +NETDB_THREAD_ALLOC(servent_data) +NETDB_THREAD_ALLOC(servdata) static void servent_data_clear(struct servent_data *sed) @@ -74,41 +74,71 @@ servent_data_clear(struct servent_data *sed) } static void -servdata_free(void *ptr) +servent_data_free(void *ptr) { - struct servdata *sd = ptr; + struct servent_data *sed = ptr; - if (sd == NULL) - return; - servent_data_clear(&sd->data); - free(sd); + servent_data_clear(sed); + free(sed); } static void -servdata_keycreate(void) +servdata_free(void *ptr) { - servdata_thr_keycreated = - (thr_keycreate(&servdata_key, servdata_free) == 0); + free(ptr); } -struct servdata * -__servdata_init(void) +int +__copy_servent(struct servent *se, struct servent *sptr, char *buf, + size_t buflen) { - struct servdata *sd; + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; se->s_aliases[i]; i++, numptr++) { + len += strlen(se->s_aliases[i]) + 1; + } + len += strlen(se->s_name) + 1; + len += strlen(se->s_proto) + 1; + len += numptr * sizeof(char*); - if (thr_main() != 0) - return (&servdata); - if (thr_once(&servdata_init_once, servdata_keycreate) != 0 || - !servdata_thr_keycreated) - return (NULL); - if ((sd = thr_getspecific(servdata_key)) != NULL) - return (sd); - if ((sd = calloc(1, sizeof(*sd))) == NULL) - return (NULL); - if (thr_setspecific(servdata_key, sd) == 0) - return (sd); - free(sd); - return (NULL); + if (len > (int)buflen) { + errno = ERANGE; + return (-1); + } + + /* copy port value */ + sptr->s_port = se->s_port; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(se->s_name) + 1; + strcpy(cp, se->s_name); + sptr->s_name = cp; + cp += n; + + /* copy aliases */ + sptr->s_aliases = (char **)ALIGN(buf); + for (i = 0 ; se->s_aliases[i]; i++) { + n = strlen(se->s_aliases[i]) + 1; + strcpy(cp, se->s_aliases[i]); + sptr->s_aliases[i] = cp; + cp += n; + } + sptr->s_aliases[i] = NULL; + + /* copy proto */ + n = strlen(se->s_proto) + 1; + strcpy(cp, se->s_proto); + sptr->s_proto = cp; + cp += n; + + return (0); } #ifdef YP @@ -149,7 +179,7 @@ _getservbyport_yp(struct servent_data *sed) } else return(0); } - + /* getservent() expects lines terminated with \n -- make it happy */ snprintf(sed->line, sizeof sed->line, "%.*s\n", resultlen, result); @@ -178,7 +208,7 @@ _getservbyname_yp(struct servent_data *sed) &result, &resultlen)) { return(0); } - + /* getservent() expects lines terminated with \n -- make it happy */ snprintf(sed->line, sizeof sed->line, "%.*s\n", resultlen, result); @@ -229,7 +259,7 @@ _getservent_yp(struct servent_data *sed) #endif void -setservent_r(int f, struct servent_data *sed) +__setservent_p(int f, struct servent_data *sed) { if (sed->fp == NULL) sed->fp = fopen(_PATH_SERVICES, "r"); @@ -239,7 +269,7 @@ setservent_r(int f, struct servent_data *sed) } void -endservent_r(struct servent_data *sed) +__endservent_p(struct servent_data *sed) { servent_data_clear(sed); sed->stayopen = 0; @@ -250,7 +280,7 @@ endservent_r(struct servent_data *sed) } int -getservent_r(struct servent *se, struct servent_data *sed) +__getservent_p(struct servent *se, struct servent_data *sed) { char *p; char *cp, **q, *endp; @@ -273,7 +303,7 @@ again: if (sed->yp_name != NULL) { if (!_getservbyname_yp(sed)) goto tryagain; - } + } else if (sed->yp_port != 0) { if (!_getservbyport_yp(sed)) goto tryagain; @@ -323,34 +353,53 @@ unpack: return (0); } +int +getservent_r(struct servent *sptr, char *buffer, size_t buflen, + struct servent **result) +{ + struct servent se; + struct servent_data *sed; + + if ((sed = __servent_data_init()) == NULL) + return (-1); + + if (__getservent_p(&se, sed) != 0) + return (-1); + if (__copy_servent(&se, sptr, buffer, buflen) != 0) + return (-1); + *result = sptr; + return (0); +} + void setservent(int f) { - struct servdata *sd; + struct servent_data *sed; - if ((sd = __servdata_init()) == NULL) + if ((sed = __servent_data_init()) == NULL) return; - setservent_r(f, &sd->data); + __setservent_p(f, sed); } void endservent(void) { - struct servdata *sd; + struct servent_data *sed; - if ((sd = __servdata_init()) == NULL) + if ((sed = __servent_data_init()) == NULL) return; - endservent_r(&sd->data); + __endservent_p(sed); } struct servent * getservent(void) { struct servdata *sd; + struct servent *rval; if ((sd = __servdata_init()) == NULL) return (NULL); - if (getservent_r(&sd->serv, &sd->data) != 0) + if (getservent_r(&sd->serv, sd->data, sizeof(sd->data), &rval) != 0) return (NULL); - return (&sd->serv); + return (rval); } diff --git a/lib/libc/net/netdb_private.h b/lib/libc/net/netdb_private.h index cbdcb17..fa1de62 100644 --- a/lib/libc/net/netdb_private.h +++ b/lib/libc/net/netdb_private.h @@ -30,14 +30,47 @@ #include <stdio.h> /* XXX: for FILE */ +#define NETDB_THREAD_ALLOC(name) \ +static struct name name; \ +static thread_key_t name##_key; \ +static once_t name##_init_once = ONCE_INITIALIZER; \ +static int name##_thr_keycreated = 0; \ +\ +static void name##_free(void *); \ +\ +static void \ +name##_keycreate(void) \ +{ \ + name##_thr_keycreated = \ + (thr_keycreate(&name##_key, name##_free) == 0); \ +} \ +\ +struct name * \ +__##name##_init(void) \ +{ \ + struct name *he; \ + \ + if (thr_main() != 0) \ + return (&name); \ + if (thr_once(&name##_init_once, name##_keycreate) != 0 || \ + !name##_thr_keycreated) \ + return (NULL); \ + if ((he = thr_getspecific(name##_key)) != NULL) \ + return (he); \ + if ((he = calloc(1, sizeof(*he))) == NULL) \ + return (NULL); \ + if (thr_setspecific(name##_key, he) == 0) \ + return (he); \ + free(he); \ + return (NULL); \ +} + #define _MAXALIASES 35 #define _MAXLINELEN 1024 #define _MAXADDRS 35 #define _HOSTBUFSIZE (8 * 1024) #define _NETBUFSIZE 1025 -struct __res_state; - struct hostent_data { uint32_t host_addr[4]; /* IPv4 or IPv6 */ char *h_addr_ptrs[_MAXADDRS + 1]; @@ -45,7 +78,6 @@ struct hostent_data { char hostbuf[_HOSTBUFSIZE]; FILE *hostf; int stayopen; - struct __res_state *res; #ifdef YP char *yp_domain; #endif @@ -86,50 +118,44 @@ struct servent_data { struct hostdata { struct hostent host; - struct hostent_data data; + char data[sizeof(struct hostent_data)]; }; struct netdata { struct netent net; - struct netent_data data; + char data[sizeof(struct netent_data)]; }; struct protodata { struct protoent proto; - struct protoent_data data; + char data[sizeof(struct protoent_data)]; }; struct servdata { struct servent serv; - struct servent_data data; + char data[sizeof(struct servent_data)]; }; -#define endhostent_r __endhostent_r -#define endnetent_r __endnetent_r -#define endprotoent_r __endprotoent_r -#define endservent_r __endservent_r -#define gethostbyaddr_r __gethostbyaddr_r -#define gethostbyname_r __gethostbyname_r -#define gethostbyname2_r __gethostbyname2_r -#define gethostent_r __gethostent_r -#define getnetbyaddr_r __getnetbyaddr_r -#define getnetbyname_r __getnetbyname_r -#define getnetent_r __getnetent_r -#define getprotobyname_r __getprotobyname_r -#define getprotobynumber_r __getprotobynumber_r -#define getprotoent_r __getprotoent_r -#define getservbyname_r __getservbyname_r -#define getservbyport_r __getservbyport_r -#define getservent_r __getservent_r -#define sethostent_r __sethostent_r -#define setnetent_r __setnetent_r -#define setprotoent_r __setprotoent_r -#define setservent_r __setservent_r - struct hostdata *__hostdata_init(void); +struct hostent *__hostent_init(void); +struct hostent_data *__hostent_data_init(void); struct netdata *__netdata_init(void); +struct netent_data *__netent_data_init(void); struct protodata *__protodata_init(void); +struct protoent_data *__protoent_data_init(void); struct servdata *__servdata_init(void); +struct servent_data *__servent_data_init(void); +int __copy_hostent(struct hostent *, struct hostent *, char *, size_t); +int __copy_netent(struct netent *, struct netent *, char *, size_t); +int __copy_protoent(struct protoent *, struct protoent *, char *, size_t); +int __copy_servent(struct servent *, struct servent *, char *, size_t); + +void __endprotoent_p(struct protoent_data *); +void __endservent_p(struct servent_data *); +int __getprotoent_p(struct protoent *, struct protoent_data *); +int __getservent_p(struct servent *, struct servent_data *); +void __setprotoent_p(int, struct protoent_data *); +void __setservent_p(int, struct servent_data *); void _endhostdnsent(void); void _endhosthtent(struct hostent_data *); void _endnetdnsent(void); @@ -142,31 +168,5 @@ void _sethostdnsent(int); void _sethosthtent(int, struct hostent_data *); void _setnetdnsent(int); void _setnethtent(int, struct netent_data *); -void endhostent_r(struct hostent_data *); -void endnetent_r(struct netent_data *); -void endprotoent_r(struct protoent_data *); -void endservent_r(struct servent_data *); -int gethostbyaddr_r(const char *, int, int, struct hostent *, - struct hostent_data *); -int gethostbyname_r(const char *, struct hostent *, struct hostent_data *); -int gethostbyname2_r(const char *, int, struct hostent *, - struct hostent_data *); -int gethostent_r(struct hostent *, struct hostent_data *); -int getnetbyaddr_r(uint32_t addr, int af, struct netent *, - struct netent_data *); -int getnetbyname_r(const char *, struct netent *, struct netent_data *); -int getnetent_r(struct netent *, struct netent_data *); -int getprotobyname_r(const char *, struct protoent *, struct protoent_data *); -int getprotobynumber_r(int, struct protoent *, struct protoent_data *); -int getprotoent_r(struct protoent *, struct protoent_data *); -int getservbyname_r(const char *, const char *, struct servent *, - struct servent_data *); -int getservbyport_r(int, const char *, struct servent *, - struct servent_data *); -int getservent_r(struct servent *, struct servent_data *); -void sethostent_r(int, struct hostent_data *); -void setnetent_r(int, struct netent_data *); -void setprotoent_r(int, struct protoent_data *); -void setservent_r(int, struct servent_data *); #endif /* _NETDB_PRIVATE_H_ */ |