]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1391. [func] Add support for IPv6 scoped addresses in named.
authorMark Andrews <marka@isc.org>
Thu, 24 Oct 2002 03:52:35 +0000 (03:52 +0000)
committerMark Andrews <marka@isc.org>
Thu, 24 Oct 2002 03:52:35 +0000 (03:52 +0000)
15 files changed:
CHANGES
bin/named/client.c
bin/named/interfacemgr.c
configure.in
doc/arm/Bv9ARM-book.xml
lib/isc/Makefile.in
lib/isc/include/isc/netaddr.h
lib/isc/include/isc/netscope.h [new file with mode: 0644]
lib/isc/include/isc/platform.h.in
lib/isc/netaddr.c
lib/isc/netscope.c [new file with mode: 0644]
lib/isc/sockaddr.c
lib/isc/unix/include/isc/net.h
lib/isc/unix/interfaceiter.c
lib/isccfg/parser.c

diff --git a/CHANGES b/CHANGES
index 7777e5ff18024aaa6f243a5a6c90b35dcd2d7f29..f45bdcef25ec683f7e5542083f6b1198bccf1b57 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+1391.  [func]          Add support for IPv6 scoped addresses in named.
+
 1390.  [func]          host now supports ixfr.
 
 1389.  [bug]           named could fail to rotate long log files.  [RT #3666]
index dec027b08f32b2c7cdceaccf78cbd1b8255b7338..51c7596ee5220fe6064664baaa6e0c221766add0 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: client.c,v 1.211 2002/09/10 04:45:52 marka Exp $ */
+/* $Id: client.c,v 1.212 2002/10/24 03:52:31 marka Exp $ */
 
 #include <config.h>
 
@@ -1340,9 +1340,25 @@ client_request(isc_task_t *task, isc_event_t *event) {
         * the address of the interface where the request was received.
         */
        if (client->interface->addr.type.sa.sa_family == AF_INET6) {
-               if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0)
-                       isc_netaddr_fromin6(&destaddr, &client->pktinfo.ipi6_addr);
-               else
+               if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
+                       u_int32_t zone = 0;
+
+                       /*
+                        * XXXJT technically, we should convert the receiving
+                        * interface ID to a proper scope zone ID.  However,
+                        * due to the fact there is no standard API for this,
+                        * we only handle link-local addresses and use the
+                        * interface index as link ID.  Despite the assumption,
+                        * it should cover most typical cases.
+                        */
+                       if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
+                               zone = (u_int32_t)client->pktinfo.ipi6_ifindex;
+
+                       isc_netaddr_fromin6(&destaddr,
+                                           &client->pktinfo.ipi6_addr);
+                       isc_netaddr_setzone(&destaddr, zone);
+                                                     
+               } else
                        isc_netaddr_any6(&destaddr);
        } else {
                isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
index d32d64984e8f42eb0e69fd3d8b7f3fa41ca74b2b..5069d0162ed93c6b1a5f85d1a8965474a17c71ad 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: interfacemgr.c,v 1.71 2002/09/10 04:45:52 marka Exp $ */
+/* $Id: interfacemgr.c,v 1.72 2002/10/24 03:52:31 marka Exp $ */
 
 #include <config.h>
 
@@ -681,6 +681,8 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
                        } else {
                                isc_netaddr_fromin6(&listen_netaddr,
                                                    &interface.address.type.in6);
+                               isc_netaddr_setzone(&listen_netaddr,
+                                                   interface.address.zone);
                        }
                        isc_sockaddr_fromnetaddr(&listen_sockaddr,
                                                 &listen_netaddr,
index 502ac80b1d37cb27566b26afc00c1313d416a185..58e153d28dae68ac6cd8975450a2713c86c716f6 100644 (file)
@@ -18,7 +18,7 @@ AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl
 esyscmd([sed "s/^/# /" COPYRIGHT])dnl
 AC_DIVERT_POP()dnl
 
-AC_REVISION($Revision: 1.331 $)
+AC_REVISION($Revision: 1.332 $)
 
 AC_INIT(lib/dns/name.c)
 AC_PREREQ(2.13)
@@ -1176,8 +1176,10 @@ $isc_netinet6in6_hack
 ],
                [struct sockaddr_in6 xyzzy; xyzzy.sin6_scope_id = 0; return (0);],
                        [AC_MSG_RESULT(yes)
+                        ISC_PLATFORM_HAVESCOPEID="#define ISC_PLATFORM_HAVESCOPEID 1"
                         result="#define LWRES_HAVE_SIN6_SCOPE_ID 1"],
                        [AC_MSG_RESULT(no)
+                        ISC_PLATFORM_HAVESCOPEID="#undef ISC_PLATFORM_HAVESCOPEID"
                         result="#undef LWRES_HAVE_SIN6_SCOPE_ID"])
                LWRES_HAVE_SIN6_SCOPE_ID="$result"
 
@@ -1202,6 +1204,7 @@ $isc_netinet6in6_hack
                LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY"
                ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO"
                LWRES_HAVE_SIN6_SCOPE_ID="#define LWRES_HAVE_SIN6_SCOPE_ID 1"
+               ISC_PLATFORM_HAVESCOPEID="#define ISC_PLATFORM_HAVESCOPEID 1"
                ISC_IPV6_H="ipv6.h"
                ISC_IPV6_O="ipv6.$O"
                ISC_ISCIPV6_O="unix/ipv6.$O"
@@ -1228,6 +1231,7 @@ AC_SUBST(ISC_IPV6_O)
 AC_SUBST(ISC_ISCIPV6_O)
 AC_SUBST(ISC_IPV6_C)
 AC_SUBST(LWRES_HAVE_SIN6_SCOPE_ID)
+AC_SUBST(ISC_PLATFORM_HAVESCOPEID)
 
 AC_MSG_CHECKING([for struct if_laddrreq])
 AC_TRY_LINK([
index 8510c0cc89942287182426577437ecdf53fce367..c678fccdf16ceca46c849b15e3deee2c66393c29 100644 (file)
@@ -2,7 +2,7 @@
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
                "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
 
-<!-- File: $Id: Bv9ARM-book.xml,v 1.205 2002/08/17 03:26:46 marka Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.206 2002/10/24 03:52:32 marka Exp $ -->
 
 <book>
 <title>BIND 9 Administrator Reference Manual</title>
@@ -1908,7 +1908,21 @@ in <varname>dotted_decimal</varname> notation.</para></entry>
 </row>
 <row rowsep = "0">
 <entry colname = "1"><para><varname>ip6_addr</varname></para></entry>
-<entry colname = "2"><para>An IPv6 address, such as <command>fe80::200:f8ff:fe01:9742</command>.</para></entry>
+<entry colname = "2"><para>An IPv6 address, such as <command>2001:ffff::200:f8ff:fe01:9742</command>.
+IPv6 scoped addresses that have ambiguity on their scope zones must be
+disambiguated by an appropriate zone ID with the percent character
+(`%') as delimiter.
+It is strongly recommended to use string zone names rather than
+numeric identifiers, in order to be robust against system
+configuration changes.
+However, since there is no standard mapping for such names and
+identifier values, currently only interface names as link identifiers
+are supported, assuming one-to-one mapping between interfaces and links.
+For example, a link-local address <command>fe80::1</command> on the
+link attached to the interface <command>ne0</command>
+can be specified as <command>fe80::1%ne0</command>.
+Note that on most systems link-local addresses always have the
+ambiguity, and need to be disambiguated.</para></entry>
 </row>
 <row rowsep = "0">
 <entry colname = "1"><para><varname>ip_addr</varname></para></entry>
index ea46560bad92deb6f6a09becf9612af657d502e1..c5121505e1ea2465677cf473e2986be6adb709d5 100644 (file)
@@ -13,7 +13,7 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: Makefile.in,v 1.75 2002/02/20 03:35:20 marka Exp $
+# $Id: Makefile.in,v 1.76 2002/10/24 03:52:32 marka Exp $
 
 srcdir =       @srcdir@
 VPATH =                @srcdir@
@@ -53,8 +53,8 @@ OBJS =                @ISC_EXTRA_OBJS@ \
                assertions.@O@ base64.@O@ bitstring.@O@ buffer.@O@ \
                bufferlist.@O@ commandline.@O@ error.@O@ event.@O@ \
                heap.@O@ hex.@O@ hmacmd5.@O@ \
-               lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
-               md5.@O@ mem.@O@ mutexblock.@O@ netaddr.@O@ ondestroy.@O@ \
+               lex.@O@ lfsr.@O@ lib.@O@ log.@O@ md5.@O@ \
+               mem.@O@ mutexblock.@O@ netaddr.@O@ netscope.@O@ ondestroy.@O@ \
                parseint.@O@ quota.@O@ random.@O@ \
                ratelimiter.@O@ region.@O@ result.@O@ rwlock.@O@ \
                serial.@O@ sha1.@O@ sockaddr.@O@ string.@O@ symtab.@O@ \
@@ -67,7 +67,7 @@ SRCS =                @ISC_EXTRA_SRCS@ \
                bufferlist.c commandline.c error.c event.c \
                heap.c hex.c hmacmd5.c \
                lex.c lfsr.c lib.c log.c \
-               md5.c mem.c mutexblock.c netaddr.c ondestroy.c \
+               md5.c mem.c mutexblock.c netaddr.c netscope.c ondestroy.c \
                parseint.c quota.c random.c \
                ratelimiter.c result.c rwlock.c \
                serial.c sha1.c sockaddr.c string.c symtab.c \
index 94f0f0c2d2dcc675d6b69f87436712b0d5b92c32..a0a51ea8b98f48fb99bd4c8752ac67c951181c87 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: netaddr.h,v 1.21 2002/04/03 06:38:35 marka Exp $ */
+/* $Id: netaddr.h,v 1.22 2002/10/24 03:52:34 marka Exp $ */
 
 #ifndef ISC_NETADDR_H
 #define ISC_NETADDR_H 1
@@ -32,6 +32,7 @@ struct isc_netaddr {
                struct in_addr in;
                struct in6_addr in6;
        } type;
+       u_int32_t zone;
 };
 
 isc_boolean_t
@@ -94,6 +95,12 @@ isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina);
 void
 isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6);
 
+void
+isc_netaddr_setzone(isc_netaddr_t *netaddr, u_int32_t zone);
+
+u_int32_t
+isc_netaddr_getzone(const isc_netaddr_t *netaddr);
+
 void
 isc_netaddr_any(isc_netaddr_t *netaddr);
 /*
diff --git a/lib/isc/include/isc/netscope.h b/lib/isc/include/isc/netscope.h
new file mode 100644 (file)
index 0000000..c8cacbe
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2002  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.
+ */
+
+/* $Id: netscope.h,v 1.2 2002/10/24 03:52:34 marka Exp $ */
+
+#ifndef ISC_NETSCOPE_H
+#define ISC_NETSCOPE_H 1
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Convert a string of an IPv6 scope zone to zone index.  If the conversion
+ * succeeds, 'zoneid' will store the index value.
+ * XXXJT: when a standard interface for this purpose is defined,
+ * we should use it.
+ *
+ * Returns:
+ *     ISC_R_SUCCESS: conversion succeeds
+ *     ISC_R_FAILURE: conversion fails
+ */
+isc_result_t
+isc_netscope_pton(int af, char *scopename, char *addr, u_int32_t *zoneid);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETADDR_H */
index e6f7cff30b06ca14599a072ec4be96a17c89d063..bdf619b6202b23c93b683fe7ca5f07d99f0900a2 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: platform.h.in,v 1.28 2001/11/19 03:08:26 mayer Exp $ */
+/* $Id: platform.h.in,v 1.29 2002/10/24 03:52:34 marka Exp $ */
 
 #ifndef ISC_PLATFORM_H
 #define ISC_PLATFORM_H 1
  */
 @ISC_PLATFORM_HAVEINADDR6@
 
+/*
+ * If this system has sin6_scope_id, ISC_PLATFORM_HAVESCOPEID will be defined.
+ */
+@ISC_PLATFORM_HAVESCOPEID@
+
 /*
  * If this system needs inet_ntop(), ISC_PLATFORM_NEEDNTOP will be defined.
  */
index 74eb25532db060e9054f747fa77e13946561b512..bc4ef9d64fc71c306f551c873649ed905c940f85 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: netaddr.c,v 1.22 2002/04/03 06:38:31 marka Exp $ */
+/* $Id: netaddr.c,v 1.23 2002/10/24 03:52:32 marka Exp $ */
 
 #include <config.h>
 
@@ -36,14 +36,17 @@ isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
        if (a->family != b->family)
                return (ISC_FALSE);
 
+       if (a->zone != b->zone)
+               return (ISC_FALSE);
+
        switch (a->family) {
        case AF_INET:
                if (a->type.in.s_addr != b->type.in.s_addr)
                        return (ISC_FALSE);
                break;
        case AF_INET6:
-               if (memcmp(&a->type.in6, &b->type.in6, sizeof(a->type.in6))
-                   != 0)
+               if (memcmp(&a->type.in6, &b->type.in6,
+                          sizeof(a->type.in6)) != 0)
                        return (ISC_FALSE);
                break;
        default:
@@ -66,6 +69,9 @@ isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
        if (a->family != b->family)
                return (ISC_FALSE);
 
+       if (a->zone != b->zone)
+               return (ISC_FALSE);
+
        switch (a->family) {
        case AF_INET:
                pa = (const unsigned char *) &a->type.in;
@@ -112,22 +118,44 @@ isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
 isc_result_t
 isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
        char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
+       char zbuf[sizeof("%4294967295")];
        unsigned int alen;
+       int zlen;
        const char *r;
+       const void *type;
 
        REQUIRE(netaddr != NULL);
 
-       r = inet_ntop(netaddr->family, &netaddr->type, abuf, sizeof(abuf));
+       switch (netaddr->family) {
+       case AF_INET:
+               type = &netaddr->type.in;
+               break;
+       case AF_INET6:
+               type = &netaddr->type.in6;
+               break;
+       default:
+               return (ISC_R_FAILURE);
+       }
+       r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
        if (r == NULL)
                return (ISC_R_FAILURE);
 
        alen = strlen(abuf);
        INSIST(alen < sizeof(abuf));
 
-       if (alen > isc_buffer_availablelength(target))
+       zlen = 0;
+       if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
+               zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
+               if (zlen < 0)
+                       return (ISC_R_FAILURE);
+               INSIST((unsigned int)zlen < sizeof(zbuf));
+       }
+
+       if (alen + zlen > isc_buffer_availablelength(target))
                return (ISC_R_NOSPACE);
 
        isc_buffer_putmem(target, (unsigned char *)abuf, alen);
+       isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
 
        return (ISC_R_SUCCESS);
 }
@@ -216,20 +244,38 @@ isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
        netaddr->type.in6 = *ina6;
 }
 
+void
+isc_netaddr_setzone(isc_netaddr_t *netaddr, u_int32_t zone) {
+       /* we currently only support AF_INET6. */
+       REQUIRE(netaddr->family == AF_INET6);
+
+       netaddr->zone = zone;
+}
+
+u_int32_t
+isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
+       return (netaddr->zone);
+}
+
 void
 isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
        int family = s->type.sa.sa_family;
        t->family = family;
        switch (family) {
-        case AF_INET:
+       case AF_INET:
                t->type.in = s->type.sin.sin_addr;
-                break;
-        case AF_INET6:
+               break;
+       case AF_INET6:
                memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16);
-                break;
-        default:
-                INSIST(0);
-        }
+#ifdef ISC_PLATFORM_HAVESCOPEID
+               t->zone = s->type.sin6.sin6_scope_id;
+#else
+               t->zone = 0;
+#endif
+               break;
+       default:
+               INSIST(0);
+       }
 }
 
 void
diff --git a/lib/isc/netscope.c b/lib/isc/netscope.c
new file mode 100644 (file)
index 0000000..bebf4e9
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 1996-2001  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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] =
+       "$Id: netscope.c,v 1.2 2002/10/24 03:52:33 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <isc/string.h>
+#include <isc/net.h>
+#include <isc/netscope.h>
+#include <isc/result.h>
+
+isc_result_t
+isc_netscope_pton(int af, char *scopename, char *addr, u_int32_t *zoneid) {
+       char *ep;
+       unsigned int ifid;
+       struct in6_addr *in6;
+       u_int32_t zone;
+       isc_uint64_t llz;
+
+       /* at this moment, we only support AF_INET6 */
+       if (af != AF_INET6)
+               return (ISC_R_FAILURE);
+
+       in6 = (struct in6_addr *)addr;
+
+       /*
+        * Basically, "names" are more stable than numeric IDs in terms of
+        * renumbering, and are more preferred.  However, since there is no
+        * standard naming convention and APIs to deal with the names.  Thus,
+        * we only handle the case of link-local addresses, for which we use
+        * interface names as link names, assuming one to one mapping between
+        * interfaces and links.
+        */
+       if (IN6_IS_ADDR_LINKLOCAL(in6) &&
+           (ifid = if_nametoindex((const char *)scopename)) != 0)
+               zone = (u_int32_t)ifid;
+       else {
+               llz = isc_string_touint64(scopename, &ep, 10);
+               if (ep == scopename)
+                       return (ISC_R_FAILURE);
+
+               /* check overflow */
+               zone = (u_int32_t)(llz & 0xffffffffUL);
+               if (zone != llz)
+                       return (ISC_R_FAILURE);
+       }
+
+       *zoneid = zone;
+       return (ISC_R_SUCCESS);
+}
index c0c2fe97901edbd1d7d1501a1726fb8355d9cba9..55837d1e227920dea07e8f6db2376e3b6ee1d13c 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sockaddr.c,v 1.54 2002/04/03 06:38:32 marka Exp $ */
+/* $Id: sockaddr.c,v 1.55 2002/10/24 03:52:33 marka Exp $ */
 
 #include <config.h>
 
@@ -371,6 +371,9 @@ isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
                sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
 #endif
                memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
+#ifdef ISC_PLATFORM_HAVESCOPEID
+               sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
+#endif
                sockaddr->type.sin6.sin6_port = htons(port);
                break;
         default:
index 4c1f3b992d9a0ce2a5a835366c9b9b50952f3337..f527a977dfaf86ddd177548b41612f89be767e13 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: net.h,v 1.34 2002/04/03 06:38:38 marka Exp $ */
+/* $Id: net.h,v 1.35 2002/10/24 03:52:35 marka Exp $ */
 
 #ifndef ISC_NET_H
 #define ISC_NET_H 1
@@ -75,6 +75,8 @@
 #include <sys/types.h>
 #include <sys/socket.h>                /* Contractual promise. */
 
+#include <net/if.h>
+
 #include <netinet/in.h>                /* Contractual promise. */
 #include <arpa/inet.h>         /* Contractual promise. */
 #ifdef ISC_PLATFORM_NEEDNETINETIN6H
index 0f9734c788b2bff4f0d226b009798214478bb6f5..8fd873efc1ca97cca54574966d68e4b4f93d27ee 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: interfaceiter.c,v 1.27 2002/07/02 05:51:43 marka Exp $ */
+/* $Id: interfaceiter.c,v 1.28 2002/10/24 03:52:34 marka Exp $ */
 
 #include <config.h>
 
@@ -53,7 +53,7 @@
 /*
  * Extract the network address part from a "struct sockaddr".
  *
- * The address family is given explicity
+ * The address family is given explicitly
  * instead of using src->sa_family, because the latter does not work
  * for copying a network mask obtained by SIOCGIFNETMASK (it does
  * not have a valid address family).
@@ -61,6 +61,8 @@
 
 static void
 get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) {
+       struct sockaddr_in6 *sa6;
+
        dst->family = family;
        switch (family) {
        case AF_INET:
@@ -69,9 +71,40 @@ get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) {
                       sizeof(struct in_addr));
                break;
        case    AF_INET6:
-               memcpy(&dst->type.in6,
-                      &((struct sockaddr_in6 *) src)->sin6_addr,
+               sa6 = (struct sockaddr_in6 *)src;
+               memcpy(&dst->type.in6, &sa6->sin6_addr,
                       sizeof(struct in6_addr));
+#ifdef ISC_PLATFORM_HAVESCOPEID
+               if (sa6->sin6_scope_id != 0)
+                       isc_netaddr_setzone(dst, sa6->sin6_scope_id);
+               else 
+#endif
+               {
+                       /*
+                        * BSD variants embed scope zone IDs in the 128bit
+                        * address as a kernel internal form.  Unfortunately,
+                        * the embedded IDs are not hidden from applications
+                        * when getting access to them by sysctl or ioctl.
+                        * We convert the internal format to the pure address
+                        * part and the zone ID part.
+                        * Since multicast addresses should not appear here
+                        * and they cannot be distinguished from netmasks,
+                        * we only consider unicast link-local addresses.
+                        */
+                       if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
+                               u_int16_t zone;
+
+                               memcpy(&zone, &sa6->sin6_addr.s6_addr[2],
+                                      sizeof(zone));
+                               zone = ntohs(zone);
+                               if (zone != 0) { /* the zone ID is embedded */
+                                       isc_netaddr_setzone(dst,
+                                                           (u_int32_t)zone);
+                                       dst->type.in6.s6_addr[2] = 0;
+                                       dst->type.in6.s6_addr[3] = 0;
+                               }
+                       }
+               }
                break;
        default:
                INSIST(0);
index 01aa8eaee737d7aae70b1f11ed0abc637ed55eae..edc8f44b4308b0d661131c0748a7558d3f9a9d8f 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: parser.c,v 1.102 2002/02/20 03:35:49 marka Exp $ */
+/* $Id: parser.c,v 1.103 2002/10/24 03:52:35 marka Exp $ */
 
 #include <config.h>
 
@@ -1662,9 +1662,31 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
                                }
                        }
                }
-               if (flags & CFG_ADDR_V6OK) {
-                       if (inet_pton(AF_INET6, s, &in6a) == 1) {
+               if ((flags & CFG_ADDR_V6OK) != 0 &&
+                   strlen(s) <= 127) {
+                       char buf[128];
+                       char *d; /* zone delimiter */
+                       u_int32_t zone = 0; /* scope zone ID */
+
+                       strcpy(buf, s);
+                       d = strchr(buf, '%');
+                       if (d != NULL)
+                               *d = '\0';
+
+                       if (inet_pton(AF_INET6, buf, &in6a) == 1) {
+                               if (d != NULL) {
+                                       isc_result_t result;
+
+                                       result = isc_netscope_pton(AF_INET6,
+                                                                  d + 1,
+                                                                  &in6a,
+                                                                  &zone);
+                                       if (result != ISC_R_SUCCESS)
+                                               return (result);
+                               }
+
                                isc_netaddr_fromin6(na, &in6a);
+                               isc_netaddr_setzone(na, zone);
                                return (ISC_R_SUCCESS);
                        }
                }