From ec3f1d35170225c74d11c27bb184e250d150b209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tatuya=20JINMEI=20=E7=A5=9E=E6=98=8E=E9=81=94=E5=93=89?= Date: Sat, 15 May 2004 03:37:34 +0000 Subject: [PATCH] 1629. [func] dig now supports IPv6 scoped addresses with the extended format in the local-server part. [RT #8753] --- CHANGES | 3 +- lib/bind9/getaddresses.c | 65 +++++++++++++++++++++++++++++++----- lib/isc/include/isc/result.h | 5 +-- lib/isc/netaddr.c | 5 +-- lib/isc/result.c | 5 +-- lib/isc/sockaddr.c | 10 +++++- lib/isccfg/parser.c | 8 +++-- 7 files changed, 83 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index 6a99be22d8..b29cc971a5 100644 --- a/CHANGES +++ b/CHANGES @@ -25,7 +25,8 @@ 1630. [contrib] queryperf: add support for IPv6 transport. -1629. [placeholder] rt8753 +1629. [func] dig now supports IPv6 scoped addresses with the + extended format in the local-server part. [RT #8753] 1628. [bug] Typo in Compaq Trucluster support. [RT# 11264] diff --git a/lib/bind9/getaddresses.c b/lib/bind9/getaddresses.c index b4c9158b44..d407f64066 100644 --- a/lib/bind9/getaddresses.c +++ b/lib/bind9/getaddresses.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: getaddresses.c,v 1.15 2004/03/05 05:09:04 marka Exp $ */ +/* $Id: getaddresses.c,v 1.16 2004/05/15 03:37:33 jinmei Exp $ */ #include #include @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -67,19 +68,67 @@ bind9_getaddresses(const char *hostname, in_port_t port, have_ipv4 = (isc_net_probeipv4() == ISC_R_SUCCESS); have_ipv6 = (isc_net_probeipv6() == ISC_R_SUCCESS); - if (inet_pton(AF_INET6, hostname, &in6) == 1) { - if (!have_ipv6) - return (ISC_R_FAMILYNOSUPPORT); - isc_sockaddr_fromin6(&addrs[0], &in6, port); - *addrcount = 1; - return (ISC_R_SUCCESS); - } else if (inet_pton(AF_INET, hostname, &in4) == 1) { + /* + * Try IPv4, then IPv6. In order to handle the extended format + * for IPv6 scoped addresses (address%scope_ID), we'll use a local + * working buffer of 128 bytes. The length is an ad-hoc value, but + * should be enough for this purpose; the buffer can contain a string + * of at least 80 bytes for scope_ID in addition to any IPv6 numeric + * addresses (up to 46 bytes), the delimiter character and the + * terminating NULL character. + */ + if (inet_pton(AF_INET, hostname, &in4) == 1) { if (have_ipv4) isc_sockaddr_fromin(&addrs[0], &in4, port); else isc_sockaddr_v6fromin(&addrs[0], &in4, port); *addrcount = 1; return (ISC_R_SUCCESS); + } else if (strlen(hostname) <= 127) { + char tmpbuf[128], *d; + isc_uint32_t zone = 0; + + strcpy(tmpbuf, hostname); + d = strchr(tmpbuf, '%'); + if (d != NULL) + *d = '\0'; + + if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) { + isc_netaddr_t na; + + if (!have_ipv6) + return (ISC_R_FAMILYNOSUPPORT); + + if (d != NULL) { +#ifdef ISC_PLATFORM_HAVESCOPEID + isc_result_t result; + + result = isc_netscope_pton(AF_INET6, d + 1, + &in6, &zone); + + if (result != ISC_R_SUCCESS) + return (result); +#else + /* + * The extended format is specified while the + * system does not provide the ability to use + * it. Throw an explicit error instead of + * ignoring the specified value. + */ + return (ISC_R_BADADDRESSFORM); +#endif + } + + isc_netaddr_fromin6(&na, &in6); + isc_netaddr_setzone(&na, zone); + isc_sockaddr_fromnetaddr(&addrs[0], + (const isc_netaddr_t *)&na, + port); + + *addrcount = 1; + return (ISC_R_SUCCESS); + + } } #ifdef USE_GETADDRINFO memset(&hints, 0, sizeof(hints)); diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h index d1ae566f0a..d3bfb49a74 100644 --- a/lib/isc/include/isc/result.h +++ b/lib/isc/include/isc/result.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.62 2004/03/05 05:11:00 marka Exp $ */ +/* $Id: result.h,v 1.63 2004/05/15 03:37:34 jinmei Exp $ */ #ifndef ISC_RESULT_H #define ISC_RESULT_H 1 @@ -82,11 +82,12 @@ #define ISC_R_BADNUMBER 56 /* not a valid number */ #define ISC_R_DISABLED 57 /* disabled */ #define ISC_R_MAXSIZE 58 /* max size */ +#define ISC_R_BADADDRESSFORM 59 /* invalid address format */ /* * Not a result code: the number of results. */ -#define ISC_R_NRESULTS 59 +#define ISC_R_NRESULTS 60 ISC_LANG_BEGINDECLS diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c index a2081afacb..74cd159535 100644 --- a/lib/isc/netaddr.c +++ b/lib/isc/netaddr.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: netaddr.c,v 1.27 2004/03/05 05:10:47 marka Exp $ */ +/* $Id: netaddr.c,v 1.28 2004/05/15 03:37:33 jinmei Exp $ */ #include @@ -47,7 +47,8 @@ isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) { break; case AF_INET6: if (memcmp(&a->type.in6, &b->type.in6, - sizeof(a->type.in6)) != 0) + sizeof(a->type.in6)) != 0 || + a->zone != b->zone) return (ISC_FALSE); break; default: diff --git a/lib/isc/result.c b/lib/isc/result.c index 68acf9f2d2..7eb3a4332c 100644 --- a/lib/isc/result.c +++ b/lib/isc/result.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.c,v 1.62 2004/03/05 05:10:48 marka Exp $ */ +/* $Id: result.c,v 1.63 2004/05/15 03:37:33 jinmei Exp $ */ #include @@ -96,7 +96,8 @@ static const char *text[ISC_R_NRESULTS] = { "soft quota reached", /* 55 */ "not a valid number", /* 56 */ "disabled", /* 57 */ - "max size" /* 58 */ + "max size", /* 58 */ + "invalid address format" /* 59 */ }; #define ISC_RESULT_RESULTSET 2 diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c index 27b9309f95..edaaf5b06d 100644 --- a/lib/isc/sockaddr.c +++ b/lib/isc/sockaddr.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sockaddr.c,v 1.59 2004/03/05 05:10:49 marka Exp $ */ +/* $Id: sockaddr.c,v 1.60 2004/05/15 03:37:33 jinmei Exp $ */ #include @@ -57,6 +57,10 @@ isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, sizeof(a->type.sin6.sin6_addr)) != 0) return (ISC_FALSE); +#ifdef ISC_PLATFORM_HAVESCOPEID + if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id) + return (ISC_FALSE); +#endif if (a->type.sin6.sin6_port != b->type.sin6.sin6_port) return (ISC_FALSE); break; @@ -86,6 +90,10 @@ isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, sizeof(a->type.sin6.sin6_addr)) != 0) return (ISC_FALSE); +#ifdef ISC_PLATFORM_HAVESCOPEID + if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id) + return (ISC_FALSE); +#endif break; default: if (memcmp(&a->type, &b->type, a->length) != 0) diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 8a4affd493..14223142ba 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: parser.c,v 1.112 2004/03/18 02:58:07 marka Exp $ */ +/* $Id: parser.c,v 1.113 2004/05/15 03:37:34 jinmei Exp $ */ #include @@ -1671,7 +1671,7 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) { } if ((flags & CFG_ADDR_V6OK) != 0 && strlen(s) <= 127U) { - char buf[128]; + char buf[128]; /* see lib/bind9/getaddresses.c */ char *d; /* zone delimiter */ isc_uint32_t zone = 0; /* scope zone ID */ @@ -1682,6 +1682,7 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) { if (inet_pton(AF_INET6, buf, &in6a) == 1) { if (d != NULL) { +#ifdef ISC_PLATFORM_HAVESCOPEID isc_result_t result; result = isc_netscope_pton(AF_INET6, @@ -1690,6 +1691,9 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) { &zone); if (result != ISC_R_SUCCESS) return (result); +#else + return (ISC_R_BADADDRESSFORM); +#endif } isc_netaddr_fromin6(na, &in6a);