diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-10-26 08:34:38 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-10-26 08:34:38 +0000 |
commit | 5ae19a502312bac2403f8aaaf743a9e9e6b1fdf2 (patch) | |
tree | 1840b3f415fab01157e95fc22c69973f46a28bab /resolv | |
parent | 4d54786a9b982820570e616c1b5669d5b169fd00 (diff) | |
download | glibc-5ae19a502312bac2403f8aaaf743a9e9e6b1fdf2.tar glibc-5ae19a502312bac2403f8aaaf743a9e9e6b1fdf2.tar.gz glibc-5ae19a502312bac2403f8aaaf743a9e9e6b1fdf2.tar.bz2 glibc-5ae19a502312bac2403f8aaaf743a9e9e6b1fdf2.zip |
Update.
2003-10-26 Ulrich Drepper <drepper@redhat.com>
* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyaddr_r): Default
reverse lookup format for IPv6 addresses is using bitfields and
.ip6.arpa suffix.
* resolv/ns_name.c: Implement encoding and decoding bitfields in
hex format.
Diffstat (limited to 'resolv')
-rw-r--r-- | resolv/ns_name.c | 99 | ||||
-rw-r--r-- | resolv/nss_dns/dns-host.c | 15 |
2 files changed, 101 insertions, 13 deletions
diff --git a/resolv/ns_name.c b/resolv/ns_name.c index cb6393527f..a4f066c9e2 100644 --- a/resolv/ns_name.c +++ b/resolv/ns_name.c @@ -24,6 +24,7 @@ static const char rcsid[] = "$BINDId: ns_name.c,v 8.15 2000/03/30 22:53:46 vixie #include <netinet/in.h> #include <arpa/nameser.h> +#include <ctype.h> #include <errno.h> #include <resolv.h> #include <string.h> @@ -64,7 +65,7 @@ ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { eom = dst + dstsiz; while ((n = *cp++) != 0) { - if ((n & NS_CMPRSFLGS) != 0) { + if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) { /* Some kind of compression pointer. */ __set_errno (EMSGSIZE); return (-1); @@ -76,6 +77,29 @@ ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { } *dn++ = '.'; } + + if (n == 0x41) { + n = *cp++ / 8; + if (dn + n * 2 + 4 >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *dn++ = '\\'; + *dn++ = '['; + *dn++ = 'x'; + + while (n-- > 0) { + c = *cp++; + unsigned u = c >> 4; + *dn++ = u > 9 ? 'a' + u - 10 : '0' + u; + u = c & 0xf; + *dn++ = u > 9 ? 'a' + u - 10 : '0' + u; + } + + *dn++ = ']'; + continue; + } + if (dn + n >= eom) { __set_errno (EMSGSIZE); return (-1); @@ -165,6 +189,43 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { return (-1); } c = n; + } else if (c == '[' && label == bp - 1 && *src == 'x') { + /* Theoretically we would have to handle \[o + as well but we do not since we do not need + it internally. */ + *label = 0x41; + label = bp++; + /* Another simplification: always assume + 128 bit number. */ + if (bp + 16 >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + ++src; + while (isxdigit (*src)) { + n = *src > '9' ? *src - 'a' + 10 : *src - '0'; + ++src; + if (! isxdigit(*src)) { + __set_errno (EMSGSIZE); + return (-1); + } + n <<= 4; + n += *src > '9' ? *src - 'a' + 10 : *src - '0'; + *bp++ = n; + ++src; + } + *label = (bp - label - 1) * 8; + if (*src++ != ']' || *src++ != '.') { + __set_errno (EMSGSIZE); + return (-1); + } + escaped = 0; + label = bp++; + if (bp >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + continue; } escaped = 0; } else if (c == '\\') { @@ -303,6 +364,20 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, while ((n = *srcp++) != 0) { /* Check for indirection. */ switch (n & NS_CMPRSFLGS) { + case 0x40: + if (n == 0x41) { + if (dstp + 1 >= dstlim) { + __set_errno (EMSGSIZE); + return (-1); + } + *dstp++ = 0x41; + n = *srcp++ / 8; + ++checked; + } else { + __set_errno (EMSGSIZE); + return (-1); /* flag error */ + } + /* FALLTHROUGH */ case 0: /* Limit checks. */ if (dstp + n + 1 >= dstlim || srcp + n >= eom) { @@ -310,9 +385,7 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, return (-1); } checked += n + 1; - *dstp++ = n; - memcpy(dstp, srcp, n); - dstp += n; + dstp = mempcpy(dstp, srcp - 1, n + 1); srcp += n; break; @@ -394,10 +467,12 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz, l = 0; do { n = *srcp; - if ((n & NS_CMPRSFLGS) != 0) { + if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) { __set_errno (EMSGSIZE); return (-1); } + if (n == 0x41) + n = *++srcp / 8; l += n + 1; if (l > MAXCDNAME) { __set_errno (EMSGSIZE); @@ -411,7 +486,7 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz, do { /* Look to see if we can use pointers. */ n = *srcp; - if (n != 0 && msg != NULL) { + if (n != 0 && n != 0x41 && msg != NULL) { l = dn_find(srcp, msg, (const u_char * const *)dnptrs, (const u_char * const *)lpp); if (l >= 0) { @@ -431,9 +506,15 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz, } } /* copy label to buffer */ - if (n & NS_CMPRSFLGS) { /* Should not happen. */ + if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) { /* Should not happen. */ goto cleanup; } + if (n == 0x41) { + n = *++srcp / 8; + if (dstp + 1 >= eob) + goto cleanup; + *dstp++ = 0x41; + } if (dstp + 1 + n >= eob) { goto cleanup; } @@ -448,7 +529,7 @@ cleanup: *lpp = NULL; __set_errno (EMSGSIZE); return (-1); - } + } return (dstp - dst); } @@ -466,7 +547,7 @@ ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, { u_char tmp[NS_MAXCDNAME]; int n; - + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) return (-1); if (ns_name_ntop(tmp, dst, dstsiz) == -1) diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c index f362dd746d..bde45ca873 100644 --- a/resolv/nss_dns/dns-host.c +++ b/resolv/nss_dns/dns-host.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2000, 2001, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1996-2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -305,10 +305,14 @@ _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af, (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff)); break; case AF_INET6: + /* XXX Maybe we need an option to select whether to use the nibble + or the bitfield form. The RFC requires the bitfield form so + we use it. */ qp = qbuf; - for (n = IN6ADDRSZ - 1; n >= 0; n--) - qp += sprintf (qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf); - strcpy (qp, "ip6.arpa"); + qp = stpcpy (qbuf, "\\[x"); + for (n = 0; n < IN6ADDRSZ; ++n) + qp += sprintf (qp, "%02hhx", uaddr[n]); + strcpy (qp, "].ip6.arpa"); break; default: /* Cannot happen. */ @@ -321,6 +325,9 @@ _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af, 1024, &host_buffer.ptr); if (n < 0 && af == AF_INET6) { + qp = qbuf; + for (n = IN6ADDRSZ - 1; n >= 0; n--) + qp += sprintf (qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf); strcpy (qp, "ip6.int"); n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, host_buffer.buf != orig_host_buffer |