diff options
Diffstat (limited to 'contrib/bind/lib/irs')
55 files changed, 3083 insertions, 805 deletions
diff --git a/contrib/bind/lib/irs/Makefile b/contrib/bind/lib/irs/Makefile index 4784ccf..0c4e46d 100644 --- a/contrib/bind/lib/irs/Makefile +++ b/contrib/bind/lib/irs/Makefile @@ -13,7 +13,7 @@ # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS # SOFTWARE. -# $Id: Makefile,v 8.21 2000/12/23 08:02:59 vixie Exp $ +# $Id: Makefile,v 8.24 2001/08/14 05:58:07 marka Exp $ # these are only appropriate for BSD 4.4 or derivatives, and are used in # development. normal builds will be done in the top level directory and @@ -83,7 +83,7 @@ ${LIBBIND}: ${OBJS} ${RANLIB} ${LIBBIND} .c.${O}: - if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + mkdir ${THREADED} 2> /dev/null || test -d ${THREADED} -a -w ${THREADED} -(${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \ -o ${THREADED}/$*.${O} ; \ ${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} \ diff --git a/contrib/bind/lib/irs/dns.c b/contrib/bind/lib/irs/dns.c index 66bdbf5..3feed26 100644 --- a/contrib/bind/lib/irs/dns.c +++ b/contrib/bind/lib/irs/dns.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns.c,v 1.15 2000/02/28 07:52:16 vixie Exp $"; +static const char rcsid[] = "$Id: dns.c,v 1.16 2001/05/29 05:48:26 marka Exp $"; #endif /* @@ -59,6 +59,8 @@ irs_dns_acc(const char *options) { struct irs_acc *acc; struct dns_p *dns; + UNUSED(options); + if (!(acc = memget(sizeof *acc))) { errno = ENOMEM; return (NULL); diff --git a/contrib/bind/lib/irs/dns_gr.c b/contrib/bind/lib/irs/dns_gr.c index 64cbe9b..a622345 100644 --- a/contrib/bind/lib/irs/dns_gr.c +++ b/contrib/bind/lib/irs/dns_gr.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns_gr.c,v 1.19 1999/01/18 07:46:48 vixie Exp $"; +static const char rcsid[] = "$Id: dns_gr.c,v 1.20 2001/05/29 05:48:27 marka Exp $"; #endif /* @@ -146,6 +146,9 @@ gr_close(struct irs_gr *this) { static struct group * gr_next(struct irs_gr *this) { + + UNUSED(this); + return (NULL); } @@ -164,6 +167,9 @@ gr_bygid(struct irs_gr *this, gid_t gid) { static void gr_rewind(struct irs_gr *this) { + + UNUSED(this); + /* NOOP */ } @@ -171,6 +177,11 @@ static int gr_list(struct irs_gr *this, const char *name, gid_t basegid, gid_t *groups, int *ngroups) { + UNUSED(this); + UNUSED(name); + UNUSED(basegid); + UNUSED(groups); + *ngroups = 0; /* There's some way to do this in Hesiod. */ return (-1); @@ -178,6 +189,8 @@ gr_list(struct irs_gr *this, const char *name, static void gr_minimize(struct irs_gr *this) { + + UNUSED(this); /* NOOP */ } diff --git a/contrib/bind/lib/irs/dns_ho.c b/contrib/bind/lib/irs/dns_ho.c index 8b2df77..e340f02 100644 --- a/contrib/bind/lib/irs/dns_ho.c +++ b/contrib/bind/lib/irs/dns_ho.c @@ -52,7 +52,7 @@ /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns_ho.c,v 1.28 2000/04/20 07:47:54 vixie Exp $"; +static const char rcsid[] = "$Id: dns_ho.c,v 1.33 2001/10/05 04:30:21 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports. */ @@ -94,11 +94,7 @@ static const char rcsid[] = "$Id: dns_ho.c,v 1.28 2000/04/20 07:47:54 vixie Exp #define MAXALIASES 35 #define MAXADDRS 35 -#if PACKETSZ > 1024 -#define MAXPACKET PACKETSZ -#else -#define MAXPACKET 1024 -#endif +#define MAXPACKET (1024*64) #define BOUNDS_CHECK(ptr, count) \ if ((ptr) + (count) > eom) { \ @@ -106,6 +102,26 @@ static const char rcsid[] = "$Id: dns_ho.c,v 1.28 2000/04/20 07:47:54 vixie Exp continue; \ } else (void)0 +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +struct dns_res_target { + struct dns_res_target *next; + querybuf qbuf; /* query buffer */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer buffer */ + int qclass, qtype; /* class and type of query */ + int action; /* condition whether query is really issued */ + char qname[MAXDNAME +1]; /* domain name */ +#if 0 + int n; /* result length */ +#endif +}; +enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE}; +enum {RESQRY_SUCCESS, RESQRY_FAIL}; + struct pvt { struct hostent host; char * h_addr_ptrs[MAXADDRS + 1]; @@ -141,6 +157,8 @@ static struct __res_state * ho_res_get(struct irs_ho *this); static void ho_res_set(struct irs_ho *this, struct __res_state *res, void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); static void map_v4v6_hostent(struct hostent *hp, char **bp, int *len); @@ -148,7 +166,20 @@ static void addrsort(res_state, char **, int); static struct hostent * gethostans(struct irs_ho *this, const u_char *ansbuf, int anslen, const char *qname, int qtype, - int af, int size); + int af, int size, + struct addrinfo **ret_aip, + const struct addrinfo *pai); +static int add_hostent(struct pvt *pvt, char *bp, char **hap, + struct addrinfo *ai); +static const u_char * ar_head(const u_char *, int, const u_char *, + const u_char *, struct pvt *, + int (*)(const char *)); +static struct addrinfo * a6_expand(const u_char *, const u_char *, int, + const u_char *, const u_char *, + const struct in6_addr *, int, + const struct addrinfo *, + struct pvt *, int (*)(const char *), int *); +static const char *dname_subst(const char *, const char *, const char *); static int init(struct irs_ho *this); /* Exports. */ @@ -158,6 +189,8 @@ irs_dns_ho(struct irs_acc *this) { struct irs_ho *ho; struct pvt *pvt; + UNUSED(this); + if (!(pvt = memget(sizeof *pvt))) { errno = ENOMEM; return (NULL); @@ -180,6 +213,7 @@ irs_dns_ho(struct irs_acc *this) { ho->minimize = ho_minimize; ho->res_get = ho_res_get; ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; return (ho); } @@ -214,24 +248,50 @@ ho_byname(struct irs_ho *this, const char *name) { } static struct hostent * -ho_byname2(struct irs_ho *this, const char *name, int af) { +ho_byname2(struct irs_ho *this, const char *name, int af) +{ struct pvt *pvt = (struct pvt *)this->private; - int n, size, type; - u_char buf[MAXPACKET]; + struct hostent *hp = NULL; + int n, size; char tmp[NS_MAXDNAME]; const char *cp; + struct addrinfo ai; + struct dns_res_target q, q2, *p; + int querystate = RESQRY_FAIL; if (init(this) == -1) return (NULL); + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + switch (af) { case AF_INET: size = INADDRSZ; - type = T_A; + q.qclass = C_IN; + q.qtype = T_A; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.action = RESTGT_DOALWAYS; break; case AF_INET6: size = IN6ADDRSZ; - type = T_AAAA; + q.qclass = C_IN; + q.qtype = ns_t_a6; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.next = &q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q.action = RESTGT_IGNORE; + else +#endif + q.action = RESTGT_DOALWAYS; + q2.qclass = C_IN; + q2.qtype = T_AAAA; + q2.answer = q2.qbuf.buf; + q2.anslen = sizeof(q2.qbuf); + q2.action = RESTGT_AFTERFAILURE; break; default: RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); @@ -248,30 +308,62 @@ ho_byname2(struct irs_ho *this, const char *name, int af) { tmp, sizeof tmp))) name = cp; - if ((n = res_nsearch(pvt->res, name, C_IN, type, - buf, sizeof buf)) < 0) - return (NULL); - return (gethostans(this, buf, n, name, type, af, size)); + for (p = &q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + if ((hp = gethostans(this, p->answer, n, name, p->qtype, + af, size, NULL, + (const struct addrinfo *)&ai)) != NULL) + return(hp); /* no more loop is necessary */ + + querystate = RESQRY_FAIL; + continue; + } + + return(hp); /* should be NULL */ } static struct hostent * -ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) +{ struct pvt *pvt = (struct pvt *)this->private; const u_char *uaddr = addr; - char qbuf[MAXDNAME+1], *qp; - u_char buf[MAXPACKET]; + char *qp; struct hostent *hp; + struct addrinfo ai; + struct dns_res_target q, q2, *p; int n, size; + int querystate = RESQRY_FAIL; if (init(this) == -1) return (NULL); + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + if (af == AF_INET6 && len == IN6ADDRSZ && (!memcmp(uaddr, mapped, sizeof mapped) || (!memcmp(uaddr, tunnelled, sizeof tunnelled) && memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) { /* Unmap. */ - addr = (char *)addr + sizeof mapped; + addr = (const char *)addr + sizeof mapped; uaddr += sizeof mapped; af = AF_INET; len = INADDRSZ; @@ -279,9 +371,31 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { switch (af) { case AF_INET: size = INADDRSZ; + q.qclass = C_IN; + q.qtype = T_PTR; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.action = RESTGT_DOALWAYS; break; case AF_INET6: size = IN6ADDRSZ; + q.qclass = C_IN; + q.qtype = T_PTR; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.next = &q2; + if ((pvt->res->options & RES_NO_BITSTRING) != 0) + q.action = RESTGT_IGNORE; + else + q.action = RESTGT_DOALWAYS; + q2.qclass = C_IN; + q2.qtype = T_PTR; + q2.answer = q2.qbuf.buf; + q2.anslen = sizeof(q2.qbuf); + if ((pvt->res->options & RES_NO_NIBBLE) != 0) + q2.action = RESTGT_IGNORE; + else + q2.action = RESTGT_AFTERFAILURE; break; default: errno = EAFNOSUPPORT; @@ -295,49 +409,93 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { } switch (af) { case AF_INET: - (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + qp = q.qname; + (void) sprintf(qp, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff), (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff)); break; case AF_INET6: - qp = qbuf; - for (n = IN6ADDRSZ - 1; n >= 0; n--) { - qp += SPRINTF((qp, "%x.%x.", - uaddr[n] & 0xf, - (uaddr[n] >> 4) & 0xf)); + if (q.action != RESTGT_IGNORE) { + qp = q.qname; + qp += SPRINTF((qp, "\\[x")); + for (n = 0; n < IN6ADDRSZ; n++) + qp += SPRINTF((qp, "%02x", uaddr[n])); + SPRINTF((qp, "/128].%s", + res_get_bitstringsuffix(pvt->res))); + } + if (q2.action != RESTGT_IGNORE) { + qp = q2.qname; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + } + strcpy(qp, res_get_nibblesuffix(pvt->res)); } - strcpy(qp, "ip6.int"); break; default: abort(); } - n = res_nquery(pvt->res, qbuf, C_IN, T_PTR, buf, sizeof buf); - if (n < 0) - return (NULL); - hp = gethostans(this, buf, n, qbuf, T_PTR, af, size); - if (!hp) - return (NULL); /* H_ERRNO was set by gethostans() */ - memcpy(pvt->host_addr, addr, len); - pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; - pvt->h_addr_ptrs[1] = NULL; - if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) { - map_v4v6_address((char*)pvt->host_addr, (char*)pvt->host_addr); - pvt->host.h_addrtype = AF_INET6; - pvt->host.h_length = IN6ADDRSZ; - } - RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); - return (hp); + + for (p = &q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nquery(pvt->res, p->qname, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + hp = gethostans(this, p->answer, n, p->qname, T_PTR, af, size, + NULL, (const struct addrinfo *)&ai); + if (!hp) { + querystate = RESQRY_FAIL; + continue; + } + + memcpy(pvt->host_addr, addr, len); + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + pvt->host.h_addrtype = AF_INET6; + pvt->host.h_length = IN6ADDRSZ; + } + + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); /* no more loop is necessary. */ + } + + return(NULL); /* H_ERRNO was set by subroutines */ } static struct hostent * ho_next(struct irs_ho *this) { + + UNUSED(this); + return (NULL); } static void ho_rewind(struct irs_ho *this) { + + UNUSED(this); + /* NOOP */ } @@ -367,6 +525,495 @@ ho_res_get(struct irs_ho *this) { return (pvt->res); } +/* XXX */ +extern struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int n; + char tmp[NS_MAXDNAME]; + const char *cp; + struct dns_res_target q, q2, q3, *p; + struct addrinfo sentinel, *cur; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&q3, 0, sizeof(q3)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch (pai->ai_family) { + case AF_UNSPEC: + /* prefer IPv6 */ + q.qclass = C_IN; + q.qtype = ns_t_a6; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.next = &q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q.action = RESTGT_IGNORE; + else +#endif + q.action = RESTGT_DOALWAYS; + q2.qclass = C_IN; + q2.qtype = T_AAAA; + q2.answer = q2.qbuf.buf; + q2.anslen = sizeof(q2.qbuf); + q2.next = &q3; + /* try AAAA only when A6 query fails */ + q2.action = RESTGT_AFTERFAILURE; + q3.qclass = C_IN; + q3.qtype = T_A; + q3.answer = q3.qbuf.buf; + q3.anslen = sizeof(q3.qbuf); + q3.action = RESTGT_DOALWAYS; + break; + case AF_INET: + q.qclass = C_IN; + q.qtype = T_A; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.action = RESTGT_DOALWAYS; + break; + case AF_INET6: + q.qclass = C_IN; + q.qtype = ns_t_a6; + q.answer = q.qbuf.buf; + q.anslen = sizeof(q.qbuf); + q.next = &q2; +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) + q.action = RESTGT_IGNORE; + else +#endif + q.action = RESTGT_DOALWAYS; + q2.qclass = C_IN; + q2.qtype = T_AAAA; + q2.answer = q2.qbuf.buf; + q2.anslen = sizeof(q2.qbuf); + q2.action = RESTGT_AFTERFAILURE; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* better error? */ + return(NULL); + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + (void)gethostans(this, p->answer, n, name, p->qtype, + pai->ai_family, /* XXX: meaningless */ + 0, &ai, pai); + if (ai) { + querystate = RESQRY_SUCCESS; + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + else + querystate = RESQRY_FAIL; + } + + return(sentinel.ai_next); +} + +static const u_char * +ar_head(cp, count, msg, eom, pvt, name_ok) + const u_char *cp, *msg, *eom; + int count; + struct pvt *pvt; + int (*name_ok)(const char *); +{ + int n; + char buf[1024]; /* XXX */ + + while (count-- > 0 && cp < eom) { + n = dn_expand(msg, eom, cp, buf, sizeof(buf)); + if (n < 0 || !maybe_ok(pvt->res, buf, name_ok)) + goto end; + cp += n; /* name */ + if (cp + 3 * INT16SZ + INT32SZ >= eom) + goto end; + cp += INT16SZ; /* type */ + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += n + INT16SZ; /* len */ + } + return(cp); + + end: + return(eom); /* XXX */ +} + +/* XXX: too many arguments */ +static struct addrinfo * +a6_expand(const u_char *ansbuf, const u_char *a6p, + int a6len, const u_char *arp, const u_char *eom, + const struct in6_addr *in6, int plen, const struct addrinfo *pai, + struct pvt *pvt, int (*name_ok)(const char *), int *errorp) +{ + struct in6_addr a; + int n, pbyte, plen1, pbyte1, error = 0; + const u_char *cp; + struct addrinfo sentinel, *cur; + char pname[1024], buf[1024]; /* XXX */ + + *errorp = NETDB_SUCCESS; + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + /* + * Validate A6 parameters. + */ + if (a6len == 0) { /* an A6 record must contain at least 1 byte. */ + error = NO_RECOVERY; + goto bad; + } + /* prefix length check. */ + if ((plen1 = *a6p) > 128) { + error = NO_RECOVERY; + goto bad; + } + if (plen1 > plen) { + /* + * New length must not be greater than old one. + * Ignore the record as specified in RFC 2874 + * Section 3.1.2. + */ + return(NULL); /* just ignore. */ + } + /* boundary check for new plen and prefix addr */ + pbyte1 = (plen1 & ~7) / 8; + if ((int)sizeof(struct in6_addr) - pbyte1 > a6len - 1) { + error = NO_RECOVERY; + goto bad; + } + + /* + * merge the new prefix portion. + * <--- plen(bits) ---> + * <--- pbyte ---><-b-> + * 000000000000000pppppxxxxxxxxxxx(= in6, 0: unknown, x: known, p: pad) + * PP++++++++(+ should be merged. P: padding, must be 0) + * <-- plen1--> + * <-pbyte1-> + * ^a6p+1 + * The result should be: + * 0000000000PP++++++++xxxxxxxxxxx(= a) + */ + pbyte = (plen & ~7) / 8; + a = *in6; + if (pbyte > pbyte1) { + /* N.B. the case of "pbyte1 == 128" is implicitly excluded. */ + int b = plen % 8; /* = the length of "pp..." above */ + u_char c_hi, c_lo; + + memcpy(&a.s6_addr[pbyte1], a6p + 1, pbyte - pbyte1); + if (b > 0) { + c_hi = a6p[pbyte - pbyte1 + 1]; + c_lo = in6->s6_addr[pbyte]; + a.s6_addr[pbyte] = + (c_hi & (0xff << (8 - b))) | + ((0x00ff >> b) & c_lo); + } + } + +#if 0 /* for debug */ + if ((pvt->res->options & RES_DEBUG) != 0) { + u_char ntopbuf[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &a, ntopbuf, sizeof(ntopbuf)); + printf("a6_expand: %s\\%d\n", ntopbuf, plen1); + } +#endif + + if (plen1 == 0) { + /* Here is the end of A6 chain. make addrinfo, then return. */ + return(addr2addrinfo(pai, (const char *)&a)); + } + + /* + * Expand the new prefix name. Since the prefix name must not be + * compressed (RFC 2874 Section 3.1.1), we could use ns_name_ntop() + * here if it had a stricter boundary check. + */ + cp = a6p + 1 + (sizeof(*in6) - pbyte1); + n = dn_expand(ansbuf, eom, cp, pname, sizeof(pname)); + if (n < 0 || !maybe_ok(pvt->res, pname, name_ok)) { + error = NO_RECOVERY; + goto bad; + } + if (cp + n != a6p + a6len) { /* length mismatch */ + error = NO_RECOVERY; + goto bad; + } + + /* + * we need (more) additional section records, but no one is + * available, which possibly means a malformed answer. + */ + if (arp == NULL) { + error = NO_RECOVERY; /* we can't resolve the chain. */ + goto bad; + } + + /* + * Loop thru the rest of the buffer, searching for the next A6 record + * that has the same owner name as the prefix name. If found, then + * recursively call this function to expand the whole A6 chain. + */ + plen = plen1; + for (cp = arp; cp != NULL && cp < eom; cp += n) { + int class, type; + + n = dn_expand(ansbuf, eom, cp, buf, sizeof(buf)); + if (n < 0 || !maybe_ok(pvt->res, buf, name_ok)) { + error = NO_RECOVERY; + goto bad; + } + cp += n; /* name */ + if (cp + 3 * INT16SZ + INT32SZ > eom) { + error = NO_RECOVERY; + goto bad; + } + type = ns_get16(cp); + cp += INT16SZ; /* type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /* len */ + if (cp + n > eom) { + error = NO_RECOVERY; + goto bad; + } + if (class != C_IN || type != ns_t_a6) { + /* we are only interested in A6 records. skip others */ + continue; + } + + if (ns_samename(buf, pname) != 1) { + continue; + } + + /* Proceed to the next record in the chain. */ + cur->ai_next = a6_expand(ansbuf, cp, n, cp + n, eom, + (const struct in6_addr *)&a, + plen, pai, pvt, name_ok, &error); + if (error != NETDB_SUCCESS) + goto bad; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + return(sentinel.ai_next); + + bad: + *errorp = error; + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return(NULL); +} + +static const char * +dname_subst(const char *qname0, const char *owner0, const char *target) { + char owner[MAXDNAME]; + static char qname[MAXDNAME]; + const char blabelhead[] = "\\[x"; /* we can assume hex strings */ + int qlen, olen; + int bufsiz = sizeof(qname); + + /* make local copies, which are canonicalized. */ + if (ns_makecanon(qname0, qname, sizeof(qname)) < 0 || + ns_makecanon(owner0, owner, sizeof(owner)) < 0) + return(NULL); + qlen = strlen(qname); + olen = strlen(owner); + /* from now on, do not refer to qname0 nor owner0. */ + + /* + * check if QNAME is a subdomain of OWNER. + * XXX: currently, we only handle the following two cases: + * (A) none of the labels are bitlabels, or + * (B) both of the head labels are bitlabels (and the following + * labels are NOT bitlabels). + * If we pass the check, then subtract the remaining part from QNAME. + * ex. (A) qname=www.foo.com,owner=foo.com => new qname=www. + * (B) qname=\[x3ffe0501/32].foo.com,owner=\[x3ffe/16].foo.com + * => new qname=\[x0501/16]. + */ + if (ns_samedomain(qname, owner)) { /* check (A) */ + /* at this point, qlen must not be smaller than olen */ + qname[qlen - olen] = 0; + bufsiz -= (qlen - olen); + } else { /* check (B) */ + char *parent0, *parent1; + /* the following 3 have enough size to store 1 bitlabel */ + u_char qlabel[64], olabel[64], newlabel[64]; + int qlabellen, olabellen; + + if (strncmp(qname, blabelhead, 3) != 0 || + strncmp(owner, blabelhead, 3) != 0) + return(NULL); + /* + * Both two begin with bitlabels. The succeeding parts + * must exact match. + */ + if ((parent0 = strchr(qname, '.')) == NULL || + (parent1 = strchr(owner, '.')) == NULL) + return(NULL); + + /* ns_samename allows names to begin with '.' */ + if (ns_samename(parent0, parent1) != 1) + return(NULL); + + /* cut the upper domain parts off. */ + *(parent0 + 1) = 0; + *(parent1 + 1) = 0; + /* convert the textual form into binary one. */ + if (ns_name_pton(qname, qlabel, sizeof(qlabel)) < 0 || + ns_name_pton(owner, olabel, sizeof(olabel)) < 0) + return(NULL); + if ((qlabellen = *(qlabel + 1)) == 0) + qlabellen = 256; + if ((olabellen = *(olabel + 1)) == 0) + olabellen = 256; + if (olabellen > qlabellen) + return(NULL); /* owner does not contain qname. */ + else { + int qplen = (qlabellen + 7) / 8; + int oplen = (olabellen + 7) / 8; + int sft = olabellen % 8; + int nllen, n; + u_char *qp, *op, *np; + + /* skip ELT and Count. */ + qp = qlabel + 2; + op = olabel + 2; + + /* check if olabel is a "subdomain" of qlabel. */ + if (memcmp(qp, op, oplen - 1) != 0) + return(NULL); + if (sft > 0) { + /* compare trailing bits (between 1 and 7) */ + if ((qp[qplen - 1] & (0xff << sft)) != + op[qplen - 1]) + return(NULL); + } + + /* OK, get remaining bits from qlabel. */ + np = newlabel; + if (olabellen == qlabellen) { + /* + * Two names (including bitlabels) are exactly + * same. Discard the whole names. + * XXX: ns_samename() above should exclude + * this case... + */ + qname[0] = 0; + goto maketarget; + } + *np++ = 0x41; /* XXX hardcoding */ + *np++ = nllen = (qlabellen - olabellen); + if (sft == 0) { + /* + * No alignment issue. can just use memcpy. + * Note that the "else" part below contains + * this case. We separate the two cases just + * for efficiency. + * We assume that ns_name_pton above ensures + * QP does not contain trailing garbages. + */ + memcpy(np, qp + oplen, qplen - oplen); + np += qplen - oplen; + *np = 0; + } else { + /* + * copy the lower (8-SFT) bits of QP to the + * upper (8-SFT) bits of NP, then copy the + * upper SFT bits of QP+1 to the lower SFT bits + * of NP, and so on... + * if QP is xxxyyyyy zzzwww..., then + * NP would be yyyyyzzz ... + * Again, we assume QP does not contain + * trailing garbages. + */ + qp += (oplen - 1); + while (nllen > 0) { + *np = (*qp << sft) & 0xff; + if ((nllen -= (8 - sft)) <= 0) + break; /* done */ + qp++; + *np |= ((*qp >> sft) & 0xff); + np++; + nllen -= sft; + } + *++np = 0; + } + + /* + * make a new bitlabel with the remaining bits. + * Note that there's no buffer boundary issue, since + * qlabel, olabel, and newlabel all have the same size. + * ns_name_ntop() must not return 0, since we have + * a non-empty bitlabel. + */ + if ((n = ns_name_ntop(newlabel, qname, sizeof(qname))) + <= 0) + return(NULL); + bufsiz -= n; + if (qname[n - 1] != '.') { /* XXX no trailing dot */ + qname[n - 1] = '.'; + qname[n] = 0; + bufsiz--; + } + + } + } + + maketarget: + /* + * Finally, append the remaining part (maybe empty) to the new target. + */ + if (bufsiz < (int)strlen(target)) /* bufsiz takes care of the \0. */ + return(NULL); + strcat(qname, target); + + return((const char *)qname); +} + static void ho_res_set(struct irs_ho *this, struct __res_state *res, void (*free_res)(void *)) { @@ -386,23 +1033,37 @@ ho_res_set(struct irs_ho *this, struct __res_state *res, static struct hostent * gethostans(struct irs_ho *this, const u_char *ansbuf, int anslen, const char *qname, int qtype, - int af, int size) + int af, int size, /* meaningless for addrinfo cases */ + struct addrinfo **ret_aip, const struct addrinfo *pai) { struct pvt *pvt = (struct pvt *)this->private; int type, class, buflen, ancount, qdcount, n, haveanswer, had_error; + int error = NETDB_SUCCESS, arcount; int (*name_ok)(const char *); const HEADER *hp; const u_char *eom; + const u_char *eor; const u_char *cp; - const char *tname, **tap; + const char *tname; + const char *hname; char *bp, **ap, **hap; char tbuf[MAXDNAME+1]; + struct addrinfo sentinel, *cur, ai; + const u_char *arp = NULL; + + if (pai == NULL) abort(); + if (ret_aip != NULL) + *ret_aip = NULL; + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; tname = qname; eom = ansbuf + anslen; switch (qtype) { + case ns_t_a6: case T_A: case T_AAAA: + case T_ANY: /* use T_ANY only for T_A/T_AAAA lookup */ name_ok = res_hnok; break; case T_PTR: @@ -414,7 +1075,7 @@ gethostans(struct irs_ho *this, pvt->host.h_addrtype = af; pvt->host.h_length = size; - pvt->host.h_name = NULL; + hname = pvt->host.h_name = NULL; /* * Find first satisfactory answer. @@ -423,9 +1084,10 @@ gethostans(struct irs_ho *this, RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } - hp = (HEADER *)ansbuf; + hp = (const HEADER *)ansbuf; ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); + arcount = ntohs(hp->arcount); bp = pvt->hostbuf; buflen = sizeof pvt->hostbuf; cp = ansbuf + HFIXEDSZ; @@ -443,7 +1105,8 @@ gethostans(struct irs_ho *this, RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } - if (qtype == T_A || qtype == T_AAAA) { + if (qtype == T_A || qtype == T_AAAA || + qtype == ns_t_a6 || qtype == T_ANY) { /* res_nsend() has already verified that the query name is the * same as the one we sent; this just gets the expanded name * (i.e., with the succeeding search-domain tacked on). @@ -454,9 +1117,10 @@ gethostans(struct irs_ho *this, return (NULL); } pvt->host.h_name = bp; + hname = bp; bp += n; buflen -= n; - /* The qname can be abbreviated, but h_name is now absolute. */ + /* The qname can be abbreviated, but hname is now absolute. */ qname = pvt->host.h_name; } ap = pvt->host_aliases; @@ -486,10 +1150,12 @@ gethostans(struct irs_ho *this, cp += n; continue; } - if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { + eor = cp + n; + if ((qtype == T_A || qtype == T_AAAA || qtype == ns_t_a6 || + qtype == T_ANY) && type == T_CNAME) { if (ap >= &pvt->host_aliases[MAXALIASES-1]) continue; - n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf); + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { had_error++; continue; @@ -508,17 +1174,78 @@ gethostans(struct irs_ho *this, } strcpy(bp, tbuf); pvt->host.h_name = bp; + hname = bp; bp += n; buflen -= n; continue; } + if (type == ns_t_dname) { + const char *t0, *t; + + /* + * just replace the query target; do not update the + * alias list. (Or should we?) + */ + t0 = (qtype == T_PTR) ? tname : hname; + + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof(tbuf)); + if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { + had_error++; + continue; + } +#ifdef RES_USE_DNAME + if ((pvt ->res->options & RES_USE_DNAME) == 0) { + cp += n; + continue; + } +#endif + if ((t = dname_subst(t0, bp, tbuf)) == NULL) { + cp += n; + continue; + } +#if 0 /* for debug */ + if ((pvt->res->options & RES_DEBUG) != 0) { + printf("DNAME owner=%s, target=%s, next=%s\n", + bp, tbuf, t); + } +#endif + cp += n; + + n = strlen(t) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, t); + if (qtype == T_PTR) + tname = bp; + else + hname = bp; + bp += n; + buflen -= n; + + continue; + } if (qtype == T_PTR && type == T_CNAME) { - n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf); + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { had_error++; continue; } cp += n; +#ifdef RES_USE_DNAME + if ((pvt->res->options & RES_USE_DNAME) != 0) +#endif + { + /* + * We may be able to check this regardless + * of the USE_DNAME bit, but we add the check + * for now since the DNAME support is + * experimental. + */ + if (ns_samename(tname, bp) != 1) + continue; + } /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ if (n > buflen) { @@ -531,25 +1258,38 @@ gethostans(struct irs_ho *this, buflen -= n; continue; } - if (type != qtype) { + if (qtype == T_ANY) { + if (!(type == T_A || type == T_AAAA || + type == ns_t_a6)) { + cp += n; + continue; + } + } else if (type != qtype) { cp += n; continue; } switch (type) { case T_PTR: + if (ret_aip != NULL) { + /* addrinfo never needs T_PTR */ + cp += n; + continue; + } if (ns_samename(tname, bp) != 1) { cp += n; continue; } - n = dn_expand(ansbuf, eom, cp, bp, buflen); + n = dn_expand(ansbuf, eor, cp, bp, buflen); if (n < 0 || !maybe_hnok(pvt->res, bp) || n >= MAXHOSTNAMELEN) { had_error++; break; } cp += n; - if (!haveanswer) + if (!haveanswer) { pvt->host.h_name = bp; + hname = bp; + } else if (ap < &pvt->host_aliases[MAXALIASES-1]) *ap++ = bp; else @@ -560,16 +1300,91 @@ gethostans(struct irs_ho *this, buflen -= n; } break; + case ns_t_a6: { + struct in6_addr in6; + struct addrinfo ai; + +#ifdef RES_USE_A6 + if ((pvt->res->options & RES_USE_A6) == 0) { + cp += n; + continue; + } +#endif + + if (ns_samename(hname, bp) != 1) { + cp += n; + continue; + } + + /* + * search for the top of the additional section. + * once found, keep it for the case where we have + * more than one A6 record. + * XXX: however, we may not need this part. + */ + if (arp == NULL && arcount > 0) { + int nscount = ntohs(hp->nscount); + + arp = ar_head(cp + n, nscount + ancount - 1, + ansbuf, eom, pvt, name_ok); + } + + /* recursively collect the whole A6 chain */ + ai = *pai; /* XXX: we can't override constant pai */ + ai.ai_family = AF_INET6; + memset(&in6, 0, sizeof(in6)); /* just for safety */ + cur->ai_next = a6_expand(ansbuf, cp, n, arp, eom, + &in6, 128, + (const struct addrinfo *)&ai, + pvt, name_ok, &error); + if (error != NETDB_SUCCESS) { +#ifdef DEBUG + /* in this case, cur->ai_next must be NULL. */ + if (cur->ai_next != NULL) + abort(); +#endif + had_error++; + continue; + } + + /* + * We don't bother even if cur->ai_next is NULL unless + * the expansion failed by a fatal error. The list + * can be NULL if the given A6 is incomplete, but we + * may have another complete A6 chain in this answer. + * See the last paragraph of RFC 2874 Section 3.1.4. + */ + if (cur->ai_next == NULL) { + cp += n; + continue; /* no error, no answer */ + } + goto convertinfo; + } /* FALLTHROUGH */ case T_A: case T_AAAA: - if (ns_samename(pvt->host.h_name, bp) != 1) { + if (ns_samename(hname, bp) != 1) { + cp += n; + continue; + } + if (type == T_A && n != INADDRSZ) { cp += n; continue; } - if (n != pvt->host.h_length) { + if (type == T_AAAA && n != IN6ADDRSZ) { cp += n; continue; } + + /* make addrinfo. don't overwrite constant PAI */ + ai = *pai; + ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET; + cur->ai_next = addr2addrinfo( + (const struct addrinfo *)&ai, + (const char *)cp); + if (cur->ai_next == NULL) + had_error++; + + convertinfo: /* convert addrinfo into hostent form */ if (!haveanswer) { int nn; @@ -580,34 +1395,44 @@ gethostans(struct irs_ho *this, continue; } pvt->host.h_name = bp; + hname = bp; bp += nn; buflen -= nn; } /* Ensure alignment. */ - bp += sizeof(align) - ((u_long)bp % sizeof(align)); + bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & + ~(sizeof(align) - 1)); /* Avoid overflows. */ if (bp + n >= &pvt->hostbuf[sizeof pvt->hostbuf]) { had_error++; continue; } - if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1]) { - cp += n; - continue; - } - /* Suppress duplicates. */ - for (tap = (const char **)pvt->h_addr_ptrs; - *tap != NULL; - tap++) - if (memcmp(*tap, cp, n) == 0) - break; - if (*tap != NULL) { - cp += n; - continue; + if (ret_aip) { /* need addrinfo. keep it. */ + while (cur && cur->ai_next) + cur = cur->ai_next; + } else if (cur->ai_next) { /* need hostent */ + struct addrinfo *aip = cur->ai_next; + + for (aip = cur->ai_next; aip; + aip = aip->ai_next) { + int m; + + m = add_hostent(pvt, bp, hap, aip); + if (m < 0) { + had_error++; + break; + } + if (m == 0) + continue; + if (hap < &pvt->h_addr_ptrs[MAXADDRS-1]) + hap++; + + bp += m; + } + + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; } - /* Store address. */ - memcpy(*hap++ = bp, cp, n); - *hap = NULL; - bp += n; cp += n; break; default: @@ -617,27 +1442,94 @@ gethostans(struct irs_ho *this, haveanswer++; } if (haveanswer) { - *ap = NULL; - - if (pvt->res->nsort && haveanswer > 1 && qtype == T_A) - addrsort(pvt->res, pvt->h_addr_ptrs, haveanswer); - if (!pvt->host.h_name) { - n = strlen(qname) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) - goto no_recovery; - strcpy(bp, qname); - pvt->host.h_name = bp; - bp += n; - buflen -= n; + if (ret_aip == NULL) { + *ap = NULL; + *hap = NULL; + + if (pvt->res->nsort && haveanswer > 1 && qtype == T_A) + addrsort(pvt->res, pvt->h_addr_ptrs, + haveanswer); + if (pvt->host.h_name == NULL) { + n = strlen(qname) + 1; /* for the \0 */ + if (n > buflen || n >= MAXHOSTNAMELEN) + goto no_recovery; + strcpy(bp, qname); + pvt->host.h_name = bp; + bp += n; + buflen -= n; + } + if (pvt->res->options & RES_USE_INET6) + map_v4v6_hostent(&pvt->host, &bp, &buflen); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); + } else { + if ((pai->ai_flags & AI_CANONNAME) != 0) { + if (pvt->host.h_name == NULL) { + sentinel.ai_next->ai_canonname = + strdup(qname); + } + else { + sentinel.ai_next->ai_canonname = + strdup(pvt->host.h_name); + } + } + *ret_aip = sentinel.ai_next; + return(NULL); } - if (pvt->res->options & RES_USE_INET6) - map_v4v6_hostent(&pvt->host, &bp, &buflen); - RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); - return (&pvt->host); } no_recovery: - RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); - return (NULL); + if (sentinel.ai_next) { + /* this should be impossible, but check it for safety */ + freeaddrinfo(sentinel.ai_next); + } + if (error == NETDB_SUCCESS) + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + else + RES_SET_H_ERRNO(pvt->res, error); + return(NULL); +} + +static int +add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai) +{ + int addrlen; + char *addrp; + const char **tap; + char *obp = bp; + + switch(ai->ai_addr->sa_family) { + case AF_INET6: + addrlen = IN6ADDRSZ; + addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; + break; + case AF_INET: + addrlen = INADDRSZ; + addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr; + break; + default: + return(-1); /* abort? */ + } + + /* Ensure alignment. */ + bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & + ~(sizeof(align) - 1)); + /* Avoid overflows. */ + if (bp + addrlen >= &pvt->hostbuf[sizeof pvt->hostbuf]) + return(-1); + if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1]) + return(0); /* fail, but not treat it as an error. */ + + /* Suppress duplicates. */ + for (tap = (const char **)pvt->h_addr_ptrs; + *tap != NULL; + tap++) + if (memcmp(*tap, addrp, addrlen) == 0) + break; + if (*tap != NULL) + return (0); + + memcpy(*hap = bp, addrp, addrlen); + return((bp + addrlen) - obp); } static void @@ -649,7 +1541,10 @@ map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) { hp->h_addrtype = AF_INET6; hp->h_length = IN6ADDRSZ; for (ap = hp->h_addr_list; *ap; ap++) { - int i = sizeof(align) - ((u_long)*bpp % sizeof(align)); + int i = (u_long)*bpp % sizeof(align); + + if (i != 0) + i = sizeof(align) - i; if (*lenp < (i + IN6ADDRSZ)) { /* Out of memory. Truncate address list here. */ diff --git a/contrib/bind/lib/irs/dns_nw.c b/contrib/bind/lib/irs/dns_nw.c index 66ef664..8e0e965 100644 --- a/contrib/bind/lib/irs/dns_nw.c +++ b/contrib/bind/lib/irs/dns_nw.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns_nw.c,v 1.19 1999/10/15 19:49:10 vixie Exp $"; +static const char rcsid[] = "$Id: dns_nw.c,v 1.21 2001/11/30 00:36:53 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports. */ @@ -56,11 +56,7 @@ static const char rcsid[] = "$Id: dns_nw.c,v 1.19 1999/10/15 19:49:10 vixie Exp #define MAXALIASES 35 -#if PACKETSZ > 1024 -#define MAXPACKET PACKETSZ -#else -#define MAXPACKET 1024 -#endif +#define MAXPACKET (64*1024) struct pvt { struct nwent net; @@ -109,6 +105,8 @@ irs_dns_nw(struct irs_acc *this) { struct irs_nw *nw; struct pvt *pvt; + UNUSED(this); + if (!(pvt = memget(sizeof *pvt))) { errno = ENOMEM; return (NULL); @@ -185,11 +183,15 @@ nw_byaddr(struct irs_nw *this, void *net, int len, int af) { static struct nwent * nw_next(struct irs_nw *this) { + + UNUSED(this); + return (NULL); } static void nw_rewind(struct irs_nw *this) { + UNUSED(this); /* NOOP */ } @@ -539,7 +541,7 @@ normalize_name(char *name) { /* Make lower case. */ for (t = name; *t; t++) - if (isascii(*t) && isupper(*t)) + if (isascii((unsigned char)*t) && isupper((unsigned char)*t)) *t = tolower(*t); /* Remove trailing dots. */ diff --git a/contrib/bind/lib/irs/dns_pr.c b/contrib/bind/lib/irs/dns_pr.c index 77c6a93..64de35a 100644 --- a/contrib/bind/lib/irs/dns_pr.c +++ b/contrib/bind/lib/irs/dns_pr.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns_pr.c,v 1.14 1999/09/04 22:06:14 vixie Exp $"; +static const char rcsid[] = "$Id: dns_pr.c,v 1.15 2001/05/29 05:48:31 marka Exp $"; #endif /* Imports */ @@ -152,17 +152,20 @@ pr_bynumber(struct irs_pr *this, int num) { static struct protoent * pr_next(struct irs_pr *this) { + UNUSED(this); errno = ENODEV; return (NULL); } static void pr_rewind(struct irs_pr *this) { + UNUSED(this); /* NOOP */ } static void pr_minimize(struct irs_pr *this) { + UNUSED(this); /* NOOP */ } @@ -201,7 +204,7 @@ parse_hes_list(struct irs_pr *this, char **hes_list) { /* Skip blank lines. */ p = cp; - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) p++; if (!*p) continue; @@ -213,14 +216,14 @@ parse_hes_list(struct irs_pr *this, char **hes_list) { p = pvt->prbuf; pvt->proto.p_name = p; - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) p++; if (!*p) continue; *p++ = '\0'; pvt->proto.p_proto = atoi(p); - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) p++; if (*p) *p++ = '\0'; @@ -237,7 +240,7 @@ parse_hes_list(struct irs_pr *this, char **hes_list) { pvt->proto.p_aliases = new; } pvt->proto.p_aliases[num++] = p; - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) p++; if (*p) *p++ = '\0'; diff --git a/contrib/bind/lib/irs/dns_pw.c b/contrib/bind/lib/irs/dns_pw.c index 5344c6e..b3f7e05 100644 --- a/contrib/bind/lib/irs/dns_pw.c +++ b/contrib/bind/lib/irs/dns_pw.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns_pw.c,v 1.18 1999/09/04 22:06:14 vixie Exp $"; +static const char rcsid[] = "$Id: dns_pw.c,v 1.19 2001/05/29 05:48:32 marka Exp $"; #endif #include "port_before.h" @@ -133,17 +133,20 @@ pw_byuid(struct irs_pw *this, uid_t uid) { static struct passwd * pw_next(struct irs_pw *this) { + UNUSED(this); errno = ENODEV; return (NULL); } static void pw_rewind(struct irs_pw *this) { + UNUSED(this); /* NOOP */ } static void pw_minimize(struct irs_pw *this) { + UNUSED(this); /* NOOP */ } diff --git a/contrib/bind/lib/irs/dns_sv.c b/contrib/bind/lib/irs/dns_sv.c index e6cb2df..b3244a7 100644 --- a/contrib/bind/lib/irs/dns_sv.c +++ b/contrib/bind/lib/irs/dns_sv.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns_sv.c,v 1.19 2000/03/30 22:53:56 vixie Exp $"; +static const char rcsid[] = "$Id: dns_sv.c,v 1.20 2001/05/29 05:48:33 marka Exp $"; #endif /* Imports */ @@ -66,10 +66,12 @@ static struct servent * sv_byport(struct irs_sv *, int, const char *); static struct servent * sv_next(struct irs_sv *); static void sv_rewind(struct irs_sv *); static void sv_minimize(struct irs_sv *); +#ifdef SV_RES_SETGET static struct __res_state * sv_res_get(struct irs_sv *); static void sv_res_set(struct irs_sv *, struct __res_state *, void (*)(void *)); +#endif static struct servent * parse_hes_list(struct irs_sv *, char **, const char *); @@ -105,8 +107,13 @@ irs_dns_sv(struct irs_acc *this) { sv->rewind = sv_rewind; sv->close = sv_close; sv->minimize = sv_minimize; +#ifdef SV_RES_SETGET + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; +#else sv->res_get = NULL; /* sv_res_get; */ sv->res_set = NULL; /* sv_res_set; */ +#endif return (sv); } @@ -161,12 +168,14 @@ sv_byport(struct irs_sv *this, int port, const char *proto) { static struct servent * sv_next(struct irs_sv *this) { + UNUSED(this); errno = ENODEV; return (NULL); } static void sv_rewind(struct irs_sv *this) { + UNUSED(this); /* NOOP */ } @@ -189,7 +198,7 @@ parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { /* Check to make sure the protocol matches. */ p = cp; - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) p++; if (!*p) continue; @@ -197,7 +206,7 @@ parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { proto_len = strlen(proto); if (strncasecmp(++p, proto, proto_len) != 0) continue; - if (p[proto_len] && !isspace(p[proto_len])) + if (p[proto_len] && !isspace(p[proto_len]&0xff)) continue; } /* OK, we've got a live one. Let's parse it for real. */ @@ -207,21 +216,21 @@ parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { p = pvt->svbuf; pvt->serv.s_name = p; - while (*p && !isspace(*p)) + while (*p && !isspace(*p&0xff)) p++; if (!*p) continue; *p++ = '\0'; pvt->serv.s_proto = p; - while (*p && !isspace(*p)) + while (*p && !isspace(*p&0xff)) p++; if (!*p) continue; *p++ = '\0'; pvt->serv.s_port = htons((u_short) atoi(p)); - while (*p && !isspace(*p)) + while (*p && !isspace(*p&0xff)) p++; if (*p) *p++ = '\0'; @@ -238,7 +247,7 @@ parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { pvt->serv.s_aliases = new; } pvt->serv.s_aliases[num++] = p; - while (*p && !isspace(*p)) + while (*p && !isspace(*p&0xff)) p++; if (*p) *p++ = '\0'; @@ -265,9 +274,11 @@ parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { static void sv_minimize(struct irs_sv *this) { + UNUSED(this); /* NOOP */ } +#ifdef SV_RES_SETGET static struct __res_state * sv_res_get(struct irs_sv *this) { struct pvt *pvt = (struct pvt *)this->private; @@ -284,3 +295,4 @@ sv_res_set(struct irs_sv *this, struct __res_state * res, __hesiod_res_set(dns->hes_ctx, res, free_res); } +#endif diff --git a/contrib/bind/lib/irs/gai_strerror.c b/contrib/bind/lib/irs/gai_strerror.c index f56c6f5..c487e68 100644 --- a/contrib/bind/lib/irs/gai_strerror.c +++ b/contrib/bind/lib/irs/gai_strerror.c @@ -1,45 +1,86 @@ /* -%%% copyright-cmetz-97 -This software is Copyright 1997-1998 by Craig Metz, All Rights Reserved. -The Inner Net License Version 2 applies to this software. -You should have received a copy of the license with this software. If -you didn't get a copy, you may request one from <license@inner.net>. - -*/ + * Copyright (c) 2001 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ #include <port_before.h> #include <netdb.h> -#include <errno.h> #include <port_after.h> -char * -gai_strerror(int errnum) { - switch(errnum) { - case 0: - return "no error"; - case EAI_BADFLAGS: - return "invalid value for ai_flags"; - case EAI_NONAME: - return "name or service is not known"; - case EAI_AGAIN: - return "temporary failure in name resolution"; - case EAI_FAIL: - return "non-recoverable failure in name resolution"; - case EAI_NODATA: - return "no address associated with name"; - case EAI_FAMILY: - return "ai_family not supported"; - case EAI_SOCKTYPE: - return "ai_socktype not supported"; - case EAI_SERVICE: - return "service not supported for ai_socktype"; - case EAI_ADDRFAMILY: - return "address family for name not supported"; - case EAI_MEMORY: - return "memory allocation failure"; - case EAI_SYSTEM: - return "system error"; - default: - return "unknown error"; - }; +#ifdef DO_PTHREADS +#include <pthread.h> +#include <stdlib.h> +#endif + +static const char *gai_errlist[] = { + "no error", + "address family not supported for name",/* EAI_ADDRFAMILY */ + "temporary failure", /* EAI_AGAIN */ + "invalid flags", /* EAI_BADFLAGS */ + "permanent failure", /* EAI_FAIL */ + "address family not supported", /* EAI_FAMILY */ + "memory failure", /* EAI_MEMORY */ + "no address", /* EAI_NODATA */ + "unknown name or service", /* EAI_NONAME */ + "service not supported for socktype", /* EAI_SERVICE */ + "socktype not supported", /* EAI_SOCKTYPE */ + "system failure", /* EAI_SYSTEM */ + "bad hints", /* EAI_BADHINTS */ + "bad protocol", /* EAI_PROTOCOL */ + + "unknown error" /* Must be last. */ +}; + +static const int gai_nerr = (sizeof(gai_errlist)/sizeof(*gai_errlist)); + +#define EAI_BUFSIZE 128 + +const char * +gai_strerror(int ecode) { +#ifndef DO_PTHREADS + static char buf[EAI_BUFSIZE]; +#else /* DO_PTHREADS */ + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + static pthread_key_t key; + static int once = 0; + char *buf; +#endif + + if (ecode >= 0 && ecode < (gai_nerr - 1)) + return (gai_errlist[ecode]); + +#ifdef DO_PTHREADS + if (!once) { + pthread_mutex_lock(&lock); + if (!once++) + pthread_key_create(&key, free); + pthread_mutex_unlock(&lock); + } + + buf = pthread_getspecific(key); + if (buf == NULL) { + buf = malloc(EAI_BUFSIZE); + if (buf == NULL) + return ("unknown error"); + pthread_setspecific(key, buf); + } +#endif + /* + * XXX This really should be snprintf(buf, EAI_BUFSIZE, ...). + * It is safe until message catalogs are used. + */ + sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode); + return (buf); } diff --git a/contrib/bind/lib/irs/gen.c b/contrib/bind/lib/irs/gen.c index fe41088..5ba7d52 100644 --- a/contrib/bind/lib/irs/gen.c +++ b/contrib/bind/lib/irs/gen.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: gen.c,v 1.25 1999/10/13 16:39:29 vixie Exp $"; +static const char rcsid[] = "$Id: gen.c,v 1.26 2001/05/29 05:48:35 marka Exp $"; #endif /* @@ -399,7 +399,10 @@ init_map_rules(struct gen_p *irs, const char *conf_file) { char *tmp; int n; - for (tmp = line; isascii(*tmp) && isspace(*tmp); tmp++) + for (tmp = line; + isascii((unsigned char)*tmp) && + isspace((unsigned char)*tmp); + tmp++) (void)NULL; if (*tmp == '#' || *tmp == '\n' || *tmp == '\0') continue; diff --git a/contrib/bind/lib/irs/gen_gr.c b/contrib/bind/lib/irs/gen_gr.c index 14dfa2d..4b1b282 100644 --- a/contrib/bind/lib/irs/gen_gr.c +++ b/contrib/bind/lib/irs/gen_gr.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: gen_gr.c,v 1.22 2000/07/11 05:51:56 vixie Exp $"; +static const char rcsid[] = "$Id: gen_gr.c,v 1.25 2001/06/07 02:12:26 marka Exp $"; #endif /* Imports */ @@ -324,8 +324,9 @@ gr_res_set(struct irs_gr *this, struct __res_state *res, static void grmerge(struct irs_gr *this, const struct group *src, int preserve) { struct pvt *pvt = (struct pvt *)this->private; - char *cp, **m, **p; - int n, ndst, nnew, memadj; + char *cp, **m, **p, *oldmembuf; + int n, ndst, nnew; + size_t used; if (!preserve) { pvt->group.gr_gid = src->gr_gid; @@ -372,15 +373,25 @@ grmerge(struct irs_gr *this, const struct group *src, int preserve) { /* No work to do. */ return; } - cp = realloc(pvt->membuf, pvt->membufsize + n); + used = preserve ? pvt->membufsize : 0; + cp = malloc(used + n); if (!cp) { /* No harm done, no work done. */ return; } - memadj = cp - pvt->membuf; + if (used != 0) + memcpy(cp, pvt->membuf, used); + oldmembuf = pvt->membuf; pvt->membuf = cp; - cp += pvt->membufsize; - pvt->membufsize += n; + pvt->membufsize = used + n; + cp += used; + + /* + * Adjust group.gr_mem. + */ + if (pvt->membuf != oldmembuf) + for (m = pvt->group.gr_mem; *m; m++) + *m = pvt->membuf + (*m - oldmembuf); /* * Add new elements. @@ -393,8 +404,10 @@ grmerge(struct irs_gr *this, const struct group *src, int preserve) { cp += strlen(cp) + 1; } if (preserve) { - pvt->group.gr_name += memadj; - pvt->group.gr_passwd += memadj; + pvt->group.gr_name = pvt->membuf + + (pvt->group.gr_name - oldmembuf); + pvt->group.gr_passwd = pvt->membuf + + (pvt->group.gr_passwd - oldmembuf); } else { pvt->group.gr_name = cp; strcpy(cp, src->gr_name); @@ -403,6 +416,8 @@ grmerge(struct irs_gr *this, const struct group *src, int preserve) { strcpy(cp, src->gr_passwd); cp += strlen(src->gr_passwd) + 1; } + if (oldmembuf != NULL) + free(oldmembuf); INSIST(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]); } diff --git a/contrib/bind/lib/irs/gen_ho.c b/contrib/bind/lib/irs/gen_ho.c index 9e7a429..12ed7cd 100644 --- a/contrib/bind/lib/irs/gen_ho.c +++ b/contrib/bind/lib/irs/gen_ho.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: gen_ho.c,v 1.15 1999/10/13 16:39:29 vixie Exp $"; +static const char rcsid[] = "$Id: gen_ho.c,v 1.16 2001/05/29 05:48:36 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports */ @@ -68,6 +68,8 @@ static struct __res_state * ho_res_get(struct irs_ho *this); static void ho_res_set(struct irs_ho *this, struct __res_state *res, void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); static int init(struct irs_ho *this); @@ -102,6 +104,7 @@ irs_gen_ho(struct irs_acc *this) { ho->minimize = ho_minimize; ho->res_get = ho_res_get; ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; return (ho); } @@ -328,6 +331,51 @@ ho_res_set(struct irs_ho *this, struct __res_state *res, } } +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct addrinfo *rval = NULL; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + if (ho->addrinfo == NULL) /* for safety */ + continue; + rval = (*ho->addrinfo)(ho, name, pai); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || + errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + if (rval) + freeaddrinfo(rval); + return (NULL); +} + static int init(struct irs_ho *this) { struct pvt *pvt = (struct pvt *)this->private; diff --git a/contrib/bind/lib/irs/gen_ng.c b/contrib/bind/lib/irs/gen_ng.c index 064d616..c28b510 100644 --- a/contrib/bind/lib/irs/gen_ng.c +++ b/contrib/bind/lib/irs/gen_ng.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: gen_ng.c,v 1.14 1999/10/13 16:39:29 vixie Exp $"; +static const char rcsid[] = "$Id: gen_ng.c,v 1.15 2001/05/29 05:48:38 marka Exp $"; #endif /* Imports */ @@ -52,7 +52,8 @@ struct pvt { /* Forward */ static void ng_close(struct irs_ng *); -static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); static int ng_test(struct irs_ng *, const char *, const char *, const char *, const char *); @@ -103,7 +104,9 @@ ng_close(struct irs_ng *this) { } static int -ng_next(struct irs_ng *this, char **host, char **user, char **domain) { +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ struct pvt *pvt = (struct pvt *)this->private; struct irs_ng *ng; diff --git a/contrib/bind/lib/irs/gen_p.h b/contrib/bind/lib/irs/gen_p.h index b8210b0..35ef439 100644 --- a/contrib/bind/lib/irs/gen_p.h +++ b/contrib/bind/lib/irs/gen_p.h @@ -16,7 +16,7 @@ */ /* - * $Id: gen_p.h,v 1.10 1999/01/18 07:46:50 vixie Exp $ + * $Id: gen_p.h,v 1.11 2001/05/29 05:48:39 marka Exp $ */ /* Notes: @@ -90,7 +90,7 @@ struct irs_rule { * This is the private data for a search access class. */ struct gen_p { - const char * options; + char * options; struct irs_rule * map_rules[(int)irs_nmap]; struct irs_inst accessors[(int)irs_nacc]; struct __res_state * res; diff --git a/contrib/bind/lib/irs/getaddrinfo.c b/contrib/bind/lib/irs/getaddrinfo.c index f95a681..f2c533d 100644 --- a/contrib/bind/lib/irs/getaddrinfo.c +++ b/contrib/bind/lib/irs/getaddrinfo.c @@ -1,505 +1,1225 @@ -/*- - * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. - * The Berkeley Software Design Inc. software License Agreement specifies - * the terms and conditions for redistribution. +/* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * BSDI $Id: getaddrinfo.c,v 8.3 1999/06/11 01:25:58 vixie Exp $ + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ -#include <port_before.h> +/* + * Issues to be discussed: + * - Thread safe-ness must be checked. + * - 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) + * Note: + * - We use getipnodebyname() just for thread-safeness. There's no intent + * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to + * getipnodebyname(). + * - The code filters out AFs that are not supported by the kernel, + * when globbing NULL hostname (to loopback, or wildcard). Is it the right + * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG + * in ai_flags? + * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. + * (1) what should we do against numeric hostname (2) what should we do + * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? + * non-loopback address configured? global address configured? + * - To avoid search order issue, we have a big amount of code duplicate + * from gethnamaddr.c and some other places. The issues that there's no + * lower layer function to lookup "IPv4 or IPv6" record. Calling + * gethostbyname2 from getaddrinfo will end up in wrong search order, as + * follows: + * - The code makes use of following calls when asked to resolver with + * ai_family = PF_UNSPEC: + * getipnodebyname(host, AF_INET6); + * getipnodebyname(host, AF_INET); + * This will result in the following queries if the node is configure to + * prefer /etc/hosts than DNS: + * lookup /etc/hosts for IPv6 address + * lookup DNS for IPv6 address + * lookup /etc/hosts for IPv4 address + * lookup DNS for IPv4 address + * which may not meet people's requirement. + * The right thing to happen is to have underlying layer which does + * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. + * This would result in a bit of code duplicate with _dns_ghbyname() and + * friends. + */ + +#include "port_before.h" + +#include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> -#include <sys/un.h> + +#include <net/if.h> #include <netinet/in.h> + +#include <arpa/inet.h> +#include <arpa/nameser.h> + #include <netdb.h> -#include <errno.h> +#include <resolv.h> #include <string.h> #include <stdlib.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include <arpa/inet.h> -#include <port_after.h> - -#define SA(addr) ((struct sockaddr *)(addr)) -#define SIN(addr) ((struct sockaddr_in *)(addr)) -#define SIN6(addr) ((struct sockaddr_in6 *)(addr)) -#define SUN(addr) ((struct sockaddr_un *)(addr)) - -static struct addrinfo - *ai_reverse(struct addrinfo *oai), - *ai_clone(struct addrinfo *oai, int family), - *ai_alloc(int family, int addrlen); -#ifdef AF_LOCAL -static int get_local(const char *name, int socktype, struct addrinfo **res); +#include <stddef.h> +#include <ctype.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> + +#include <stdarg.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* + * if we enable it, we will see duplicated addrinfo entries on reply if both + * AAAA and A6 records are found. disable it for default installation. + */ +#undef T_A6 + +#define SUCCESS 0 +#define ANY 0 +#define YES 1 +#define NO 0 + +static const char in_addrany[] = { 0, 0, 0, 0 }; +static const char in6_addrany[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +static const char in_loopback[] = { 127, 0, 0, 1 }; +static const char in6_loopback[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +}; + +static const struct afd { + int a_af; + int a_addrlen; + int a_socklen; + int a_off; + const char *a_addrany; + const char *a_loopback; + int a_scoped; +} afdl [] = { + {PF_INET6, sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr), + in6_addrany, in6_loopback, 1}, + {PF_INET, sizeof(struct in_addr), + sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr), + in_addrany, in_loopback, 0}, + {0, 0, 0, 0, NULL, NULL, 0}, +}; + +struct explore { + int e_af; + int e_socktype; + int e_protocol; + const char *e_protostr; + int e_wild; +#define WILD_AF(ex) ((ex)->e_wild & 0x01) +#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) +#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) +}; + +static const struct explore explore[] = { +#if 0 + { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, #endif + { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, + { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, + { -1, 0, 0, NULL, 0 }, +}; + +#define PTON_MAX 16 + +#define MAXPACKET (1024*64) -static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip, - int socktype, int port); -static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip, - int socktype, int port); -static void set_order(int, int (**)()); +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +static int str_isnumber __P((const char *)); +static int explore_fqdn __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_copy __P((const struct addrinfo *, const struct addrinfo *, + struct addrinfo **)); +static int explore_null __P((const struct addrinfo *, + const char *, struct addrinfo **)); +static int explore_numeric __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_numeric_scope __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int get_canonname __P((const struct addrinfo *, + struct addrinfo *, const char *)); +static struct addrinfo *get_ai __P((const struct addrinfo *, + const struct afd *, const char *)); +static struct addrinfo *copy_ai __P((const struct addrinfo *)); +static int get_portmatch __P((const struct addrinfo *, const char *)); +static int get_port __P((const struct addrinfo *, const char *, int)); +static const struct afd *find_afd __P((int)); +static int addrconfig __P((int)); +static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *)); +static struct net_data *init __P((void)); + +struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *)); +struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +#if 0 +static const char *ai_errlist[] = { + "Success", + "Address family for hostname not supported", /* EAI_ADDRFAMILY */ + "Temporary failure in name resolution", /* EAI_AGAIN */ + "Invalid value for ai_flags", /* EAI_BADFLAGS */ + "Non-recoverable failure in name resolution", /* EAI_FAIL */ + "ai_family not supported", /* EAI_FAMILY */ + "Memory allocation failure", /* EAI_MEMORY */ + "No address associated with hostname", /* EAI_NODATA */ + "hostname nor servname provided, or not known", /* EAI_NONAME */ + "servname not supported for ai_socktype", /* EAI_SERVICE */ + "ai_socktype not supported", /* EAI_SOCKTYPE */ + "System error returned in errno", /* EAI_SYSTEM */ + "Invalid value for hints", /* EAI_BADHINTS */ + "Resolved protocol is unknown", /* EAI_PROTOCOL */ + "Unknown error", /* EAI_MAX */ +}; +#endif -#define FOUND_IPV4 0x1 -#define FOUND_IPV6 0x2 -#define FOUND_MAX 2 +/* XXX macros that make external reference is BAD. */ + +#define GET_AI(ai, afd, addr) \ +do { \ + /* external reference: pai, error, and label free */ \ + (ai) = get_ai(pai, (afd), (addr)); \ + if ((ai) == NULL) { \ + error = EAI_MEMORY; \ + goto free; \ + } \ +} while (/*CONSTCOND*/0) + +#define GET_PORT(ai, serv) \ +do { \ + /* external reference: error and label free */ \ + error = get_port((ai), (serv), 0); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define GET_CANONNAME(ai, str) \ +do { \ + /* external reference: pai, error and label free */ \ + error = get_canonname(pai, (ai), (str)); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define ERR(err) \ +do { \ + /* external reference: error, and label bad */ \ + error = (err); \ + goto bad; \ + /*NOTREACHED*/ \ +} while (/*CONSTCOND*/0) + +#define MATCH_FAMILY(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) +#define MATCH(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) + +#if 0 /* bind8 has its own version */ +char * +gai_strerror(ecode) + int ecode; +{ + if (ecode < 0 || ecode > EAI_MAX) + ecode = EAI_MAX; + return ai_errlist[ecode]; +} +#endif + +void +freeaddrinfo(ai) + struct addrinfo *ai; +{ + struct addrinfo *next; + + do { + next = ai->ai_next; + if (ai->ai_canonname) + free(ai->ai_canonname); + /* no need to free(ai->ai_addr) */ + free(ai); + ai = next; + } while (ai); +} + +static int +str_isnumber(p) + const char *p; +{ + char *ep; + + if (*p == '\0') + return NO; + ep = NULL; + (void)strtoul(p, &ep, 10); + if (ep && *ep == '\0') + return YES; + else + return NO; +} int -getaddrinfo(const char *hostname, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) +getaddrinfo(hostname, servname, hints, res) + const char *hostname, *servname; + const struct addrinfo *hints; + struct addrinfo **res; { - struct servent *sp; - char *proto; - int family, socktype, flags, protocol; - struct addrinfo *ai, *ai_list; - int port, err, i; - int (*net_order[FOUND_MAX+1])(); + struct addrinfo sentinel; + struct addrinfo *cur; + int error = 0; + struct addrinfo ai, ai0, *afai; + struct addrinfo *pai; + const struct explore *ex; - if (hostname == NULL && servname == NULL) - return (EAI_NONAME); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + pai = &ai; + pai->ai_flags = 0; + pai->ai_family = PF_UNSPEC; + pai->ai_socktype = ANY; + pai->ai_protocol = ANY; + pai->ai_addrlen = 0; + pai->ai_canonname = NULL; + pai->ai_addr = NULL; + pai->ai_next = NULL; - proto = NULL; - if (hints != NULL) { - if (hints->ai_flags & ~(AI_MASK)) - return (EAI_BADFLAGS); + if (hostname == NULL && servname == NULL) + return EAI_NONAME; + if (hints) { + /* error check for hints */ if (hints->ai_addrlen || hints->ai_canonname || - hints->ai_addr || hints->ai_next) { - errno = EINVAL; - return (EAI_SYSTEM); - } - family = hints->ai_family; - socktype = hints->ai_socktype; - protocol = hints->ai_protocol; - flags = hints->ai_flags; - switch (family) { - case AF_UNSPEC: - switch (hints->ai_socktype) { - case SOCK_STREAM: proto = "tcp"; break; - case SOCK_DGRAM: proto = "udp"; break; - } - break; - case AF_INET: - case AF_INET6: - switch (hints->ai_socktype) { - case 0: break; - case SOCK_STREAM: proto = "tcp"; break; - case SOCK_DGRAM: proto = "udp"; break; - case SOCK_RAW: break; - default: return (EAI_SOCKTYPE); - } - break; -#ifdef AF_LOCAL - case AF_LOCAL: - switch (hints->ai_socktype) { - case 0: break; - case SOCK_STREAM: break; - case SOCK_DGRAM: break; - default: return (EAI_SOCKTYPE); - } + hints->ai_addr || hints->ai_next) + ERR(EAI_BADHINTS); /* xxx */ + if (hints->ai_flags & ~AI_MASK) + ERR(EAI_BADFLAGS); + switch (hints->ai_family) { + case PF_UNSPEC: + case PF_INET: + case PF_INET6: break; -#endif default: - return (EAI_FAMILY); + ERR(EAI_FAMILY); + } + memcpy(pai, hints, sizeof(*pai)); + + /* + * if both socktype/protocol are specified, check if they + * are meaningful combination. + */ + if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { + for (ex = explore; ex->e_af >= 0; ex++) { + if (pai->ai_family != ex->e_af) + continue; + if (ex->e_socktype == ANY) + continue; + if (ex->e_protocol == ANY) + continue; + if (pai->ai_socktype == ex->e_socktype && + pai->ai_protocol != ex->e_protocol) { + ERR(EAI_BADHINTS); + } + } } - } else { - protocol = 0; - family = 0; - socktype = 0; - flags = 0; } -#ifdef AF_LOCAL /* - * First, deal with AF_LOCAL. If the family was not set, - * then assume AF_LOCAL if the first character of the - * hostname/servname is '/'. + * post-2553: AI_ALL and AI_V4MAPPED are effective only against + * AF_INET6 query. They needs to be ignored if specified in other + * occassions. */ + switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { + case AI_V4MAPPED: + case AI_ALL | AI_V4MAPPED: + if (pai->ai_family != AF_INET6) + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; + case AI_ALL: +#if 1 + /* illegal */ + ERR(EAI_BADFLAGS); +#else + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; +#endif + } - if (hostname && - (family == AF_LOCAL || (family == 0 && *hostname == '/'))) - return (get_local(hostname, socktype, res)); + /* + * check for special cases. (1) numeric servname is disallowed if + * socktype/protocol are left unspecified. (2) servname is disallowed + * for raw and other inet{,6} sockets. + */ + if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) +#ifdef PF_INET6 + || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) +#endif + ) { + ai0 = *pai; /* backup *pai */ - if (servname && - (family == AF_LOCAL || (family == 0 && *servname == '/'))) - return (get_local(servname, socktype, res)); + if (pai->ai_family == PF_UNSPEC) { +#ifdef PF_INET6 + pai->ai_family = PF_INET6; +#else + pai->ai_family = PF_INET; #endif + } + error = get_portmatch(pai, servname); + if (error) + ERR(error); + + *pai = ai0; + } + + ai0 = *pai; + + /* NULL hostname, or numeric hostname */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) + continue; + if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) + continue; + + if (pai->ai_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; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + 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, &cur->ai_next); + } else + error = explore_numeric_scope(pai, hostname, servname, + &cur->ai_next); + + if (error) + goto free; + + while (cur && cur->ai_next) + cur = cur->ai_next; + } /* - * Ok, only AF_INET and AF_INET6 left. + * XXX + * If numreic representation of AF1 can be interpreted as FQDN + * representation of AF2, we need to think again about the code below. */ - ai_list = NULL; + if (sentinel.ai_next) + goto good; + + if (pai->ai_flags & AI_NUMERICHOST) + ERR(EAI_NONAME); + if (hostname == NULL) + ERR(EAI_NONAME); /* - * First, look up the service name (port) if it was - * requested. If the socket type wasn't specified, then - * try and figure it out. + * hostname as alphabetical name. + * We'll make sure that + * - if returning addrinfo list is empty, return non-zero error + * value (already known one or EAI_NONAME). + * - otherwise, + * + if we haven't had any errors, return 0 (i.e. success). + * + if we've had an error, free the list and return the error. + * without any assumption on the behavior of explore_fqdn(). */ - if (servname) { - char *e; - - port = strtol(servname, &e, 10); - if (*e == '\0') { - if (socktype == 0) - return (EAI_SOCKTYPE); - if (port < 0 || port > 65535) - return (EAI_SERVICE); - port = htons(port); - } else { - sp = getservbyname(servname, proto); - if (sp == NULL) - return (EAI_SERVICE); - port = sp->s_port; - if (socktype == 0) { - if (strcmp(sp->s_proto, "tcp")) - socktype = SOCK_STREAM; - else if (strcmp(sp->s_proto, "udp")) - socktype = SOCK_DGRAM; - } - } - } else - port = 0; + + /* first, try to query DNS for all possible address families. */ + *pai = ai0; + error = explore_fqdn(pai, hostname, servname, &afai); + if (error) { + if (afai != NULL) + freeaddrinfo(afai); + goto free; + } + if (afai == NULL) { + error = EAI_NONAME; /* we've had no errors. */ + goto free; + } /* - * Next, deal with just a service name, and no hostname. - * (we verified that one of them was non-null up above). + * we would like to prefer AF_INET6 than AF_INET, so we'll make an + * outer loop by AFs. */ - if (hostname == NULL && (flags & AI_PASSIVE) != 0) { - if (family == AF_INET || family == 0) { - ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in)); - if (ai == NULL) - return (EAI_MEMORY); - ai->ai_socktype = socktype; - ai->ai_protocol = protocol; - SIN(ai->ai_addr)->sin_port = port; - ai->ai_next = ai_list; - ai_list = ai; + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + 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 (family == AF_INET6 || family == 0) { - ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6)); - if (ai == NULL) { - freeaddrinfo(ai_list); - return (EAI_MEMORY); - } - ai->ai_socktype = socktype; - ai->ai_protocol = protocol; - SIN6(ai->ai_addr)->sin6_port = port; - ai->ai_next = ai_list; - ai_list = ai; +#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(pai->ai_family)) + continue; +#endif + + 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; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) { + freeaddrinfo(afai); + goto free; } - *res = ai_list; - return (0); + while (cur && cur->ai_next) + cur = cur->ai_next; } + freeaddrinfo(afai); /* afai must not be NULL at this point. */ + + /* we must not have got any errors. */ + if (error != 0) /* just for diagnosis */ + abort(); + + if (sentinel.ai_next) { +good: + *res = sentinel.ai_next; + return(SUCCESS); + } else { + /* + * All the process succeeded, but we've had an empty list. + * This can happen if the given hints do not match our + * candidates. + */ + error = EAI_NONAME; + } + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + *res = NULL; + return(error); +} + +/* + * FQDN hostname, DNS lookup + */ +static int +explore_fqdn(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ + struct addrinfo *result; + struct addrinfo *cur; + struct net_data *net_data = init(); + struct irs_ho *ho; + int error = 0; + char tmp[NS_MAXDNAME]; + const char *cp; + + result = NULL; + /* - * If the family isn't specified or AI_NUMERICHOST specified, - * check first to see if it * is a numeric address. - * Though the gethostbyname2() routine - * will recognize numeric addresses, it will only recognize - * the format that it is being called for. Thus, a numeric - * AF_INET address will be treated by the AF_INET6 call as - * a domain name, and vice versa. Checking for both numerics - * here avoids that. + * if the servname does not match socktype/protocol, ignore it. */ - if (hostname != NULL && - (family == 0 || (flags & AI_NUMERICHOST) != 0)) { - char abuf[sizeof(struct in6_addr)]; - char nbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx00")]; - int addrsize, addroff; - - if (inet_aton(hostname, (struct in_addr *)abuf)) { - if (family == AF_INET6) { - /* Convert to a V4 mapped address */ - struct in6_addr *a6 = (struct in6_addr *)abuf; - memcpy(&a6->s6_addr[12], &a6->s6_addr[0], 4); - memset(&a6->s6_addr[10], 0xff, 2); - memset(&a6->s6_addr[0], 0, 10); - goto inet6_addr; - } - addrsize = sizeof(struct in_addr); - addroff = (char *)(&SIN(0)->sin_addr) - (char *)0; - family = AF_INET; - goto common; - - } else if (inet_pton(AF_INET6, hostname, abuf)) { - if (family && family != AF_INET6) - return (EAI_NONAME); - inet6_addr: - addrsize = sizeof(struct in6_addr); - addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0; - family = AF_INET6; - - common: - if ((ai = ai_clone(ai_list, family)) == NULL) - return (EAI_MEMORY); - ai_list = ai; - ai->ai_socktype = socktype; - SIN(ai->ai_addr)->sin_port = port; - memcpy((char *)ai->ai_addr + addroff, abuf, addrsize); - if (flags & AI_CANONNAME) { - inet_ntop(family, abuf, nbuf, sizeof(nbuf)); - ai->ai_canonname = strdup(nbuf); - } - goto done; - } else if ((flags & AI_NUMERICHOST) != 0){ - return (EAI_NONAME); - } + if (get_portmatch(pai, servname) != 0) + return(0); + + if (!net_data || !(ho = net_data->ho)) + return(0); +#if 0 /* XXX (notyet) */ + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); } +#endif + if (!strchr(hostname, '.') && + (cp = res_hostalias(net_data->res, hostname, + tmp, sizeof(tmp)))) + hostname = cp; + result = (*ho->addrinfo)(ho, hostname, pai); + if (!net_data->ho_stayopen) { + (*ho->minimize)(ho); + } + if (result == NULL) { + int e = h_errno; - set_order(family, net_order); - for (i = 0; i < FOUND_MAX; i++) { - if (net_order[i] == NULL) + switch(e) { + case NETDB_INTERNAL: + error = EAI_SYSTEM; + break; + case TRY_AGAIN: + error = EAI_AGAIN; + break; + case NO_RECOVERY: + error = EAI_FAIL; + break; + case HOST_NOT_FOUND: + case NO_DATA: + error = EAI_NONAME; break; - if ((err = (net_order[i])(hostname, flags, &ai_list, - socktype, port)) != 0) - return(err); + default: + case NETDB_SUCCESS: /* should be impossible... */ + error = EAI_NONAME; + break; + } + goto free; } - if (ai_list == NULL) - return (EAI_NODATA); + for (cur = result; cur; cur = cur->ai_next) { + GET_PORT(cur, servname); /* XXX: redundant lookups... */ + /* canonname should already be filled. */ + } -done: - ai_list = ai_reverse(ai_list); + *res = result; - *res = ai_list; - return (0); + return(0); + +free: + if (result) + freeaddrinfo(result); + return error; } -static void -set_order(family, net_order) - int family; - int (**net_order)(); +static int +explore_copy(pai, src0, res) + const struct addrinfo *pai; /* seed */ + const struct addrinfo *src0; /* source */ + struct addrinfo **res; { - char *order, *tok; - int found; + int error; + struct addrinfo sentinel, *cur; + const struct addrinfo *src; - if (family) { - switch (family) { - case AF_INET: - *net_order++ = add_ipv4; - break; - case AF_INET6: - *net_order++ = add_ipv6; - break; - } - } else { - order = getenv("NET_ORDER"); - found = 0; - while (order != NULL) { - /* We ignore any unknown names. */ - tok = strsep(&order, ":"); - if (strcasecmp(tok, "inet6") == 0) { - if ((found & FOUND_IPV6) == 0) - *net_order++ = add_ipv6; - found |= FOUND_IPV6; - } else if (strcasecmp(tok, "inet") == 0 || - strcasecmp(tok, "inet4") == 0) { - if ((found & FOUND_IPV4) == 0) - *net_order++ = add_ipv4; - found |= FOUND_IPV4; - } + 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; } - /* Add in anything that we didn't find */ - if ((found & FOUND_IPV4) == 0) - *net_order++ = add_ipv4; - if ((found & FOUND_IPV6) == 0) - *net_order++ = add_ipv6; + cur->ai_next->ai_socktype = pai->ai_socktype; + cur->ai_next->ai_protocol = pai->ai_protocol; + cur = cur->ai_next; } - *net_order = NULL; - return; + + *res = sentinel.ai_next; + return 0; + +fail: + freeaddrinfo(sentinel.ai_next); + return error; } -static char v4_loop[4] = { 127, 0, 0, 1 }; +/* + * hostname == NULL. + * passive socket -> anyaddr (0.0.0.0 or ::) + * non-passive socket -> localhost (127.0.0.1 or ::1) + */ +static int +explore_null(pai, servname, res) + const struct addrinfo *pai; + const char *servname; + struct addrinfo **res; +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (pai->ai_flags & AI_PASSIVE) { + GET_AI(cur->ai_next, afd, afd->a_addrany); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "anyaddr"); + */ + GET_PORT(cur->ai_next, servname); + } else { + GET_AI(cur->ai_next, afd, afd->a_loopback); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "localhost"); + */ + GET_PORT(cur->ai_next, servname); + } + cur = cur->ai_next; + + *res = sentinel.ai_next; + return 0; + +free: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} +/* + * numeric hostname + */ static int -add_ipv4(const char *hostname, int flags, struct addrinfo **aip, - int socktype, int port) +explore_numeric(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; { - struct addrinfo *ai; - struct hostent *hp; - char **addr; + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + char pton[PTON_MAX]; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; - if (hostname == NULL && (flags & AI_PASSIVE) == 0) { - if ((ai = ai_clone(*aip, AF_INET)) == NULL) { - freeaddrinfo(*aip); - return(EAI_MEMORY); + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + switch (afd->a_af) { +#if 0 /*X/Open spec*/ + case AF_INET: + if (inet_aton(hostname, (struct in_addr *)pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + while (cur && cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + break; +#endif + default: + if (inet_pton(afd->a_af, hostname, pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + while (cur && cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ } + break; + } - *aip = ai; - ai->ai_socktype = socktype; - SIN(ai->ai_addr)->sin_port = port; - memcpy(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4); - } else if ((hp = gethostbyname2(hostname, AF_INET)) != NULL) { - for (addr = hp->h_addr_list; *addr; addr++) { - if ((ai = ai_clone(*aip, hp->h_addrtype)) == NULL) { - freeaddrinfo(*aip); - return(EAI_MEMORY); - } - *aip = ai; - ai->ai_socktype = socktype; - - /* We get IPv6 addresses if RES_USE_INET6 is set */ - if (hp->h_addrtype == AF_INET6) { - SIN6(ai->ai_addr)->sin6_port = port; - memcpy(&SIN6(ai->ai_addr)->sin6_addr, *addr, - hp->h_length); - } else { - SIN(ai->ai_addr)->sin_port = port; - memcpy(&SIN(ai->ai_addr)->sin_addr, *addr, - hp->h_length); + *res = sentinel.ai_next; + return 0; + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname with scope + */ +static int +explore_numeric_scope(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ +#ifndef SCOPE_DELIMITER + return explore_numeric(pai, hostname, servname, res); +#else + const struct afd *afd; + struct addrinfo *cur; + int error; + char *cp, *hostname2 = NULL, *scope, *addr; + struct sockaddr_in6 *sin6; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (!afd->a_scoped) + return explore_numeric(pai, hostname, servname, res); + + cp = strchr(hostname, SCOPE_DELIMITER); + if (cp == NULL) + return explore_numeric(pai, hostname, servname, res); + + /* + * Handle special case of <scoped_address><delimiter><scope id> + */ + hostname2 = strdup(hostname); + if (hostname2 == NULL) + return EAI_MEMORY; + /* terminate at the delimiter */ + hostname2[cp - hostname] = '\0'; + addr = hostname2; + scope = cp + 1; + + error = explore_numeric(pai, addr, servname, res); + if (error == 0) { + int scopeid; + + for (cur = *res; cur; cur = cur->ai_next) { + if (cur->ai_family != AF_INET6) + continue; + sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; + if ((scopeid = ip6_str2scopeid(scope, sin6)) == -1) { + free(hostname2); + return(EAI_NONAME); /* XXX: is return OK? */ } - if (flags & AI_CANONNAME) - ai->ai_canonname = strdup(hp->h_name); +#ifdef HAVE_SIN6_SCOPE_ID + sin6->sin6_scope_id = scopeid; +#endif } } - return(0); -} -static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + free(hostname2); + + return error; +#endif +} static int -add_ipv6(const char *hostname, int flags, struct addrinfo **aip, - int socktype, int port) +get_canonname(pai, ai, str) + const struct addrinfo *pai; + struct addrinfo *ai; + const char *str; { + if ((pai->ai_flags & AI_CANONNAME) != 0) { + ai->ai_canonname = (char *)malloc(strlen(str) + 1); + if (ai->ai_canonname == NULL) + return EAI_MEMORY; + strcpy(ai->ai_canonname, str); + } + return 0; +} + +static struct addrinfo * +get_ai(pai, afd, addr) + const struct addrinfo *pai; + const struct afd *afd; + const char *addr; +{ + char *p; struct addrinfo *ai; - struct hostent *hp; - char **addr; - if (hostname == NULL && (flags & AI_PASSIVE) == 0) { - if ((ai = ai_clone(*aip, AF_INET6)) == NULL) { - freeaddrinfo(*aip); - return(EAI_MEMORY); - } + ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + + (afd->a_socklen)); + if (ai == NULL) + return NULL; - *aip = ai; - ai->ai_socktype = socktype; - SIN6(ai->ai_addr)->sin6_port = port; - memcpy(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16); - } else if ((hp = gethostbyname2(hostname, AF_INET6)) != NULL) { - for (addr = hp->h_addr_list; *addr; addr++) { - if ((ai = ai_clone(*aip, AF_INET6)) == NULL) { - freeaddrinfo(*aip); - return (EAI_MEMORY); - } - *aip = ai; - ai->ai_socktype = socktype; - SIN6(ai->ai_addr)->sin6_port = port; - memcpy(&SIN6(ai->ai_addr)->sin6_addr, *addr, - hp->h_length); - if (flags & AI_CANONNAME) - ai->ai_canonname = strdup(hp->h_name); + memcpy(ai, pai, sizeof(struct addrinfo)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memset(ai->ai_addr, 0, (size_t)afd->a_socklen); +#ifdef HAVE_SA_LEN + ai->ai_addr->sa_len = afd->a_socklen; +#endif + ai->ai_addrlen = afd->a_socklen; + ai->ai_addr->sa_family = ai->ai_family = afd->a_af; + p = (char *)(void *)(ai->ai_addr); + memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); + 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; } +#ifdef HAVE_STRLCPY + strlcpy(ai->ai_canonname, pai->ai_canonname, l); +#else + strncpy(ai->ai_canonname, pai->ai_canonname, l); +#endif + } else { + /* just to make sure */ + ai->ai_canonname = NULL; } - return (0); + + ai->ai_next = NULL; + + return ai; } -void -freeaddrinfo(struct addrinfo *ai) { - struct addrinfo *ai_next; +static int +get_portmatch(const struct addrinfo *ai, const char *servname) { - while (ai != NULL) { - ai_next = ai->ai_next; - if (ai->ai_addr) - free(ai->ai_addr); - if (ai->ai_canonname) - free(ai->ai_canonname); - free(ai); - ai = ai_next; - } + /* get_port does not touch first argument. when matchonly == 1. */ + /* LINTED const cast */ + return get_port((const struct addrinfo *)ai, servname, 1); } -#ifdef AF_LOCAL static int -get_local(const char *name, int socktype, struct addrinfo **res) { - struct addrinfo *ai; - struct sockaddr_un *sun; +get_port(const struct addrinfo *ai, const char *servname, int matchonly) { + const char *proto; + struct servent *sp; + int port; + int allownumeric; - if (socktype == 0) - return (EAI_SOCKTYPE); + if (servname == NULL) + return 0; + switch (ai->ai_family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif + break; + default: + return 0; + } - if ((ai = ai_alloc(AF_LOCAL, sizeof(*sun))) == NULL) - return (EAI_MEMORY); + switch (ai->ai_socktype) { + case SOCK_RAW: + return EAI_SERVICE; + case SOCK_DGRAM: + case SOCK_STREAM: + allownumeric = 1; + break; + case ANY: + allownumeric = 0; + break; + default: + return EAI_SOCKTYPE; + } - sun = SUN(ai->ai_addr); - strncpy(sun->sun_path, name, sizeof(sun->sun_path)); + if (str_isnumber(servname)) { + if (!allownumeric) + return EAI_SERVICE; + port = htons(atoi(servname)); + if (port < 0 || port > 65535) + return EAI_SERVICE; + } else { + switch (ai->ai_socktype) { + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_STREAM: + proto = "tcp"; + break; + default: + proto = NULL; + break; + } - ai->ai_socktype = socktype; - /* - * ai->ai_flags, ai->ai_protocol, ai->ai_canonname, - * and ai->ai_next were initialized to zero. - */ + if ((sp = getservbyname(servname, proto)) == NULL) + return EAI_SERVICE; + port = sp->s_port; + } + + if (!matchonly) { + switch (ai->ai_family) { + case AF_INET: + ((struct sockaddr_in *)(void *) + ai->ai_addr)->sin_port = port; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(void *) + ai->ai_addr)->sin6_port = port; + break; + } + } - *res = ai; - return (0); + return 0; +} + +static const struct afd * +find_afd(af) + int af; +{ + const struct afd *afd; + + if (af == PF_UNSPEC) + return NULL; + for (afd = afdl; afd->a_af; afd++) { + if (afd->a_af == af) + return afd; + } + return NULL; } -#endif /* - * Allocate an addrinfo structure, and a sockaddr structure - * of the specificed length. We initialize: - * ai_addrlen - * ai_family - * ai_addr - * ai_addr->sa_family - * ai_addr->sa_len (HAVE_SA_LEN) - * and everything else is initialized to zero. + * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend + * 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. */ -static struct addrinfo * -ai_alloc(int family, int addrlen) { - struct addrinfo *ai; +static int +addrconfig(af) + int af; +{ + int s; - if ((ai = (struct addrinfo *)calloc(1, sizeof(*ai))) == NULL) - return (NULL); + /* XXX errno */ + s = socket(af, SOCK_DGRAM, 0); + if (s < 0) { + if (errno != EMFILE) + return 0; + } else + close(s); + return 1; +} - if ((ai->ai_addr = SA(calloc(1, addrlen))) == NULL) { - free(ai); - return (NULL); +/* convert a string to a scope identifier. XXX: IPv6 specific */ +static int +ip6_str2scopeid(scope, sin6) + char *scope; + struct sockaddr_in6 *sin6; +{ + int scopeid; + struct in6_addr *a6 = &sin6->sin6_addr; + char *ep; + + /* empty scopeid portion is invalid */ + if (*scope == '\0') + return -1; + +#ifdef USE_IFNAMELINKID + if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { + /* + * Using interface names as link indices can be allowed + * only when we can assume a one-to-one mappings between + * links and interfaces. See comments in getnameinfo.c. + */ + scopeid = if_nametoindex(scope); + if (scopeid == 0) + goto trynumeric; + return(scopeid); } - ai->ai_addrlen = addrlen; - ai->ai_family = family; - ai->ai_addr->sa_family = family; -#ifdef HAVE_SA_LEN - ai->ai_addr->sa_len = addrlen; #endif - return (ai); + + /* still unclear about literal, allow numeric only - placeholder */ + if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) + goto trynumeric; + if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) + goto trynumeric; + else + goto trynumeric; /* global */ + + /* try to convert to a numeric id as a last resort */ +trynumeric: + scopeid = (int)strtoul(scope, &ep, 10); + if (*ep == '\0') + return scopeid; + else + return -1; } -static struct addrinfo * -ai_clone(struct addrinfo *oai, int family) { - struct addrinfo *ai; +struct addrinfo * +hostent2addrinfo(hp, pai) + struct hostent *hp; + const struct addrinfo *pai; +{ + int i, af, error = 0; + char **aplist = NULL, *ap; + struct addrinfo sentinel, *cur; + const struct afd *afd; + + af = hp->h_addrtype; + if (pai->ai_family != AF_UNSPEC && af != pai->ai_family) + return(NULL); + + afd = find_afd(af); + if (afd == NULL) + return(NULL); + + aplist = hp->h_addr_list; - ai = ai_alloc(family, ((family == AF_INET6) ? - sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; - if (ai == NULL) { - freeaddrinfo(oai); - return (NULL); + for (i = 0; (ap = aplist[i]) != NULL; i++) { +#if 0 /* the trick seems too much */ + af = hp->h_addr_list; + if (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { + af = AF_INET; + ap = ap + sizeof(struct in6_addr) + - sizeof(struct in_addr); + } + afd = find_afd(af); + if (afd == NULL) + continue; +#endif /* 0 */ + + GET_AI(cur->ai_next, afd, ap); + + /* GET_PORT(cur->ai_next, servname); */ + if ((pai->ai_flags & AI_CANONNAME) != 0) { + /* + * RFC2553 says that ai_canonname will be set only for + * the first element. we do it for all the elements, + * just for convenience. + */ + GET_CANONNAME(cur->ai_next, hp->h_name); + } + while (cur && cur->ai_next) /* no need to loop, actually. */ + cur = cur->ai_next; + continue; + + free: + if (cur->ai_next) + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + /* continue, without tht pointer CUR advanced. */ } - if (oai == NULL) - return (ai); - - ai->ai_flags = oai->ai_flags; - ai->ai_socktype = oai->ai_socktype; - ai->ai_protocol = oai->ai_protocol; - ai->ai_canonname = NULL; - ai->ai_next = oai; - return (ai); + + return(sentinel.ai_next); } -static struct addrinfo * -ai_reverse(struct addrinfo *oai) { - struct addrinfo *nai, *tai; - - nai = NULL; - - while (oai) { - /* grab one off the old list */ - tai = oai; - oai = oai->ai_next; - /* put it on the front of the new list */ - tai->ai_next = nai; - nai = tai; +struct addrinfo * +addr2addrinfo(pai, cp) + const struct addrinfo *pai; + const char *cp; +{ + const struct afd *afd; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return(NULL); + + return(get_ai(pai, afd, cp)); +} + +static struct net_data * +init() +{ + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { +error: + errno = EIO; + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); } - return (nai); + + return (net_data); } diff --git a/contrib/bind/lib/irs/getgrent.c b/contrib/bind/lib/irs/getgrent.c index 866e8c5..f6eea13 100644 --- a/contrib/bind/lib/irs/getgrent.c +++ b/contrib/bind/lib/irs/getgrent.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: getgrent.c,v 1.19 1999/10/13 16:39:30 vixie Exp $"; +static const char rcsid[] = "$Id: getgrent.c,v 1.20 2001/05/29 05:48:41 marka Exp $"; #endif /* Imports */ @@ -36,6 +36,8 @@ static int __bind_irs_gr_unneeded; #include <grp.h> #include <resolv.h> #include <stdio.h> +#include <string.h> +#include <unistd.h> #include <irs.h> @@ -80,14 +82,14 @@ setgroupent(int stayopen) { #ifdef SETGRENT_VOID void -setgrent() { +setgrent(void) { struct net_data *net_data = init(); - return (setgrent_p(net_data)); + setgrent_p(net_data); } #else int -setgrent() { +setgrent(void) { struct net_data *net_data = init(); return (setgrent_p(net_data)); @@ -102,7 +104,7 @@ endgrent() { } int -getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroups) { +getgrouplist(GETGROUPLIST_ARGS) { struct net_data *net_data = init(); return (getgrouplist_p(name, basegid, groups, ngroups, net_data)); @@ -142,7 +144,7 @@ getgrgid_p(gid_t gid, struct net_data *net_data) { if (!net_data || !(gr = net_data->gr)) return (NULL); if (net_data->gr_stayopen && net_data->gr_last && - net_data->gr_last->gr_gid == gid) + (gid_t)net_data->gr_last->gr_gid == gid) return (net_data->gr_last); net_data->gr_last = (*gr->bygid)(gr, gid); if (!net_data->gr_stayopen) diff --git a/contrib/bind/lib/irs/getgrent_r.c b/contrib/bind/lib/irs/getgrent_r.c index df055db..641a2b2 100644 --- a/contrib/bind/lib/irs/getgrent_r.c +++ b/contrib/bind/lib/irs/getgrent_r.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: getgrent_r.c,v 8.4 1999/01/18 07:46:51 vixie Exp $"; +static const char rcsid[] = "$Id: getgrent_r.c,v 8.7 2001/11/01 08:02:08 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <port_before.h> @@ -26,7 +26,17 @@ static const char rcsid[] = "$Id: getgrent_r.c,v 8.4 1999/01/18 07:46:51 vixie E #include <errno.h> #include <string.h> #include <stdio.h> +#include <sys/types.h> +#if (defined(POSIX_GETGRNAM_R) || defined(POSIX_GETGRGID_R)) && \ + defined(_POSIX_PTHREAD_SEMANTICS) + /* turn off solaris remapping in <grp.h> */ +#define _UNIX95 +#undef _POSIX_PTHREAD_SEMANTICS #include <grp.h> +#define _POSIX_PTHREAD_SEMANTICS 1 +#else +#include <grp.h> +#endif #include <sys/param.h> #include <port_after.h> @@ -50,7 +60,7 @@ getgrnam_r(const char *name, struct group *gptr, if (ge == NULL) { *result = NULL; - return (-1); + return (0); } res = copy_group(ge, gptr, buf, buflen); @@ -75,11 +85,11 @@ getgrnam_r(const char *name, struct group *gptr, /* POSIX 1003.1c */ #ifdef POSIX_GETGRGID_R int -__posix_getgrgid_r(const gid_t gid, struct group *gptr, +__posix_getgrgid_r(gid_t gid, struct group *gptr, char *buf, int buflen, struct group **result) { #else /* POSIX_GETGRGID_R */ int -getgrgid_r(const gid_t gid, struct group *gptr, +getgrgid_r(gid_t gid, struct group *gptr, char *buf, size_t buflen, struct group **result) { #endif /* POSIX_GETGRGID_R */ struct group *ge = getgrgid(gid); @@ -87,7 +97,7 @@ getgrgid_r(const gid_t gid, struct group *gptr, if (ge == NULL) { *result = NULL; - return (-1); + return (0); } res = copy_group(ge, gptr, buf, buflen); @@ -97,7 +107,7 @@ getgrgid_r(const gid_t gid, struct group *gptr, #ifdef POSIX_GETGRGID_R struct group * -getgrgid_r(const gid_t gid, struct group *gptr, +getgrgid_r(gid_t gid, struct group *gptr, char *buf, int buflen) { struct group *ge = getgrgid(gid); int res; @@ -181,7 +191,7 @@ copy_group(struct group *ge, struct group *gptr, char *buf, int buflen) { if (len > buflen) { errno = ERANGE; - return (-1); + return (ERANGE); } /* copy group id */ diff --git a/contrib/bind/lib/irs/gethostent.c b/contrib/bind/lib/irs/gethostent.c index 5aa46c5..586fa49 100644 --- a/contrib/bind/lib/irs/gethostent.c +++ b/contrib/bind/lib/irs/gethostent.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: gethostent.c,v 1.28 2001/03/01 05:47:44 marka Exp $"; +static const char rcsid[] = "$Id: gethostent.c,v 1.29 2001/05/29 05:48:44 marka Exp $"; #endif /* Imports */ @@ -215,10 +215,6 @@ endhostent_p(struct net_data *net_data) { (*ho->minimize)(ho); } -#if !defined(HAS_INET6_STRUCTS) || defined(MISSING_IN6ADDR_ANY) -static const struct in6_addr in6addr_any; -#endif - #ifndef IN6_IS_ADDR_V4COMPAT static const unsigned char in6addr_compat[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -299,7 +295,7 @@ getipnodebyname(const char *name, int af, int flags, int *error_num) { char *addr_list[2]; char *aliases[1]; - he.h_name = (char *)name; + DE_CONST(name, he.h_name); he.h_addr_list = addr_list; he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6; he.h_addr_list[1] = NULL; @@ -379,8 +375,10 @@ getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { /* * Lookup IPv4 and IPv4 mapped/compatible addresses */ - if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) || - (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)) || + if ((af == AF_INET6 && + IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) || + (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) || (af == AF_INET)) { const char *cp = src; @@ -405,7 +403,7 @@ getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { /* * Lookup IPv6 address. */ - if (memcmp((struct in6_addr *)src, &in6addr_any, 16) == 0) { + if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) { *error_num = HOST_NOT_FOUND; return (NULL); } @@ -491,7 +489,7 @@ scan_interfaces(int *have_v4, int *have_v6) { struct in_addr in4; struct in6_addr in6; char *buf = NULL, *cp, *cplim; - static int bufsiz = 4095; + static unsigned int bufsiz = 4095; int s, cpsize, n; /* Set to zero. Used as loop terminators below. */ @@ -571,7 +569,7 @@ scan_interfaces(int *have_v4, int *have_v6) { #else cpsize = sizeof lifreq.lifr_name; /* XXX maybe this should be a hard error? */ - if (ioctl(s, SOICGLIFADDR, (char *)&lifreq) < 0) + if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0) continue; #endif switch (lifreq.lifr_addr.ss_family) { @@ -816,6 +814,7 @@ fakeaddr(const char *name, int af, struct net_data *net_data) { return (NULL); } pvt = net_data->ho_data; +#ifndef __bsdi__ /* * Unlike its forebear(inet_aton), our friendly inet_pton() is strict * in its interpretation of its input, and it will only return "1" if @@ -825,6 +824,15 @@ fakeaddr(const char *name, int af, struct net_data *net_data) { * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now. */ if (inet_pton(af, name, pvt->addr) != 1) { +#else + /* BSDI XXX + * We put this back to inet_aton -- we really want the old behavior + * Long live 127.1... + */ + if ((af != AF_INET || + inet_aton(name, (struct in_addr *)pvt->addr) != 1) && + inet_pton(af, name, pvt->addr) != 1) { +#endif RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); return (NULL); } diff --git a/contrib/bind/lib/irs/gethostent_r.c b/contrib/bind/lib/irs/gethostent_r.c index dab8639..e8017ac 100644 --- a/contrib/bind/lib/irs/gethostent_r.c +++ b/contrib/bind/lib/irs/gethostent_r.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: gethostent_r.c,v 8.5 2000/07/11 05:46:35 vixie Exp $"; +static const char rcsid[] = "$Id: gethostent_r.c,v 8.7 2001/11/01 08:02:09 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <port_before.h> @@ -26,6 +26,7 @@ static const char rcsid[] = "$Id: gethostent_r.c,v 8.5 2000/07/11 05:46:35 vixie #include <errno.h> #include <string.h> #include <stdio.h> +#include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #include <sys/param.h> @@ -39,26 +40,50 @@ copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS); HOST_R_RETURN gethostbyname_r(const char *name, struct hostent *hptr, HOST_R_ARGS) { struct hostent *he = gethostbyname(name); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif HOST_R_ERRNO; +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else if (he == NULL) return (HOST_R_BAD); return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif } HOST_R_RETURN gethostbyaddr_r(const char *addr, int len, int type, struct hostent *hptr, HOST_R_ARGS) { struct hostent *he = gethostbyaddr(addr, len, type); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif HOST_R_ERRNO; +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else if (he == NULL) return (HOST_R_BAD); return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif } /* @@ -70,13 +95,25 @@ gethostbyaddr_r(const char *addr, int len, int type, HOST_R_RETURN gethostent_r(struct hostent *hptr, HOST_R_ARGS) { struct hostent *he = gethostent(); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif HOST_R_ERRNO; +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else if (he == NULL) return (HOST_R_BAD); return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif } HOST_R_SET_RETURN @@ -96,7 +133,7 @@ HOST_R_END_RETURN #ifdef HOST_R_ENT_ARGS endhostent_r(HOST_R_ENT_ARGS) #else -endhostent_r() +endhostent_r(void) #endif { endhostent(); @@ -222,6 +259,6 @@ copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) { } #endif /* !HOSTENT_DATA */ #else /* HOST_R_RETURN */ - static int gethostent_r_unknown_systemm = 0; + static int gethostent_r_unknown_system = 0; #endif /* HOST_R_RETURN */ #endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/contrib/bind/lib/irs/getnameinfo.c b/contrib/bind/lib/irs/getnameinfo.c index 9f186f3..0e86cc1 100644 --- a/contrib/bind/lib/irs/getnameinfo.c +++ b/contrib/bind/lib/irs/getnameinfo.c @@ -1,8 +1,6 @@ /* * Issues to be discussed: * - Thread safe-ness must be checked - * - Return values. There seems to be no standard for return value (RFC2133) - * but INRIA implementation returns EAI_xxx defined for getaddrinfo(). */ /* @@ -50,14 +48,10 @@ #include <netdb.h> #include <resolv.h> #include <string.h> +#include <stddef.h> #include <port_after.h> -#define SUCCESS 0 -#define ANY 0 -#define YES 1 -#define NO 0 - /* * Note that a_off will be dynamically adjusted so that to be consistent * with the definition of sockaddr_in{,6}. @@ -66,30 +60,30 @@ static struct afd { int a_af; int a_addrlen; - int a_socklen; + size_t a_socklen; int a_off; } afdl [] = { /* first entry is linked last... */ {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), - 4 /*XXX*/}, + offsetof(struct sockaddr_in, sin_addr)}, {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), - 8 /*XXX*/}, - {0, 0, 0}, + offsetof(struct sockaddr_in6, sin6_addr)}, + {0, 0, 0, 0}, }; struct sockinet { +#ifdef HAVE_SA_LEN u_char si_len; +#endif u_char si_family; u_short si_port; }; -#define ENI_NOSOCKET 0 -#define ENI_NOSERVNAME 1 -#define ENI_NOHOSTNAME 2 -#define ENI_MEMORY 3 -#define ENI_SYSTEM 4 -#define ENI_FAMILY 5 -#define ENI_SALEN 6 +static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *, + size_t, int)); +#ifdef HAVE_SIN6_SCOPE_ID +static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, int)); +#endif int getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) @@ -106,82 +100,60 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) struct hostent *hp; u_short port; #ifdef HAVE_SA_LEN - int len; + size_t len; #endif int family, i; - char *addr, *p; + const char *addr; + char *p; u_char pfx; - static int firsttime = 1; - static char numserv[512]; - static char numaddr[512]; - - - /* dynamically adjust a_off */ - if (firsttime) { - struct afd *p; - u_char *q; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - - for (p = &afdl[0]; p->a_af; p++) { - switch (p->a_af) { - case PF_INET: - q = (u_char *)&sin.sin_addr.s_addr; - p->a_off = q - (u_char *)&sin; - break; - case PF_INET6: - q = (u_char *)&sin6.sin6_addr.s6_addr; - p->a_off = q - (u_char *)&sin6; - break; - default: - break; - } - } - firsttime = 0; - } + char numserv[512]; + char numaddr[512]; if (sa == NULL) - return ENI_NOSOCKET; + return EAI_FAIL; #ifdef HAVE_SA_LEN len = sa->sa_len; - if (len != salen) return ENI_SALEN; + if (len != salen) return EAI_FAIL; #endif - + family = sa->sa_family; for (i = 0; afdl[i].a_af; i++) if (afdl[i].a_af == family) { afd = &afdl[i]; goto found; } - return ENI_FAMILY; - + return EAI_FAMILY; + found: - if (salen != afd->a_socklen) return ENI_SALEN; - - port = ((struct sockinet *)sa)->si_port; /* network byte order */ - addr = (char *)sa + afd->a_off; + if (salen != afd->a_socklen) return EAI_FAIL; + + port = ((const struct sockinet *)sa)->si_port; /* network byte order */ + addr = (const char *)sa + afd->a_off; if (serv == NULL || servlen == 0) { - /* what we should do? */ + /* + * rfc2553bis says that serv == NULL or servlen == 0 means that + * the caller does not want the result. + */ } else if (flags & NI_NUMERICSERV) { - snprintf(numserv, sizeof(numserv), "%d", ntohs(port)); + sprintf(numserv, "%d", ntohs(port)); if (strlen(numserv) > servlen) - return ENI_MEMORY; + return EAI_MEMORY; strcpy(serv, numserv); } else { sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp"); if (sp) { if (strlen(sp->s_name) + 1 > servlen) - return ENI_MEMORY; + return EAI_MEMORY; strcpy(serv, sp->s_name); } else - return ENI_NOSERVNAME; + return EAI_NONAME; } switch (sa->sa_family) { case AF_INET: - if (ntohl(*(u_long *)addr) >> IN_CLASSA_NSHIFT == 0) + if (ntohl(*(const u_long *)addr) >> IN_CLASSA_NSHIFT == 0) flags |= NI_NUMERICHOST; break; case AF_INET6: @@ -191,14 +163,12 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) break; } if (host == NULL || hostlen == 0) { - /* what should we do? */ + /* + * rfc2553bis says that host == NULL or hostlen == 0 means that + * the caller does not want the result. + */ } else if (flags & NI_NUMERICHOST) { - if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) - == NULL) - return ENI_SYSTEM; - if (strlen(numaddr) + 1 > hostlen) - return ENI_MEMORY; - strcpy(host, numaddr); + goto numeric; } else { hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); @@ -208,18 +178,130 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) if (p) *p = '\0'; } if (strlen(hp->h_name) + 1 > hostlen) - return ENI_MEMORY; + return EAI_MEMORY; strcpy(host, hp->h_name); } else { if (flags & NI_NAMEREQD) - return ENI_NOHOSTNAME; - if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) - == NULL) - return ENI_NOHOSTNAME; - if (strlen(numaddr) + 1 > hostlen) - return ENI_MEMORY; - strcpy(host, numaddr); + return EAI_NONAME; + numeric: + switch(afd->a_af) { + case AF_INET6: + { + int error; + + if ((error = ip6_parsenumeric(sa, addr, host, + hostlen, + flags)) != 0) + return(error); + break; + } + + default: + if (inet_ntop(afd->a_af, addr, numaddr, + sizeof(numaddr)) == NULL) + return EAI_NONAME; + if (strlen(numaddr) + 1 > hostlen) + return EAI_MEMORY; + strcpy(host, numaddr); + } + } + } + return(0); +} + +static int +ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host, + size_t hostlen, int flags) +{ + size_t numaddrlen; + char numaddr[512]; + +#ifndef HAVE_SIN6_SCOPE_ID + UNUSED(sa); + UNUSED(flags); +#endif + + if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) + == NULL) + return EAI_SYSTEM; + + numaddrlen = strlen(numaddr); + if (numaddrlen + 1 > hostlen) /* don't forget terminator */ + return EAI_MEMORY; + strcpy(host, numaddr); + +#ifdef HAVE_SIN6_SCOPE_ID + if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) { + char scopebuf[MAXHOSTNAMELEN]; /* XXX */ + int scopelen; + + /* ip6_sa2str never fails */ + scopelen = ip6_sa2str((const struct sockaddr_in6 *)sa, + scopebuf, sizeof(scopebuf), flags); + + if (scopelen + 1 + numaddrlen + 1 > hostlen) + return EAI_MEMORY; + + /* construct <numeric-addr><delim><scopeid> */ + memcpy(host + numaddrlen + 1, scopebuf, + scopelen); + host[numaddrlen] = SCOPE_DELIMITER; + host[numaddrlen + 1 + scopelen] = '\0'; + } +#endif + + return 0; +} + +#ifdef HAVE_SIN6_SCOPE_ID +/* ARGSUSED */ +static int +ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, + size_t bufsiz, int flags) +{ +#ifdef USE_IFNAMELINKID + unsigned int ifindex = (unsigned int)sa6->sin6_scope_id; + const struct in6_addr *a6 = &sa6->sin6_addr; +#endif + char tmp[64]; + +#ifdef NI_NUMERICSCOPE + if (flags & NI_NUMERICSCOPE) { + sprintf(tmp, "%u", sa6->sin6_scope_id); + if (bufsiz != 0) { + strncpy(buf, tmp, bufsiz - 1); + buf[bufsiz - 1] = '\0'; + } + return(strlen(tmp)); + } +#endif + +#ifdef USE_IFNAMELINKID + /* + * For a link-local address, convert the index to an interface + * name, assuming a one-to-one mapping between links and interfaces. + * Note, however, that this assumption is stronger than the + * specification of the scoped address architecture; the + * specficication says that more than one interfaces can belong to + * a single link. + */ + + /* if_indextoname() does not take buffer size. not a good api... */ + if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) && + bufsiz >= IF_NAMESIZE) { + char *p = if_indextoname(ifindex, buf); + if (p) { + return(strlen(p)); } } - return SUCCESS; +#endif + + /* last resort */ + sprintf(tmp, "%u", sa6->sin6_scope_id); + if (bufsiz != 0) { + strncpy(buf, tmp, bufsiz - 1); + buf[bufsiz - 1] = '\0'; + } + return(strlen(tmp)); } +#endif diff --git a/contrib/bind/lib/irs/getnetent.c b/contrib/bind/lib/irs/getnetent.c index 52aebe3..49810b7 100644 --- a/contrib/bind/lib/irs/getnetent.c +++ b/contrib/bind/lib/irs/getnetent.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: getnetent.c,v 1.18 2000/12/23 08:14:53 vixie Exp $"; +static const char rcsid[] = "$Id: getnetent.c,v 1.19 2001/05/29 05:48:47 marka Exp $"; #endif /* Imports */ @@ -259,10 +259,11 @@ fakeaddr(const char *name, int af, struct net_data *net_data) { RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); return (NULL); } - if (!isascii(name[0]) || !isdigit(name[0])) + if (!isascii((unsigned char)(name[0])) || + !isdigit((unsigned char)(name[0]))) return (NULL); for (cp = name; *cp; ++cp) - if (!isascii(*cp) || (!isdigit(*cp) && *cp != '.')) + if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.')) return (NULL); if (*--cp == '.') return (NULL); diff --git a/contrib/bind/lib/irs/getnetent_r.c b/contrib/bind/lib/irs/getnetent_r.c index b78b45a..1472eb5 100644 --- a/contrib/bind/lib/irs/getnetent_r.c +++ b/contrib/bind/lib/irs/getnetent_r.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: getnetent_r.c,v 8.4 1999/01/18 07:46:52 vixie Exp $"; +static const char rcsid[] = "$Id: getnetent_r.c,v 8.6 2001/11/01 08:02:11 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <port_before.h> @@ -26,6 +26,7 @@ static const char rcsid[] = "$Id: getnetent_r.c,v 8.4 1999/01/18 07:46:52 vixie #include <errno.h> #include <string.h> #include <stdio.h> +#include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #include <sys/param.h> @@ -39,11 +40,22 @@ copy_netent(struct netent *, struct netent *, NET_R_COPY_ARGS); NET_R_RETURN getnetbyname_r(const char *name, struct netent *nptr, NET_R_ARGS) { struct netent *ne = getnetbyname(name); +#ifdef NET_R_SETANSWER + int n = 0; + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else if (ne == NULL) return (NET_R_BAD); return (copy_netent(ne, nptr, NET_R_COPY)); +#endif } #ifndef GETNETBYADDR_ADDR_T @@ -52,11 +64,23 @@ getnetbyname_r(const char *name, struct netent *nptr, NET_R_ARGS) { NET_R_RETURN getnetbyaddr_r(GETNETBYADDR_ADDR_T addr, int type, struct netent *nptr, NET_R_ARGS) { struct netent *ne = getnetbyaddr(addr, type); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else if (ne == NULL) return (NET_R_BAD); return (copy_netent(ne, nptr, NET_R_COPY)); +#endif } /* @@ -68,11 +92,23 @@ getnetbyaddr_r(GETNETBYADDR_ADDR_T addr, int type, struct netent *nptr, NET_R_AR NET_R_RETURN getnetent_r(struct netent *nptr, NET_R_ARGS) { struct netent *ne = getnetent(); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else if (ne == NULL) return (NET_R_BAD); return (copy_netent(ne, nptr, NET_R_COPY)); +#endif } NET_R_SET_RETURN @@ -117,7 +153,7 @@ copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) { len += strlen(ne->n_name) + 1; len += numptr * sizeof(char*); - if (len > buflen) { + if (len > (int)buflen) { errno = ERANGE; return (NET_R_BAD); } @@ -186,6 +222,6 @@ copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) { } #endif /* !NETENT_DATA */ #else /* NET_R_RETURN */ - static int getnetent_r_unknown_systemm = 0; + static int getnetent_r_unknown_system = 0; #endif /* NET_R_RETURN */ #endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/contrib/bind/lib/irs/getnetgrent.c b/contrib/bind/lib/irs/getnetgrent.c index 8c5f5f8..e966ea6 100644 --- a/contrib/bind/lib/irs/getnetgrent.c +++ b/contrib/bind/lib/irs/getnetgrent.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: getnetgrent.c,v 1.14 1999/10/07 20:44:03 vixie Exp $"; +static const char rcsid[] = "$Id: getnetgrent.c,v 1.15 2001/05/29 05:48:49 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports */ @@ -70,7 +70,7 @@ innetgr(const char *netgroup, const char *host, } int -getnetgrent(char **host, char **user, char **domain) { +getnetgrent(const char **host, const char **user, const char **domain) { struct net_data *net_data = init(); return (getnetgrent_p(host, user, domain, net_data)); @@ -109,7 +109,7 @@ innetgr_p(const char *netgroup, const char *host, } int -getnetgrent_p(char **host, char **user, char **domain, +getnetgrent_p(const char **host, const char **user, const char **domain, struct net_data *net_data ) { struct irs_ng *ng; diff --git a/contrib/bind/lib/irs/getnetgrent_r.c b/contrib/bind/lib/irs/getnetgrent_r.c index e0c366c..adae817 100644 --- a/contrib/bind/lib/irs/getnetgrent_r.c +++ b/contrib/bind/lib/irs/getnetgrent_r.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: getnetgrent_r.c,v 8.4 1999/01/18 07:46:52 vixie Exp $"; +static const char rcsid[] = "$Id: getnetgrent_r.c,v 8.6 2001/11/01 08:02:12 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <port_before.h> @@ -26,15 +26,18 @@ static const char rcsid[] = "$Id: getnetgrent_r.c,v 8.4 1999/01/18 07:46:52 vixi #include <errno.h> #include <string.h> #include <stdio.h> +#include <sys/types.h> #include <netinet/in.h> #include <netdb.h> +#include <netgroup.h> +#include <stdlib.h> #include <port_after.h> #ifdef NGR_R_RETURN static NGR_R_RETURN -copy_protoent(char **, char **, char **, char *, char *, char *, - NGR_R_COPY_ARGS); +copy_protoent(char **, char **, char **, const char *, const char *, + const char *, NGR_R_COPY_ARGS); NGR_R_RETURN innetgr_r(const char *netgroup, const char *host, const char *user, @@ -51,7 +54,7 @@ innetgr_r(const char *netgroup, const char *host, const char *user, NGR_R_RETURN getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS) { - char *mp, *up, *dp; + const char *mp, *up, *dp; int res = getnetgrent(&mp, &up, &dp); if (res != 1) @@ -69,14 +72,27 @@ setnetgrent_r(const char *netgroup) #endif { setnetgrent(netgroup); +#ifdef NGR_R_PRIVATE + *buf = NULL; +#endif #ifdef NGR_R_SET_RESULT return (NGR_R_SET_RESULT); #endif } NGR_R_END_RETURN -endnetgrent_r(NGR_R_ENT_ARGS) { +#ifdef NGR_R_ENT_ARGS +endnetgrent_r(NGR_R_ENT_ARGS) +#else +endnetgrent_r(void) +#endif +{ endnetgrent(); +#ifdef NGR_R_PRIVATE + if (*buf != NULL) + free(*buf); + *buf = NULL; +#endif NGR_R_END_RESULT(NGR_R_OK); } @@ -84,9 +100,10 @@ endnetgrent_r(NGR_R_ENT_ARGS) { static int copy_protoent(char **machinep, char **userp, char **domainp, - char *mp, char *up, char *dp, NGR_R_COPY_ARGS) { + const char *mp, const char *up, const char *dp, + NGR_R_COPY_ARGS) { char *cp; - int i, n; + int n; int len; /* Find out the amount of space required to store the answer. */ @@ -95,12 +112,20 @@ copy_protoent(char **machinep, char **userp, char **domainp, if (up != NULL) len += strlen(up) + 1; if (dp != NULL) len += strlen(dp) + 1; - if (len > buflen) { +#ifdef NGR_R_PRIVATE + free(*buf); + *buf = malloc(len); + if (*buf == NULL) + return(NGR_R_BAD); + cp = *buf; +#else + if (len > (int)buflen) { errno = ERANGE; return (NGR_R_BAD); } - cp = buf; +#endif + if (mp != NULL) { n = strlen(mp) + 1; diff --git a/contrib/bind/lib/irs/getprotoent.c b/contrib/bind/lib/irs/getprotoent.c index e3bfc37..724b0ad 100644 --- a/contrib/bind/lib/irs/getprotoent.c +++ b/contrib/bind/lib/irs/getprotoent.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: getprotoent.c,v 1.15 1999/10/13 16:39:31 vixie Exp $"; +static const char rcsid[] = "$Id: getprotoent.c,v 1.16 2001/11/01 07:34:33 marka Exp $"; #endif /* Imports */ @@ -33,6 +33,7 @@ static const char rcsid[] = "$Id: getprotoent.c,v 1.15 1999/10/13 16:39:31 vixie #include <errno.h> #include <resolv.h> #include <stdio.h> +#include <string.h> #include <irs.h> diff --git a/contrib/bind/lib/irs/getprotoent_r.c b/contrib/bind/lib/irs/getprotoent_r.c index e5c54d7..fc3b17e 100644 --- a/contrib/bind/lib/irs/getprotoent_r.c +++ b/contrib/bind/lib/irs/getprotoent_r.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: getprotoent_r.c,v 8.4 1999/01/18 07:46:52 vixie Exp $"; +static const char rcsid[] = "$Id: getprotoent_r.c,v 8.6 2001/11/01 08:02:14 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <port_before.h> @@ -26,6 +26,7 @@ static const char rcsid[] = "$Id: getprotoent_r.c,v 8.4 1999/01/18 07:46:52 vixi #include <errno.h> #include <string.h> #include <stdio.h> +#include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #include <port_after.h> @@ -38,21 +39,41 @@ copy_protoent(struct protoent *, struct protoent *, PROTO_R_COPY_ARGS); PROTO_R_RETURN getprotobyname_r(const char *name, struct protoent *pptr, PROTO_R_ARGS) { struct protoent *pe = getprotobyname(name); +#ifdef PROTO_R_SETANSWER + int n = 0; + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else if (pe == NULL) return (PROTO_R_BAD); return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif } PROTO_R_RETURN getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) { struct protoent *pe = getprotobynumber(proto); +#ifdef PROTO_R_SETANSWER + int n = 0; + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else if (pe == NULL) return (PROTO_R_BAD); return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif } /* @@ -64,11 +85,21 @@ getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) { PROTO_R_RETURN getprotoent_r(struct protoent *pptr, PROTO_R_ARGS) { struct protoent *pe = getprotoent(); +#ifdef PROTO_R_SETANSWER + int n = 0; + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else if (pe == NULL) return (PROTO_R_BAD); return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif } PROTO_R_SET_RETURN @@ -113,7 +144,7 @@ copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) { len += strlen(pe->p_name) + 1; len += numptr * sizeof(char*); - if (len > buflen) { + if (len > (int)buflen) { errno = ERANGE; return (PROTO_R_BAD); } @@ -180,6 +211,6 @@ copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) { } #endif /* PROTOENT_DATA */ #else /* PROTO_R_RETURN */ - static int getprotoent_r_unknown_systemm = 0; + static int getprotoent_r_unknown_system = 0; #endif /* PROTO_R_RETURN */ #endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/contrib/bind/lib/irs/getpwent_r.c b/contrib/bind/lib/irs/getpwent_r.c index 761fa45..ee2d8a7 100644 --- a/contrib/bind/lib/irs/getpwent_r.c +++ b/contrib/bind/lib/irs/getpwent_r.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: getpwent_r.c,v 8.3 1999/01/08 19:24:33 vixie Exp $"; +static const char rcsid[] = "$Id: getpwent_r.c,v 8.6 2001/11/01 08:02:15 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <port_before.h> @@ -27,7 +27,19 @@ static const char rcsid[] = "$Id: getpwent_r.c,v 8.3 1999/01/08 19:24:33 vixie E #include <string.h> #include <stdio.h> #include <sys/types.h> +#if (defined(POSIX_GETPWNAM_R) || defined(POSIX_GETPWUID_R)) +#if defined(_POSIX_PTHREAD_SEMANTICS) + /* turn off solaris remapping in <grp.h> */ +#undef _POSIX_PTHREAD_SEMANTICS #include <pwd.h> +#define _POSIX_PTHREAD_SEMANTICS 1 +#else +#define _UNIX95 1 +#include <pwd.h> +#endif +#else +#include <pwd.h> +#endif #include <port_after.h> #ifdef PASS_R_RETURN @@ -50,7 +62,7 @@ getpwnam_r(const char *login, struct passwd *pwptr, if (pw == NULL) { *result = NULL; - return (-1); + return (0); } res = copy_passwd(pw, pwptr, buf, buflen); @@ -87,7 +99,7 @@ getpwuid_r(uid_t uid, struct passwd *pwptr, if (pw == NULL) { *result = NULL; - return (-1); + return (0); } res = copy_passwd(pw, pwptr, buf, buflen); @@ -142,7 +154,12 @@ setpassent_r(int stayopen) } PASS_R_SET_RETURN -setpwent_r(PASS_R_ENT_ARGS) { +#ifdef PASS_R_ENT_ARGS +setpwent_r(PASS_R_ENT_ARGS) +#else +setpwent_r(void) +#endif +{ setpwent(); #ifdef PASS_R_SET_RESULT @@ -151,7 +168,12 @@ setpwent_r(PASS_R_ENT_ARGS) { } PASS_R_END_RETURN -endpwent_r(PASS_R_ENT_ARGS) { +#ifdef PASS_R_ENT_ARGS +endpwent_r(PASS_R_ENT_ARGS) +#else +endpwent_r(void) +#endif +{ endpwent(); PASS_R_END_RESULT(PASS_R_OK); @@ -177,8 +199,8 @@ fgetpwent_r(FILE *f, struct passwd *pwptr, PASS_R_COPY_ARGS) { static int copy_passwd(struct passwd *pw, struct passwd *pwptr, char *buf, int buflen) { char *cp; - int i, n; - int numptr, len; + int n; + int len; /* Find out the amount of space required to store the answer. */ len = strlen(pw->pw_name) + 1; @@ -192,7 +214,7 @@ copy_passwd(struct passwd *pw, struct passwd *pwptr, char *buf, int buflen) { if (len > buflen) { errno = ERANGE; - return (-1); + return (ERANGE); } /* copy fixed atomic values*/ @@ -248,6 +270,6 @@ copy_passwd(struct passwd *pw, struct passwd *pwptr, char *buf, int buflen) { return (0); } #else /* PASS_R_RETURN */ - static int getpwent_r_unknown_systemm = 0; + static int getpwent_r_unknown_system = 0; #endif /* PASS_R_RETURN */ #endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */ diff --git a/contrib/bind/lib/irs/getservent.c b/contrib/bind/lib/irs/getservent.c index d2b8b50..d63ae1d 100644 --- a/contrib/bind/lib/irs/getservent.c +++ b/contrib/bind/lib/irs/getservent.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: getservent.c,v 1.16 1999/10/13 16:39:31 vixie Exp $"; +static const char rcsid[] = "$Id: getservent.c,v 1.17 2001/11/01 07:33:16 marka Exp $"; #endif /* Imports */ @@ -33,6 +33,7 @@ static const char rcsid[] = "$Id: getservent.c,v 1.16 1999/10/13 16:39:31 vixie #include <errno.h> #include <resolv.h> #include <stdio.h> +#include <string.h> #include <irs.h> diff --git a/contrib/bind/lib/irs/getservent_r.c b/contrib/bind/lib/irs/getservent_r.c index 4da9dc2..b4897ae 100644 --- a/contrib/bind/lib/irs/getservent_r.c +++ b/contrib/bind/lib/irs/getservent_r.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: getservent_r.c,v 8.3 1999/01/08 19:24:36 vixie Exp $"; +static const char rcsid[] = "$Id: getservent_r.c,v 8.5 2001/11/01 08:02:16 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <port_before.h> @@ -26,6 +26,7 @@ static const char rcsid[] = "$Id: getservent_r.c,v 8.3 1999/01/08 19:24:36 vixie #include <errno.h> #include <string.h> #include <stdio.h> +#include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #include <sys/param.h> @@ -40,22 +41,42 @@ SERV_R_RETURN getservbyname_r(const char *name, const char *proto, struct servent *sptr, SERV_R_ARGS) { struct servent *se = getservbyname(name, proto); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + return (n); +#else if (se == NULL) return (SERV_R_BAD); return (copy_servent(se, sptr, SERV_R_COPY)); +#endif } SERV_R_RETURN getservbyport_r(int port, const char *proto, struct servent *sptr, SERV_R_ARGS) { struct servent *se = getservbyport(port, proto); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + return (n); +#else if (se == NULL) return (SERV_R_BAD); return (copy_servent(se, sptr, SERV_R_COPY)); +#endif } /* @@ -67,11 +88,21 @@ getservbyport_r(int port, const char *proto, SERV_R_RETURN getservent_r(struct servent *sptr, SERV_R_ARGS) { struct servent *se = getservent(); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + return (n); +#else if (se == NULL) return (SERV_R_BAD); return (copy_servent(se, sptr, SERV_R_COPY)); +#endif } SERV_R_SET_RETURN @@ -119,7 +150,7 @@ copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { len += strlen(se->s_proto) + 1; len += numptr * sizeof(char*); - if (len > buflen) { + if (len > (int)buflen) { errno = ERANGE; return (SERV_R_BAD); } @@ -201,6 +232,6 @@ copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { } #endif /* !SERVENT_DATA */ #else /*SERV_R_RETURN */ - static int getservent_r_unknown_systemm = 0; + static int getservent_r_unknown_system = 0; #endif /*SERV_R_RETURN */ #endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/contrib/bind/lib/irs/hesiod.c b/contrib/bind/lib/irs/hesiod.c index 40826eb..2b08911 100644 --- a/contrib/bind/lib/irs/hesiod.c +++ b/contrib/bind/lib/irs/hesiod.c @@ -1,5 +1,5 @@ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie Exp $"; +static const char rcsid[] = "$Id: hesiod.c,v 1.22 2001/05/29 05:48:55 marka Exp $"; #endif /* @@ -259,6 +259,8 @@ void hesiod_free_list(void *context, char **list) { char **p; + UNUSED(context); + for (p = list; *p; p++) free(*p); free(list); diff --git a/contrib/bind/lib/irs/irp.c b/contrib/bind/lib/irs/irp.c index a6c8f4f..fa28b3f 100644 --- a/contrib/bind/lib/irs/irp.c +++ b/contrib/bind/lib/irs/irp.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: irp.c,v 8.6 2000/02/04 08:28:33 vixie Exp $"; +static const char rcsid[] = "$Id: irp.c,v 8.8 2001/09/25 04:50:29 marka Exp $"; #endif /* Imports */ @@ -84,6 +84,8 @@ irs_irp_acc(const char *options) { struct irs_acc *acc; struct irp_p *irp; + UNUSED(options); + if (!(acc = memget(sizeof *acc))) { errno = ENOMEM; return (NULL); @@ -387,9 +389,9 @@ irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen) { code = 0; } else if (text != NULL && textlen > 0) { p = line; - while (isspace(*p)) p++; - while (isdigit(*p)) p++; - while (isspace(*p)) p++; + while (isspace((unsigned char)*p)) p++; + while (isdigit((unsigned char)*p)) p++; + while (isspace((unsigned char)*p)) p++; strncpy(text, p, textlen - 1); p[textlen - 1] = '\0'; } @@ -537,7 +539,8 @@ irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) { va_start(ap, fmt); todo = vsprintf(buffer, fmt, ap); - if (todo > sizeof buffer - 2) { + va_end(ap); + if (todo > (int)sizeof(buffer) - 3) { syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()"); exit(1); } @@ -559,7 +562,6 @@ irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) { } todo -= i; } - va_end(ap); return (0); } diff --git a/contrib/bind/lib/irs/irp_gr.c b/contrib/bind/lib/irs/irp_gr.c index 4e2a28c..c235e19 100644 --- a/contrib/bind/lib/irs/irp_gr.c +++ b/contrib/bind/lib/irs/irp_gr.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: irp_gr.c,v 8.1 1999/01/18 07:46:53 vixie Exp $"; +static const char rcsid[] = "$Id: irp_gr.c,v 8.3 2001/05/29 05:48:57 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* extern */ @@ -285,7 +285,7 @@ gr_bygid(struct irs_gr *this, gid_t gid) { int code; char text[256]; - if (gr->gr_name != NULL && gr->gr_gid == gid) { + if (gr->gr_name != NULL && (gid_t)gr->gr_gid == gid) { return (gr); } @@ -397,6 +397,9 @@ free_group(struct group *gr) { for (p = gr->gr_mem ; p != NULL && *p != NULL ; p++) free(*p); + if (gr->gr_mem) + free(gr->gr_mem); + if (p != NULL) free(p); } diff --git a/contrib/bind/lib/irs/irp_ho.c b/contrib/bind/lib/irs/irp_ho.c index 7bfd0e2..2124017 100644 --- a/contrib/bind/lib/irs/irp_ho.c +++ b/contrib/bind/lib/irs/irp_ho.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: irp_ho.c,v 8.2 1999/10/13 16:39:31 vixie Exp $"; +static const char rcsid[] = "$Id: irp_ho.c,v 8.3 2001/05/29 05:48:59 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports. */ @@ -79,7 +79,8 @@ static void ho_rewind(struct irs_ho *this); static void ho_minimize(struct irs_ho *this); static void free_host(struct hostent *ho); - +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); /* Public. */ @@ -121,6 +122,7 @@ irs_irp_ho(struct irs_acc *this) { ho->next = ho_next; ho->rewind = ho_rewind; ho->minimize = ho_minimize; + ho->addrinfo = ho_addrinfo; return (ho); } @@ -416,3 +418,12 @@ free_host(struct hostent *ho) { } } +/* dummy */ +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + UNUSED(this); + UNUSED(name); + UNUSED(pai); + return(NULL); +} diff --git a/contrib/bind/lib/irs/irp_ng.c b/contrib/bind/lib/irs/irp_ng.c index e96f66c..b3cf0f4 100644 --- a/contrib/bind/lib/irs/irp_ng.c +++ b/contrib/bind/lib/irs/irp_ng.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: irp_ng.c,v 8.2 1999/10/13 16:39:31 vixie Exp $"; +static const char rcsid[] = "$Id: irp_ng.c,v 8.3 2001/05/29 05:49:00 marka Exp $"; #endif /* Imports */ @@ -52,7 +52,8 @@ struct pvt { static void ng_rewind(struct irs_ng *, const char*); static void ng_close(struct irs_ng *); -static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_next(struct irs_ng *, const char **, const char **, + const char **); static int ng_test(struct irs_ng *, const char *, const char *, const char *, const char *); @@ -158,7 +159,8 @@ ng_rewind(struct irs_ng *this, const char *group) { /* - * int ng_next(struct irs_ng *this, char **host, char **user, char **domain) + * int ng_next(struct irs_ng *this, const char **host, const char **user, + * const char **domain) * * Notes: * @@ -167,7 +169,9 @@ ng_rewind(struct irs_ng *this, const char *group) { */ static int -ng_next(struct irs_ng *this, char **host, char **user, char **domain) { +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ struct pvt *pvt = (struct pvt *)this->private; int code; char *body = NULL; @@ -224,6 +228,8 @@ ng_test(struct irs_ng *this, const char *name, char text[256]; int rval = 0; + UNUSED(name); + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { return (0); } diff --git a/contrib/bind/lib/irs/irp_p.h b/contrib/bind/lib/irs/irp_p.h index adf8174..0f68b28 100644 --- a/contrib/bind/lib/irs/irp_p.h +++ b/contrib/bind/lib/irs/irp_p.h @@ -16,7 +16,7 @@ */ /* - * $Id: irp_p.h,v 8.1 1999/01/18 07:46:54 vixie Exp $ + * $Id: irp_p.h,v 8.2 2001/08/10 02:40:52 marka Exp $ */ #ifndef _IRP_P_H_INCLUDED @@ -53,7 +53,7 @@ char *irs_irp_read_body(struct irp_p *pvt, size_t *size); int irs_irp_get_full_response(struct irp_p *pvt, int *code, char *text, size_t textlen, char **body, size_t *bodylen); -int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...); +int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); extern int irp_log_errors; diff --git a/contrib/bind/lib/irs/irp_pw.c b/contrib/bind/lib/irs/irp_pw.c index f23cb73..b659caa 100644 --- a/contrib/bind/lib/irs/irp_pw.c +++ b/contrib/bind/lib/irs/irp_pw.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: irp_pw.c,v 8.1 1999/01/18 07:46:54 vixie Exp $"; +static const char rcsid[] = "$Id: irp_pw.c,v 8.2 2001/11/01 07:29:26 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Extern */ @@ -340,8 +340,10 @@ free_passwd(struct passwd *pw) { if (pw->pw_passwd != NULL) free(pw->pw_passwd); +#ifdef HAVE_PW_CLASS if (pw->pw_class != NULL) free(pw->pw_class); +#endif if (pw->pw_gecos != NULL) free(pw->pw_gecos); diff --git a/contrib/bind/lib/irs/irpmarshall.c b/contrib/bind/lib/irs/irpmarshall.c index 240bb08..6331ce1 100644 --- a/contrib/bind/lib/irs/irpmarshall.c +++ b/contrib/bind/lib/irs/irpmarshall.c @@ -49,7 +49,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: irpmarshall.c,v 8.6 2000/11/13 05:08:08 vixie Exp $"; +static const char rcsid[] = "$Id: irpmarshall.c,v 8.7 2001/05/29 05:49:01 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #if 0 @@ -139,7 +139,7 @@ irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) { char pwGid[24]; char pwChange[24]; char pwExpire[24]; - char *pwClass; + const char *pwClass; const char *fieldsep = COLONSTR; if (pw == NULL || len == NULL) { @@ -1228,8 +1228,8 @@ irp_marshall_ng(const char *host, const char *user, const char *domain, /* - * int irp_unmarshall_ng(char **host, char **user, char **domain, - * char *buffer) + * int irp_unmarshall_ng(const char **host, const char **user, + * const char **domain, char *buffer) * * notes: * @@ -1243,20 +1243,24 @@ irp_marshall_ng(const char *host, const char *user, const char *domain, */ int -irp_unmarshall_ng(char **host, char **user, char **domain, char *buffer) { +irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp, + char *buffer) +{ char *p, *q; char fieldsep = ','; int myerrno = EINVAL; + char *host, *user, *domain; - if (user == NULL || host == NULL || domain == NULL || buffer == NULL) { + if (userp == NULL || hostp == NULL || + domainp == NULL || buffer == NULL) { errno = EINVAL; return (-1); } - *host = *user = *domain = NULL; + host = user = domain = NULL; p = buffer; - while (isspace(*p)) { + while (isspace((unsigned char)*p)) { p++; } if (*p != '(') { @@ -1269,7 +1273,7 @@ irp_unmarshall_ng(char **host, char **user, char **domain, char *buffer) { if (!*q) { goto error; } else if (q > p + 1) { - *host = strndup(p, q - p); + host = strndup(p, q - p); } p = q + 1; @@ -1282,7 +1286,7 @@ irp_unmarshall_ng(char **host, char **user, char **domain, char *buffer) { if (!*q) { goto error; } - *user = strndup(p, q - p); + user = strndup(p, q - p); } else { p++; } @@ -1296,17 +1300,20 @@ irp_unmarshall_ng(char **host, char **user, char **domain, char *buffer) { if (!*q) { goto error; } - *domain = strndup(p, q - p); + domain = strndup(p, q - p); } + *hostp = host; + *userp = user; + *domainp = domain; return (0); error: errno = myerrno; - if (*host != NULL) free(*host); - if (*user != NULL) free(*user); - if (*domain != NULL) free(*domain); + if (host != NULL) free(host); + if (user != NULL) free(user); + if (domain != NULL) free(domain); return (-1); } @@ -1847,7 +1854,7 @@ getfield(char **res, size_t reslen, char **ptr, char delim) { if (*res == NULL) { *res = strndup(*ptr, q - *ptr); } else { - if (q - *ptr + 1 > reslen) { /* to big for res */ + if ((size_t)(q - *ptr + 1) > reslen) { /* to big for res */ errno = EINVAL; return (NULL); } else { diff --git a/contrib/bind/lib/irs/irs_data.c b/contrib/bind/lib/irs/irs_data.c index 8446c6b..000da0c 100644 --- a/contrib/bind/lib/irs/irs_data.c +++ b/contrib/bind/lib/irs/irs_data.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: irs_data.c,v 1.15 2000/12/23 08:14:54 vixie Exp $"; +static const char rcsid[] = "$Id: irs_data.c,v 1.19 2001/08/20 07:08:41 marka Exp $"; #endif #include "port_before.h" @@ -30,6 +30,7 @@ static const char rcsid[] = "$Id: irs_data.c,v 1.15 2000/12/23 08:14:54 vixie Ex #include <resolv.h> #include <stdio.h> +#include <string.h> #include <isc/memcluster.h> #ifdef DO_PTHREADS @@ -67,7 +68,7 @@ void net_data_destroy(void *p) { struct net_data *net_data = p; - res_nclose(net_data->res); + res_ndestroy(net_data->res); if (net_data->gr != NULL) { (*net_data->gr->close)(net_data->gr); net_data->gr = NULL; @@ -152,7 +153,8 @@ net_data_create(const char *conf_file) { if (net_data->res == NULL) return (NULL); - if (res_ninit(net_data->res) == -1) + if ((net_data->res->options & RES_INIT) == 0 && + res_ninit(net_data->res) == -1) return (NULL); return (net_data); @@ -165,6 +167,7 @@ net_data_minimize(struct net_data *net_data) { res_nclose(net_data->res); } +#ifdef _REENTRANT struct __res_state * __res_state(void) { /* NULL param here means use the default config file. */ @@ -174,6 +177,7 @@ __res_state(void) { return (&_res); } +#endif int * __h_errno(void) { diff --git a/contrib/bind/lib/irs/lcl.c b/contrib/bind/lib/irs/lcl.c index 16e167f..ed9e6b4 100644 --- a/contrib/bind/lib/irs/lcl.c +++ b/contrib/bind/lib/irs/lcl.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: lcl.c,v 1.16 2000/02/28 07:52:16 vixie Exp $"; +static const char rcsid[] = "$Id: lcl.c,v 1.17 2001/05/29 05:49:02 marka Exp $"; #endif /* Imports */ @@ -55,6 +55,8 @@ irs_lcl_acc(const char *options) { struct irs_acc *acc; struct lcl_p *lcl; + UNUSED(options); + if (!(acc = memget(sizeof *acc))) { errno = ENOMEM; return (NULL); diff --git a/contrib/bind/lib/irs/lcl_gr.c b/contrib/bind/lib/irs/lcl_gr.c index acb85ee..7536c27 100644 --- a/contrib/bind/lib/irs/lcl_gr.c +++ b/contrib/bind/lib/irs/lcl_gr.c @@ -49,7 +49,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: lcl_gr.c,v 1.25 1999/10/13 17:11:19 vixie Exp $"; +static const char rcsid[] = "$Id: lcl_gr.c,v 1.26 2001/05/29 05:49:03 marka Exp $"; /* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ /* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ #endif /* LIBC_SCCS and not lint */ @@ -129,6 +129,8 @@ irs_lcl_gr(struct irs_acc *this) { struct irs_gr *gr; struct pvt *pvt; + UNUSED(this); + if (!(gr = memget(sizeof *gr))) { errno = ENOMEM; return (NULL); @@ -313,7 +315,7 @@ grscan(struct irs_gr *this, int search, gid_t gid, const char *name) { continue; } pvt->group.gr_gid = atoi(p); - if (search && name == NULL && pvt->group.gr_gid != gid) + if (search && name == NULL && (gid_t)pvt->group.gr_gid != gid) continue; /* We want this record. */ diff --git a/contrib/bind/lib/irs/lcl_ho.c b/contrib/bind/lib/irs/lcl_ho.c index 5939207..e9685a3 100644 --- a/contrib/bind/lib/irs/lcl_ho.c +++ b/contrib/bind/lib/irs/lcl_ho.c @@ -52,7 +52,7 @@ /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: lcl_ho.c,v 1.25 1999/10/13 17:11:19 vixie Exp $"; +static const char rcsid[] = "$Id: lcl_ho.c,v 1.26 2001/05/29 05:49:04 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports. */ @@ -83,6 +83,7 @@ static const char rcsid[] = "$Id: lcl_ho.c,v 1.25 1999/10/13 17:11:19 vixie Exp #include "irs_p.h" #include "dns_p.h" +#include "lcl_p.h" #ifdef SPRINTF_CHAR # define SPRINTF(x) strlen(sprintf/**/x) @@ -136,6 +137,8 @@ static struct __res_state * ho_res_get(struct irs_ho *this); static void ho_res_set(struct irs_ho *this, struct __res_state *res, void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); static size_t ns_namelen(const char *); static int init(struct irs_ho *this); @@ -153,6 +156,8 @@ irs_lcl_ho(struct irs_acc *this) { struct irs_ho *ho; struct pvt *pvt; + UNUSED(this); + if (!(pvt = memget(sizeof *pvt))) { errno = ENOMEM; return (NULL); @@ -174,6 +179,7 @@ irs_lcl_ho(struct irs_acc *this) { ho->minimize = ho_minimize; ho->res_get = ho_res_get; ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; return (ho); } @@ -257,7 +263,7 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { (!memcmp(uaddr, mapped, sizeof mapped) || !memcmp(uaddr, tunnelled, sizeof tunnelled))) { /* Unmap. */ - addr = (u_char *)addr + sizeof mapped; + addr = (const u_char *)addr + sizeof mapped; uaddr += sizeof mapped; af = AF_INET; len = INADDRSZ; @@ -479,6 +485,73 @@ ho_res_set(struct irs_ho *this, struct __res_state *res, pvt->free_res = free_res; } +struct lcl_res_target { + struct lcl_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct lcl_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /* INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + /* Private. */ static size_t diff --git a/contrib/bind/lib/irs/lcl_ng.c b/contrib/bind/lib/irs/lcl_ng.c index 03acbf6..239b63e 100644 --- a/contrib/bind/lib/irs/lcl_ng.c +++ b/contrib/bind/lib/irs/lcl_ng.c @@ -16,7 +16,7 @@ */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: lcl_ng.c,v 1.16 1999/10/13 16:39:32 vixie Exp $"; +static const char rcsid[] = "$Id: lcl_ng.c,v 1.17 2001/05/29 05:49:05 marka Exp $"; #endif /* Imports */ @@ -39,6 +39,7 @@ static const char rcsid[] = "$Id: lcl_ng.c,v 1.16 1999/10/13 16:39:32 vixie Exp #include "port_after.h" #include "irs_p.h" +#include "lcl_p.h" /* Definitions */ @@ -88,7 +89,8 @@ struct pvt { static void ng_rewind(struct irs_ng *, const char*); static void ng_close(struct irs_ng *); -static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); static int ng_test(struct irs_ng *, const char *, const char *, const char *, const char *); @@ -104,6 +106,8 @@ struct irs_ng * irs_lcl_ng(struct irs_acc *this) { struct irs_ng *ng; struct pvt *pvt; + + UNUSED(this); if (!(ng = memget(sizeof *ng))) { errno = ENOMEM; @@ -174,7 +178,9 @@ ng_rewind(struct irs_ng *this, const char *group) { * Get the next netgroup off the list. */ static int -ng_next(struct irs_ng *this, char **host, char **user, char **domain) { +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ struct pvt *pvt = (struct pvt *)this->private; if (pvt->nextgrp) { @@ -194,7 +200,7 @@ static int ng_test(struct irs_ng *this, const char *name, const char *host, const char *user, const char *domain) { - char *ng_host, *ng_user, *ng_domain; + const char *ng_host, *ng_user, *ng_domain; ng_rewind(this, name); while (ng_next(this, &ng_host, &ng_user, &ng_domain)) @@ -350,7 +356,7 @@ parse_netgrp(struct irs_ng *this, const char *group) { static struct linelist * read_for_group(struct irs_ng *this, const char *group) { struct pvt *pvt = (struct pvt *)this->private; - char *pos, *spos, *linep, *olinep; + char *pos, *spos, *linep = NULL, *olinep; int len, olen, cont; struct linelist *lp; char line[LINSIZ + 1]; diff --git a/contrib/bind/lib/irs/lcl_nw.c b/contrib/bind/lib/irs/lcl_nw.c index 0d41ec4..457621b 100644 --- a/contrib/bind/lib/irs/lcl_nw.c +++ b/contrib/bind/lib/irs/lcl_nw.c @@ -49,7 +49,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: lcl_nw.c,v 1.21 1999/10/15 19:49:10 vixie Exp $"; +static const char rcsid[] = "$Id: lcl_nw.c,v 1.22 2001/05/29 05:49:07 marka Exp $"; /* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ /* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ #endif /* LIBC_SCCS and not lint */ @@ -122,6 +122,8 @@ irs_lcl_nw(struct irs_acc *this) { struct irs_nw *nw; struct pvt *pvt; + UNUSED(this); + if (!(pvt = memget(sizeof *pvt))) { errno = ENOMEM; return (NULL); diff --git a/contrib/bind/lib/irs/lcl_pw.c b/contrib/bind/lib/irs/lcl_pw.c index 2655677..31c1ed0 100644 --- a/contrib/bind/lib/irs/lcl_pw.c +++ b/contrib/bind/lib/irs/lcl_pw.c @@ -49,7 +49,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: lcl_pw.c,v 1.19 1999/01/18 07:46:57 vixie Exp $"; +static const char rcsid[] = "$Id: lcl_pw.c,v 1.20 2001/05/29 05:49:08 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Extern */ @@ -119,6 +119,8 @@ struct irs_pw * irs_lcl_pw(struct irs_acc *this) { struct irs_pw *pw; struct pvt *pvt; + + UNUSED(this); if (!(pw = memget(sizeof *pw))) { errno = ENOMEM; diff --git a/contrib/bind/lib/irs/lcl_sv.c b/contrib/bind/lib/irs/lcl_sv.c index 7e5bec9..d94366b 100644 --- a/contrib/bind/lib/irs/lcl_sv.c +++ b/contrib/bind/lib/irs/lcl_sv.c @@ -49,7 +49,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: lcl_sv.c,v 1.20 1999/10/07 20:44:03 vixie Exp $"; +static const char rcsid[] = "$Id: lcl_sv.c,v 1.22 2001/06/18 14:43:59 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* extern */ @@ -122,6 +122,8 @@ struct irs_sv * irs_lcl_sv(struct irs_acc *this) { struct irs_sv *sv; struct pvt *pvt; + + UNUSED(this); if ((sv = memget(sizeof *sv)) == NULL) { errno = ENOMEM; @@ -287,13 +289,10 @@ sv_next(struct irs_sv *this) { struct pvt *pvt = (struct pvt *)this->private; #ifdef IRS_LCL_SV_DB - if (pvt->dbh != NULL) - NULL; - else + if (pvt->dbh == NULL && pvt->sv.fp == NULL) +#else + if (pvt->sv.fp == NULL) #endif - if (pvt->sv.fp != NULL) - NULL; - else sv_rewind(this); #ifdef IRS_LCL_SV_DB @@ -395,7 +394,7 @@ sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) { return (NULL); sv->serv.s_port = ((u_short *)key->data)[1]; n = strlen(p) + 1; - if (n > sizeof(sv->line)) { + if ((size_t)n > sizeof(sv->line)) { n = sizeof(sv->line); } memcpy(sv->line, p, n); diff --git a/contrib/bind/lib/irs/nis.c b/contrib/bind/lib/irs/nis.c index e19068a..aa10fba 100644 --- a/contrib/bind/lib/irs/nis.c +++ b/contrib/bind/lib/irs/nis.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nis.c,v 1.14 2000/02/28 07:52:16 vixie Exp $"; +static const char rcsid[] = "$Id: nis.c,v 1.15 2001/05/29 05:49:11 marka Exp $"; #endif /* Imports */ @@ -63,6 +63,8 @@ irs_nis_acc(const char *options) { struct irs_acc *acc; char *domain; + UNUSED(options); + if (yp_get_default_domain(&domain) != 0) return (NULL); if (!(nis = memget(sizeof *nis))) { diff --git a/contrib/bind/lib/irs/nis_gr.c b/contrib/bind/lib/irs/nis_gr.c index 713437a..b4e0945 100644 --- a/contrib/bind/lib/irs/nis_gr.c +++ b/contrib/bind/lib/irs/nis_gr.c @@ -49,7 +49,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nis_gr.c,v 1.20 1999/01/30 00:53:16 vixie Exp $"; +static const char rcsid[] = "$Id: nis_gr.c,v 1.21 2001/05/29 05:49:12 marka Exp $"; /* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ /* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ #endif /* LIBC_SCCS and not lint */ @@ -217,7 +217,7 @@ gr_byname(struct irs_gr *this, const char *name) { int r; nisfree(pvt, do_val); - r = yp_match(pvt->nis_domain, group_byname, (char *)name, strlen(name), + r = yp_match(pvt->nis_domain, group_byname, name, strlen(name), &pvt->curval_data, &pvt->curval_len); if (r != 0) { errno = ENOENT; @@ -252,6 +252,7 @@ gr_rewind(struct irs_gr *this) { static void gr_minimize(struct irs_gr *this) { + UNUSED(this); /* NOOP */ } @@ -260,7 +261,7 @@ gr_minimize(struct irs_gr *this) { static struct group * makegroupent(struct irs_gr *this) { struct pvt *pvt = (struct pvt *)this->private; - int num_members = 0; + unsigned int num_members = 0; char *cp, **new; u_long t; diff --git a/contrib/bind/lib/irs/nis_ho.c b/contrib/bind/lib/irs/nis_ho.c index 07d2274..72a8d17 100644 --- a/contrib/bind/lib/irs/nis_ho.c +++ b/contrib/bind/lib/irs/nis_ho.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nis_ho.c,v 1.16 1999/10/13 16:39:32 vixie Exp $"; +static const char rcsid[] = "$Id: nis_ho.c,v 1.18 2001/06/18 14:44:00 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports */ @@ -103,6 +103,8 @@ static struct __res_state * ho_res_get(struct irs_ho *this); static void ho_res_set(struct irs_ho *this, struct __res_state *res, void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); static struct hostent * makehostent(struct irs_ho *this); static void nisfree(struct pvt *, enum do_what); @@ -138,6 +140,7 @@ irs_nis_ho(struct irs_acc *this) { ho->minimize = ho_minimize; ho->res_set = ho_res_set; ho->res_get = ho_res_get; + ho->addrinfo = ho_addrinfo; return (ho); } @@ -175,13 +178,17 @@ static struct hostent * ho_byname2(struct irs_ho *this, const char *name, int af) { struct pvt *pvt = (struct pvt *)this->private; int r; + char *tmp; + + UNUSED(af); if (init(this) == -1) return (NULL); nisfree(pvt, do_val); - r = yp_match(pvt->nis_domain, hosts_byname, (char *)name, strlen(name), - &pvt->curval_data, &pvt->curval_len); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, hosts_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); if (r != 0) { RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); return (NULL); @@ -203,7 +210,7 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { (!memcmp(uaddr, mapped, sizeof mapped) || !memcmp(uaddr, tunnelled, sizeof tunnelled))) { /* Unmap. */ - addr = (u_char *)addr + sizeof mapped; + addr = (const u_char *)addr + sizeof mapped; uaddr += sizeof mapped; af = AF_INET; len = INADDRSZ; @@ -307,6 +314,72 @@ ho_res_set(struct irs_ho *this, struct __res_state *res, pvt->free_res = free_res; } +struct nis_res_target { + struct nis_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct nis_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /* INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + /* Private */ static struct hostent * diff --git a/contrib/bind/lib/irs/nis_ng.c b/contrib/bind/lib/irs/nis_ng.c index 88d97ff..a42d994 100644 --- a/contrib/bind/lib/irs/nis_ng.c +++ b/contrib/bind/lib/irs/nis_ng.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nis_ng.c,v 1.16 1999/01/18 07:46:58 vixie Exp $"; +static const char rcsid[] = "$Id: nis_ng.c,v 1.17 2001/05/29 05:49:14 marka Exp $"; #endif /* Imports */ @@ -78,7 +78,8 @@ static /*const*/ char netgroup_map[] = "netgroup"; /* Forward */ static void ng_close(struct irs_ng *); -static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); static int ng_test(struct irs_ng *, const char *, const char *, const char *, const char *); @@ -129,14 +130,14 @@ ng_close(struct irs_ng *this) { } static int -ng_next(struct irs_ng *this, char **host, char **user, char **domain) { +ng_next(struct irs_ng *this, const char **host, const char **user, const char **domain) { struct pvt *pvt = (struct pvt *)this->private; if (!pvt->cur) return (0); - *host = (/*const*/ char *)pvt->cur->host; - *user = (/*const*/ char *)pvt->cur->user; - *domain = (/*const*/ char *)pvt->cur->domain; + *host = pvt->cur->host; + *user = pvt->cur->user; + *domain = pvt->cur->domain; pvt->cur = pvt->cur->next; return (1); } @@ -178,6 +179,7 @@ ng_rewind(struct irs_ng *this, const char *name) { static void ng_minimize(struct irs_ng *this) { + UNUSED(this); /* NOOP */ } @@ -188,13 +190,15 @@ add_group_to_list(struct pvt *pvt, const char *name, int len) { char *vdata, *cp, *np; struct tmpgrp *tmp; int vlen, r; + char *nametmp; /* Don't add the same group to the list more than once. */ for (tmp = pvt->tmp; tmp; tmp = tmp->next) if (!strcmp(tmp->name, name)) return; - r = yp_match(pvt->nis_domain, netgroup_map, (char *)name, len, + DE_CONST(name, nametmp); + r = yp_match(pvt->nis_domain, netgroup_map, nametmp, len, &vdata, &vlen); if (r == 0) { cp = vdata; diff --git a/contrib/bind/lib/irs/nis_nw.c b/contrib/bind/lib/irs/nis_nw.c index 72ec391..bc659f3 100644 --- a/contrib/bind/lib/irs/nis_nw.c +++ b/contrib/bind/lib/irs/nis_nw.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nis_nw.c,v 1.15 1999/01/18 07:46:58 vixie Exp $"; +static const char rcsid[] = "$Id: nis_nw.c,v 1.16 2001/05/29 05:49:15 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports */ @@ -187,6 +187,7 @@ static struct nwent * nw_byname(struct irs_nw *this, const char *name, int af) { struct pvt *pvt = (struct pvt *)this->private; int r; + char *tmp; if (init(this) == -1) return (NULL); @@ -197,8 +198,9 @@ nw_byname(struct irs_nw *this, const char *name, int af) { return (NULL); } nisfree(pvt, do_val); - r = yp_match(pvt->nis_domain, networks_byname, (char *)name, - strlen(name), &pvt->curval_data, &pvt->curval_len); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, networks_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); if (r != 0) { RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); return (NULL); diff --git a/contrib/bind/lib/irs/nis_pr.c b/contrib/bind/lib/irs/nis_pr.c index 8dff084..bc09075 100644 --- a/contrib/bind/lib/irs/nis_pr.c +++ b/contrib/bind/lib/irs/nis_pr.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nis_pr.c,v 1.13 1999/01/18 07:46:59 vixie Exp $"; +static const char rcsid[] = "$Id: nis_pr.c,v 1.14 2001/05/29 05:49:16 marka Exp $"; #endif /* Imports */ @@ -132,10 +132,12 @@ static struct protoent * pr_byname(struct irs_pr *this, const char *name) { struct pvt *pvt = (struct pvt *)this->private; int r; + char *tmp; nisfree(pvt, do_val); - r = yp_match(pvt->nis_domain, protocols_byname, (char *)name, - strlen(name), &pvt->curval_data, &pvt->curval_len); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, protocols_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); if (r != 0) { errno = ENOENT; return (NULL); @@ -204,6 +206,7 @@ pr_rewind(struct irs_pr *this) { static void pr_minimize(struct irs_pr *this) { + UNUSED(this); /* NOOP */ } @@ -220,9 +223,9 @@ makeprotoent(struct irs_pr *this) { pvt->prbuf = pvt->curval_data; pvt->curval_data = NULL; - for (p = pvt->prbuf; *p && *p != '#'; p++) - NULL; - while (p > pvt->prbuf && isspace(p[-1])) + for (p = pvt->prbuf; *p && *p != '#';) + p++; + while (p > pvt->prbuf && isspace((unsigned char)(p[-1]))) p--; *p = '\0'; @@ -230,16 +233,16 @@ makeprotoent(struct irs_pr *this) { n = m = 0; pvt->proto.p_name = p; - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) p++; if (!*p) return (NULL); *p++ = '\0'; - while (*p && isspace(*p)) + while (*p && isspace((unsigned char)*p)) p++; pvt->proto.p_proto = atoi(p); - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) p++; *p++ = '\0'; @@ -255,7 +258,7 @@ makeprotoent(struct irs_pr *this) { pvt->proto.p_aliases = t; } pvt->proto.p_aliases[n++] = p; - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) p++; if (*p) *p++ = '\0'; diff --git a/contrib/bind/lib/irs/nis_pw.c b/contrib/bind/lib/irs/nis_pw.c index ce90f20..1d345a5 100644 --- a/contrib/bind/lib/irs/nis_pw.c +++ b/contrib/bind/lib/irs/nis_pw.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nis_pw.c,v 1.16 1999/01/30 00:53:16 vixie Exp $"; +static const char rcsid[] = "$Id: nis_pw.c,v 1.17 2001/05/29 05:49:18 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports */ @@ -169,9 +169,11 @@ static struct passwd * pw_byname(struct irs_pw *this, const char *name) { struct pvt *pvt = (struct pvt *)this->private; int r; + char *tmp; nisfree(pvt, do_val); - r = yp_match(pvt->nis_domain, passwd_byname, name, strlen(name), + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, passwd_byname, tmp, strlen(tmp), &pvt->curval_data, &pvt->curval_len); if (r != 0) { errno = ENOENT; @@ -206,6 +208,7 @@ pw_rewind(struct irs_pw *this) { static void pw_minimize(struct irs_pw *this) { + UNUSED(this); /* NOOP */ } @@ -226,7 +229,9 @@ makepasswdent(struct irs_pw *this) { pvt->passwd.pw_name = cp; if (!(cp = strchr(cp, ':'))) goto cleanup; +#ifdef HAS_PW_CLASS pvt->passwd.pw_class = cp; /* Needs to point at a \0. */ +#endif *cp++ = '\0'; pvt->passwd.pw_passwd = cp; diff --git a/contrib/bind/lib/irs/nis_sv.c b/contrib/bind/lib/irs/nis_sv.c index 8810fd2..40bfda5 100644 --- a/contrib/bind/lib/irs/nis_sv.c +++ b/contrib/bind/lib/irs/nis_sv.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nis_sv.c,v 1.14 1999/01/18 07:46:59 vixie Exp $"; +static const char rcsid[] = "$Id: nis_sv.c,v 1.15 2001/05/29 05:49:19 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports */ @@ -205,6 +205,7 @@ sv_next(struct irs_sv *this) { static void sv_minimize(struct irs_sv *this) { + UNUSED(this); /* NOOP */ } @@ -242,7 +243,7 @@ makeservent(struct irs_sv *this) { pvt->serv.s_port = htons((u_short) atoi(p)); pvt->serv.s_proto = NULL; - while (*p && !isspace(*p)) + while (*p && !isspace((unsigned char)*p)) if (*p++ == '/') pvt->serv.s_proto = p; if (!pvt->serv.s_proto) diff --git a/contrib/bind/lib/irs/nul_ng.c b/contrib/bind/lib/irs/nul_ng.c index cc5c801..1a61d8c 100644 --- a/contrib/bind/lib/irs/nul_ng.c +++ b/contrib/bind/lib/irs/nul_ng.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nul_ng.c,v 1.10 1999/01/18 07:46:59 vixie Exp $"; +static const char rcsid[] = "$Id: nul_ng.c,v 1.11 2001/05/29 05:49:20 marka Exp $"; #endif /* @@ -49,7 +49,8 @@ static const char rcsid[] = "$Id: nul_ng.c,v 1.10 1999/01/18 07:46:59 vixie Exp /* Forward. */ static void ng_close(struct irs_ng *); -static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); static int ng_test(struct irs_ng *, const char *, const char *, const char *, const char *); @@ -62,6 +63,8 @@ struct irs_ng * irs_nul_ng(struct irs_acc *this) { struct irs_ng *ng; + UNUSED(this); + if (!(ng = memget(sizeof *ng))) { errno = ENOMEM; return (NULL); @@ -85,7 +88,13 @@ ng_close(struct irs_ng *this) { /* ARGSUSED */ static int -ng_next(struct irs_ng *this, char **host, char **user, char **domain) { +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + UNUSED(this); + UNUSED(host); + UNUSED(user); + UNUSED(domain); errno = ENOENT; return (-1); } @@ -94,16 +103,24 @@ static int ng_test(struct irs_ng *this, const char *name, const char *user, const char *host, const char *domain) { + UNUSED(this); + UNUSED(name); + UNUSED(user); + UNUSED(host); + UNUSED(domain); errno = ENODEV; return (-1); } static void ng_rewind(struct irs_ng *this, const char *netgroup) { + UNUSED(this); + UNUSED(netgroup); /* NOOP */ } static void ng_minimize(struct irs_ng *this) { + UNUSED(this); /* NOOP */ } diff --git a/contrib/bind/lib/irs/util.c b/contrib/bind/lib/irs/util.c index 1d097c6..e37f4d9 100644 --- a/contrib/bind/lib/irs/util.c +++ b/contrib/bind/lib/irs/util.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: util.c,v 1.11 2000/02/04 08:28:33 vixie Exp $"; +static const char rcsid[] = "$Id: util.c,v 1.12 2001/05/29 05:49:21 marka Exp $"; #endif #include "port_before.h" @@ -89,7 +89,7 @@ make_group_list(struct irs_gr *this, const char *name, */ (*this->rewind)(this); while ((grp = (*this->next)(this)) != NULL) { - if (grp->gr_gid == basegid) + if ((gid_t)grp->gr_gid == basegid) continue; for (i = 0; grp->gr_mem[i]; i++) { if (!strcmp(grp->gr_mem[i], name)) { |