From patchwork Tue Sep 5 16:05:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?=C5=81ukasz_Stelmach?= X-Patchwork-Id: 22624 Received: (qmail 117912 invoked by alias); 5 Sep 2017 16:06:18 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 117847 invoked by uid 89); 5 Sep 2017 16:06:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=1727 X-HELO: smtpo.poczta.interia.pl X-Interia-R: Interia X-Interia-R-IP: 89.64.33.181 X-Interia-R-Helo: From: =?UTF-8?q?=C5=81ukasz=20Stelmach?= To: libc-alpha@sourceware.org Cc: =?UTF-8?q?=C5=81ukasz=20Stelmach?= Subject: [RFC][PATCH 2/4][BZ 17083] NSS: Parse zone identifier of IPv6 addresses in /etc/hosts Date: Tue, 5 Sep 2017 18:05:28 +0200 Message-Id: <20170905160530.19525-3-stlman@poczta.fm> In-Reply-To: <20170905160530.19525-1-stlman@poczta.fm> References: <20170905160530.19525-1-stlman@poczta.fm> MIME-Version: 1.0 X-Interia-Antivirus: OK X-IPL-POID: 4 X-IPL-SAS-SPAS: -0.6 X-IPL-SAS-UREP: 0 X-IPL-SAS-UREP-PRIV: 0 X-IPL-Envelope-To: stlman@poczta.fm Parse link-local IPv6 addresses in /etc/hosts, which contain zone identifiers as described in RFC 4007. Signed-off-by: Ɓukasz Stelmach --- nss/nss_files/files-hosts.c | 54 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c index bccb6a5780..28eb73fb2d 100644 --- a/nss/nss_files/files-hosts.c +++ b/nss/nss_files/files-hosts.c @@ -33,8 +33,8 @@ #define DATABASE "hosts" #define NEED_H_ERRNO -#define EXTRA_ARGS , af, flags -#define EXTRA_ARGS_DECL , int af, int flags +#define EXTRA_ARGS , af, flags, in6_zone_id +#define EXTRA_ARGS_DECL , int af, int flags, uint32_t *in6_zone_id #define ENTDATA hostent_data struct hostent_data @@ -53,6 +53,9 @@ LINE_PARSER STRING_FIELD (addr, isspace, 1); + if (in6_zone_id != NULL) + *in6_zone_id = 0; + /* Parse address. */ if (inet_pton (af == AF_UNSPEC ? AF_INET : af, addr, entdata->host_addr) > 0) @@ -80,6 +83,40 @@ LINE_PARSER else if (af == AF_UNSPEC && inet_pton (AF_INET6, addr, entdata->host_addr) > 0) af = AF_INET6; + else if (strchr(addr, SCOPE_DELIMITER) != NULL) + { + /* Parse a zone identifier RFC 4007 11. */ + struct addrinfo hints; + struct addrinfo *res; + struct sockaddr_in6 *sa; + int ret; + + /* Only IPv6 link-local addresses can have zone identifiers. */ + af = AF_INET6; + + memset(&hints, 0, sizeof(struct addrinfo)); + /* Don't perform any lookups. */ + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = AF_INET6; + + ret = getaddrinfo(addr, NULL, &hints, &res); + if (ret != 0) + return 0; + + sa = (struct sockaddr_in6*)res->ai_addr; + + /* Zone identifiers makes sense only for link-local addresses. */ + if (!IN6_IS_ADDR_LINKLOCAL(sa->sin6_addr.s6_addr)) { + freeaddrinfo(res); + return 0; + } + + if (in6_zone_id != NULL) + *in6_zone_id = sa->sin6_scope_id; + + memcpy(entdata->host_addr, &sa->sin6_addr, IN6ADDRSZ); + freeaddrinfo(res); + } else /* Illegal address: ignore line. */ return 0; @@ -99,14 +136,14 @@ LINE_PARSER #define EXTRA_ARGS_VALUE \ , (res_use_inet6 () ? AF_INET6 : AF_INET), \ - (res_use_inet6 () ? AI_V4MAPPED : 0) + (res_use_inet6 () ? AI_V4MAPPED : 0), NULL #include "files-XXX.c" #undef EXTRA_ARGS_VALUE /* We only need to consider IPv4 mapped addresses if the input to the gethostbyaddr() function is an IPv6 address. */ #define EXTRA_ARGS_VALUE \ - , af, (len == IN6ADDRSZ ? AI_V4MAPPED : 0) + , af, (len == IN6ADDRSZ ? AI_V4MAPPED : 0), NULL DB_LOOKUP (hostbyaddr, ,,, { if (result->h_length == (int) len @@ -135,7 +172,7 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, int flags = (res_use_inet6 () ? AI_V4MAPPED : 0); while ((status = internal_getent (stream, result, buffer, buflen, errnop, - herrnop, af, flags)) + herrnop, af, flags, NULL)) == NSS_STATUS_SUCCESS) { LOOKUP_NAME_CASE (h_name, h_aliases) @@ -163,7 +200,7 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, again: while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer, tmp_buflen, errnop, herrnop, af, - flags)) + flags, NULL)) == NSS_STATUS_SUCCESS) { int matches = 1; @@ -385,12 +422,13 @@ _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, /* Align the buffer for the next record. */ uintptr_t pad = (-(uintptr_t) buffer % __alignof__ (struct hostent_data)); + uint32_t in6_zone_id = 0; buffer += pad; buflen = buflen > pad ? buflen - pad : 0; struct hostent result; status = internal_getent (stream, &result, buffer, buflen, errnop, - herrnop, AF_UNSPEC, 0); + herrnop, AF_UNSPEC, 0, &in6_zone_id); if (status != NSS_STATUS_SUCCESS) break; @@ -448,7 +486,7 @@ _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, got_canon = true; (*pat)->family = result.h_addrtype; memcpy ((*pat)->addr, result.h_addr_list[0], result.h_length); - (*pat)->scopeid = 0; + (*pat)->scopeid = in6_zone_id; pat = &((*pat)->next);