diff --git a/CHANGES b/CHANGES index 7777e5ff18..f45bdcef25 100644 --- 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] diff --git a/bin/named/client.c b/bin/named/client.c index dec027b08f..51c7596ee5 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -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 @@ -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); diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index d32d64984e..5069d0162e 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -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 @@ -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, diff --git a/configure.in b/configure.in index 502ac80b1d..58e153d28d 100644 --- a/configure.in +++ b/configure.in @@ -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([ diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 8510c0cc89..c678fccdf1 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -2,7 +2,7 @@ - + BIND 9 Administrator Reference Manual @@ -1908,7 +1908,21 @@ in dotted_decimal notation. ip6_addr -An IPv6 address, such as fe80::200:f8ff:fe01:9742. +An IPv6 address, such as 2001:ffff::200:f8ff:fe01:9742. +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 fe80::1 on the +link attached to the interface ne0 +can be specified as fe80::1%ne0. +Note that on most systems link-local addresses always have the +ambiguity, and need to be disambiguated. ip_addr diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index ea46560bad..c5121505e1 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -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 \ diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h index 94f0f0c2d2..a0a51ea8b9 100644 --- a/lib/isc/include/isc/netaddr.h +++ b/lib/isc/include/isc/netaddr.h @@ -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 index 0000000000..c8cacbec3b --- /dev/null +++ b/lib/isc/include/isc/netscope.h @@ -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 */ diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in index e6f7cff30b..bdf619b620 100644 --- a/lib/isc/include/isc/platform.h.in +++ b/lib/isc/include/isc/platform.h.in @@ -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 @@ -76,6 +76,11 @@ */ @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. */ diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c index 74eb25532d..bc4ef9d64f 100644 --- a/lib/isc/netaddr.c +++ b/lib/isc/netaddr.c @@ -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 @@ -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 index 0000000000..bebf4e9bc7 --- /dev/null +++ b/lib/isc/netscope.c @@ -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 +#include +#include +#include + +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); +} diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c index c0c2fe9790..55837d1e22 100644 --- a/lib/isc/sockaddr.c +++ b/lib/isc/sockaddr.c @@ -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 @@ -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: diff --git a/lib/isc/unix/include/isc/net.h b/lib/isc/unix/include/isc/net.h index 4c1f3b992d..f527a977df 100644 --- a/lib/isc/unix/include/isc/net.h +++ b/lib/isc/unix/include/isc/net.h @@ -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 #include /* Contractual promise. */ +#include + #include /* Contractual promise. */ #include /* Contractual promise. */ #ifdef ISC_PLATFORM_NEEDNETINETIN6H diff --git a/lib/isc/unix/interfaceiter.c b/lib/isc/unix/interfaceiter.c index 0f9734c788..8fd873efc1 100644 --- a/lib/isc/unix/interfaceiter.c +++ b/lib/isc/unix/interfaceiter.c @@ -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 @@ -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); diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 01aa8eaee7..edc8f44b43 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -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 @@ -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); } }