Update.
authorUlrich Drepper <drepper@redhat.com>
Sun, 26 Oct 2003 08:34:38 +0000 (08:34 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sun, 26 Oct 2003 08:34:38 +0000 (08:34 +0000)
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.

ChangeLog
resolv/ns_name.c
resolv/nss_dns/dns-host.c

index 4a512a9..b619cc5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+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.
+
 2003-10-23  Jakub Jelinek  <jakub@redhat.com>
 
        * locale/programs/locale.c (show_info): Fix printing word values on
index cb63935..a4f066c 100644 (file)
@@ -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)
index f362dd7..bde45ca 100644 (file)
@@ -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