1391. [func] Add support for IPv6 scoped addresses in named.

This commit is contained in:
Mark Andrews 2002-10-24 03:52:35 +00:00
parent 4cd7166048
commit 6526fd032f
15 changed files with 297 additions and 35 deletions

View file

@ -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]

View 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);

View 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,

View 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([

View 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>

View 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 \

View 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);
/*

View file

@ -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 */

View 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
@ -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.
*/

View 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

66
lib/isc/netscope.c Normal file
View file

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

View 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:

View 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

View 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);

View 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);
}
}