- 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
This commit is contained in:
Hajimu UMEMOTO 2005-04-29 19:55:23 +00:00
parent 5d1ae027f0
commit 2c08ac2b38
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=145687
2 changed files with 41 additions and 36 deletions

View file

@ -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)) {

View file

@ -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;
}