diff options
author | ume <ume@FreeBSD.org> | 2005-04-29 19:55:23 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2005-04-29 19:55:23 +0000 |
commit | 5acac5def141d4709680819f06b1a8c4fb8c641a (patch) | |
tree | ac7d19999bfe61a1d5647789758e160633cdc4c0 /lib | |
parent | bb1e0b257abb86c2b6efe470eaa92b65967e6d1d (diff) | |
download | FreeBSD-src-5acac5def141d4709680819f06b1a8c4fb8c641a.zip FreeBSD-src-5acac5def141d4709680819f06b1a8c4fb8c641a.tar.gz |
- do validation check and IPv4-mapped IPv6 address handling before
any query.
- don't query against IPv6 link-local address.
- use IN6_IS_ADDR_V4{MAPPED,COMPAT} macros.
- use memcpy() instead of bcopy().
Inspired by: NetBSD
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/gethostbydns.c | 40 | ||||
-rw-r--r-- | lib/libc/net/gethostnamadr.c | 37 |
2 files changed, 41 insertions, 36 deletions
diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c index bd4d02d..6cb43f0 100644 --- a/lib/libc/net/gethostbydns.c +++ b/lib/libc/net/gethostbydns.c @@ -387,7 +387,7 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, cp += n; continue; } - bcopy(cp, *hap++ = bp, n); + memcpy(*hap++ = bp, cp, n); bp += n; cp += n; if (cp != erdata) { @@ -517,14 +517,11 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap) int _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) { - const char *addr; /* XXX should have been def'd as u_char! */ + const u_char *uaddr; int len, af; struct hostent *he; struct hostent_data *hed; - const u_char *uaddr; - static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; - static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; - int n, size, error; + int n, error; querybuf *buf; char qbuf[MAXDNAME+1], *qp; #ifdef SUNSECURITY @@ -535,8 +532,7 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) char hname2[MAXDNAME+1], numaddr[46]; #endif /*SUNSECURITY*/ - addr = va_arg(ap, const char *); - uaddr = (const u_char *)addr; + uaddr = va_arg(ap, const u_char *); len = va_arg(ap, int); af = va_arg(ap, int); he = va_arg(ap, struct hostent *); @@ -546,32 +542,6 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) h_errno = NETDB_INTERNAL; return NS_UNAVAIL; } - if (af == AF_INET6 && len == IN6ADDRSZ && - (!bcmp(uaddr, mapped, sizeof mapped) || - !bcmp(uaddr, tunnelled, sizeof tunnelled))) { - /* Unmap. */ - addr += sizeof mapped; - uaddr += sizeof mapped; - af = AF_INET; - len = INADDRSZ; - } - switch (af) { - case AF_INET: - size = INADDRSZ; - break; - case AF_INET6: - size = IN6ADDRSZ; - break; - default: - errno = EAFNOSUPPORT; - h_errno = NETDB_INTERNAL; - return NS_UNAVAIL; - } - if (size != len) { - errno = EINVAL; - h_errno = NETDB_INTERNAL; - return NS_UNAVAIL; - } switch (af) { case AF_INET: (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", @@ -651,7 +621,7 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) #endif /*SUNSECURITY*/ he->h_addrtype = af; he->h_length = len; - bcopy(addr, hed->host_addr, len); + memcpy(hed->host_addr, uaddr, len); hed->h_addr_ptrs[0] = (char *)hed->host_addr; hed->h_addr_ptrs[1] = NULL; if (af == AF_INET && (_res.options & RES_USE_INET6)) { diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c index 78b3a7a..8aae192 100644 --- a/lib/libc/net/gethostnamadr.c +++ b/lib/libc/net/gethostnamadr.c @@ -252,6 +252,9 @@ int gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he, struct hostent_data *hed) { + const u_char *uaddr = (const u_char *)addr; + const struct in6_addr *addr6; + socklen_t size; int rval; static const ns_dtab dtab[] = { @@ -261,8 +264,40 @@ gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he, { 0 } }; + if (af == AF_INET6 && len == IN6ADDRSZ) { + addr6 = (const struct in6_addr *)(const void *)uaddr; + if (IN6_IS_ADDR_LINKLOCAL(addr6)) { + h_errno = HOST_NOT_FOUND; + return -1; + } + if (IN6_IS_ADDR_V4MAPPED(addr6) || + IN6_IS_ADDR_V4COMPAT(addr6)) { + /* Unmap. */ + uaddr += IN6ADDRSZ - INADDRSZ; + af = AF_INET; + len = INADDRSZ; + } + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + h_errno = NETDB_INTERNAL; + return -1; + } + if (size != len) { + errno = EINVAL; + h_errno = NETDB_INTERNAL; + return -1; + } + rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyaddr", - default_src, addr, len, af, he, hed); + default_src, uaddr, len, af, he, hed); return (rval == NS_SUCCESS) ? 0 : -1; } |