This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][PATCH 2/4][BZ 17083] NSS: Parse zone identifier of IPv6 addresses in /etc/hosts


Parse link-local IPv6 addresses in /etc/hosts, which contain zone
identifiers as described in RFC 4007.

Signed-off-by: Łukasz Stelmach <stlman@poczta.fm>
---
 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);
 
-- 
2.11.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]