This is the mail archive of the glibc-cvs@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]

GNU C Library master sources branch master updated. glibc-2.24-143-g80d8cb9


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  80d8cb91dee8bdcc4e430b3e2620d95f89b1ee0b (commit)
      from  a0a9b6e376b75c07b4f65f270f008ce035bbf536 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=80d8cb91dee8bdcc4e430b3e2620d95f89b1ee0b

commit 80d8cb91dee8bdcc4e430b3e2620d95f89b1ee0b
Author: Florian Weimer <fweimer@redhat.com>
Date:   Thu Sep 15 15:46:30 2016 +0200

    inet: Add __inet6_scopeid_pton function [BZ #20611]
    
    __inet6_scopeid_pton implements strict validation of numeric scope IDs.
    Use it in getaddrinfo and __res_vinit.

diff --git a/ChangeLog b/ChangeLog
index 646c336..9845c66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2016-09-15  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #20611]
+	* inet/Makefile (routines): Add inet6_scopeid_pton.
+	(tests): Add tst-inet6_scopeid_pton.
+	* inet/inet6_scopeid_pton.c: New file.
+	* inet/net-internal.h: Likewise.
+	* inet/tst-inet6_scopeid_pton.c: New test.
+	* inet/Versions (GLIBC_PRIVATE): Add __inet6_scopeid_pton.
+	* resolv/res_init.c (__res_vinit): Use __inet6_scopeid_pton.
+	* sysdeps/posix/getaddrinfo.c (gaih_inet): Likewise.
+
 2016-09-14  Florian Weimer  <fweimer@redhat.com>
 
 	Remove support for compiling wrappers with PTW.
diff --git a/inet/Makefile b/inet/Makefile
index 2207b93..1c30932 100644
--- a/inet/Makefile
+++ b/inet/Makefile
@@ -44,13 +44,15 @@ routines := htonl htons		\
 	    getaliasent_r getaliasent getaliasname getaliasname_r \
 	    in6_addr getnameinfo if_index ifaddrs inet6_option \
 	    getipv4sourcefilter setipv4sourcefilter \
-	    getsourcefilter setsourcefilter inet6_opt inet6_rth
+	    getsourcefilter setsourcefilter inet6_opt inet6_rth \
+	    inet6_scopeid_pton
 
 aux := check_pf check_native ifreq
 
 tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
 	 tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
-	 tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-sockaddr
+	 tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-sockaddr \
+	 tst-inet6_scopeid_pton
 
 include ../Rules
 
diff --git a/inet/Versions b/inet/Versions
index 56eb274..6f663f3 100644
--- a/inet/Versions
+++ b/inet/Versions
@@ -85,5 +85,8 @@ libc {
     # functions used in other libraries
     __internal_endnetgrent; __internal_getnetgrent_r;
     __internal_setnetgrent;
+
+    # Used from nscd.
+    __inet6_scopeid_pton;
   }
 }
diff --git a/inet/inet6_scopeid_pton.c b/inet/inet6_scopeid_pton.c
new file mode 100644
index 0000000..aa37392
--- /dev/null
+++ b/inet/inet6_scopeid_pton.c
@@ -0,0 +1,63 @@
+/* Convert an IPv6 scope ID from text to the internal representation.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <net-internal.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <locale.h>
+#include <net/if.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/* Parse SOURCE as a scope ID for ADDRESS.  Return 0 on success and -1
+   on error.  */
+internal_function int
+__inet6_scopeid_pton (const struct in6_addr *address, const char *scope,
+                      uint32_t *result)
+{
+  if (IN6_IS_ADDR_LINKLOCAL (address)
+      || IN6_IS_ADDR_MC_LINKLOCAL (address))
+    {
+      uint32_t number = __if_nametoindex (scope);
+      if (number != 0)
+        {
+          *result = number;
+          return 0;
+        }
+    }
+
+  if (isdigit_l (scope[0], _nl_C_locobj_ptr))
+    {
+      char *end;
+      unsigned long long number
+        = ____strtoull_l_internal (scope, &end, /*base */ 10, /* group */ 0,
+                                   _nl_C_locobj_ptr);
+      if (*end == '\0' && number <= UINT32_MAX)
+        {
+          *result = number;
+          return 0;
+        }
+    }
+
+  __set_errno (EINVAL);
+  return -1;
+}
+
+libc_hidden_def (__inet6_scopeid_pton)
diff --git a/inet/net-internal.h b/inet/net-internal.h
new file mode 100644
index 0000000..961d1f7
--- /dev/null
+++ b/inet/net-internal.h
@@ -0,0 +1,30 @@
+/* Network-related functions for internal library use.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _NET_INTERNAL_H
+#define _NET_INTERNAL_H 1
+
+#include <arpa/inet.h>
+#include <stdint.h>
+
+int __inet6_scopeid_pton (const struct in6_addr *address,
+                          const char *scope, uint32_t *result)
+  internal_function attribute_hidden;
+libc_hidden_proto (__inet6_scopeid_pton)
+
+#endif /* _NET_INTERNAL_H */
diff --git a/inet/tst-inet6_scopeid_pton.c b/inet/tst-inet6_scopeid_pton.c
new file mode 100644
index 0000000..f9f541e
--- /dev/null
+++ b/inet/tst-inet6_scopeid_pton.c
@@ -0,0 +1,131 @@
+/* Tests for __inet6_scopeid_pton.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <arpa/inet.h>
+#include <inttypes.h>
+#include <net-internal.h>
+#include <net/if.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* An interface which is known to the system.  */
+static const char *interface_name;
+static uint32_t interface_index;
+
+/* Initiale the variables above.  */
+static void
+setup_interface (void)
+{
+  struct if_nameindex *list = if_nameindex ();
+  if (list != NULL && list[0].if_index != 0 && list[0].if_name[0] != '\0')
+    {
+      interface_name = list[0].if_name;
+      interface_index = list[0].if_index;
+    }
+}
+
+/* Convert ADDRESS to struct in6_addr.  */
+static struct in6_addr
+from_string (const char *address)
+{
+  struct in6_addr addr;
+  if (inet_pton (AF_INET6, address, &addr) != 1)
+    {
+      printf ("error: inet_pton (\"%s\") failed\n", address);
+      exit (1);
+    }
+  return addr;
+}
+
+/* Check a single address were we expected a failure.  */
+static void
+expect_failure (const char *address, const char *scope)
+{
+  struct in6_addr addr = from_string (address);
+  uint32_t result = 1234;
+  if (__inet6_scopeid_pton (&addr, scope, &result) == 0)
+    {
+      printf ("error: unexpected success for %s%%%s\n",
+              address, scope);
+      exit (1);
+    }
+  if (result != 1234)
+    {
+      printf ("error: unexpected result update for %s%%%s\n",
+              address, scope);
+      exit (1);
+    }
+}
+
+/* Check a single address were we expected a success.  */
+static void
+expect_success (const char *address, const char *scope, uint32_t expected)
+{
+  struct in6_addr addr = from_string (address);
+  uint32_t actual = expected + 1;
+  if (__inet6_scopeid_pton (&addr, scope, &actual) != 0)
+    {
+      printf ("error: unexpected failure for %s%%%s\n",
+              address, scope);
+      exit (1);
+    }
+  if (actual != expected)
+    {
+      printf ("error: unexpected result for for %s%%%s\n",
+              address, scope);
+      printf ("  expected: %" PRIu32 "\n", expected);
+      printf ("  actual:   %" PRIu32 "\n", actual);
+      exit (1);
+    }
+}
+
+static int
+do_test (void)
+{
+  setup_interface ();
+
+  static const char *test_addresses[]
+    = { "::", "::1", "2001:db8::1", NULL };
+  for (int i = 0; test_addresses[i] != NULL; ++i)
+    {
+      expect_success (test_addresses[i], "0", 0);
+      expect_success (test_addresses[i], "5555", 5555);
+
+      expect_failure (test_addresses[i], "");
+      expect_failure (test_addresses[i], "-1");
+      expect_failure (test_addresses[i], "-99");
+      expect_failure (test_addresses[i], "037777777777");
+      expect_failure (test_addresses[i], "0x");
+      expect_failure (test_addresses[i], "0x1");
+    }
+
+  if (interface_name != NULL)
+    {
+      expect_success ("fe80::1", interface_name, interface_index);
+      expect_success ("ff02::1", interface_name, interface_index);
+      expect_failure ("::", interface_name);
+      expect_failure ("::1", interface_name);
+      expect_failure ("ff01::1", interface_name);
+      expect_failure ("2001:db8::1", interface_name);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/resolv/res_init.c b/resolv/res_init.c
index cfb8188..bfae537 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -81,6 +81,7 @@
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <inet/net-internal.h>
 
 #include <not-cancel.h>
 
@@ -283,26 +284,12 @@ __res_vinit(res_state statp, int preinit) {
 				sa6->sin6_flowinfo = 0;
 				sa6->sin6_addr = a6;
 
-				if (__glibc_likely (el == NULL))
-				    sa6->sin6_scope_id = 0;
-				else {
-				    int try_numericscope = 1;
-				    if (IN6_IS_ADDR_LINKLOCAL (&a6)
-					|| IN6_IS_ADDR_MC_LINKLOCAL (&a6)) {
-					sa6->sin6_scope_id
-					  = __if_nametoindex (el + 1);
-					if (sa6->sin6_scope_id != 0)
-					    try_numericscope = 0;
-				    }
-
-				    if (try_numericscope) {
-					char *end;
-					sa6->sin6_scope_id
-					  = (uint32_t) strtoul (el + 1, &end,
-								10);
-					if (*end != '\0')
-					    sa6->sin6_scope_id = 0;
-				    }
+				sa6->sin6_scope_id = 0;
+				if (__glibc_likely (el != NULL)) {
+				  /* Ignore errors, for backwards
+				     compatibility.  */
+				  (void) __inet6_scopeid_pton
+				    (&a6, el + 1, &sa6->sin6_scope_id);
 				}
 
 				statp->nsaddr_list[nserv].sin_family = 0;
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 09fbc83..740e955 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -82,6 +82,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <nscd/nscd_proto.h>
 #include <resolv/res_hconf.h>
 #include <scratch_buffer.h>
+#include <inet/net-internal.h>
 
 #ifdef HAVE_LIBIDN
 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
@@ -570,31 +571,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
 		  goto free_and_return;
 		}
 
-	      if (scope_delim != NULL)
+	      if (scope_delim != NULL
+		  && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
+					   scope_delim + 1,
+					   &at->scopeid) != 0)
 		{
-		  int try_numericscope = 0;
-		  if (IN6_IS_ADDR_LINKLOCAL (at->addr)
-		      || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
-		    {
-		      at->scopeid = if_nametoindex (scope_delim + 1);
-		      if (at->scopeid == 0)
-			try_numericscope = 1;
-		    }
-		  else
-		    try_numericscope = 1;
-
-		  if (try_numericscope != 0)
-		    {
-		      char *end;
-		      assert (sizeof (uint32_t) <= sizeof (unsigned long));
-		      at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
-							10);
-		      if (*end != '\0')
-			{
-			  result = -EAI_NONAME;
-			  goto free_and_return;
-			}
-		    }
+		  result = -EAI_NONAME;
+		  goto free_and_return;
 		}
 
 	      if (req->ai_flags & AI_CANONNAME)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                     |   12 ++++
 inet/Makefile                 |    6 +-
 inet/Versions                 |    3 +
 inet/inet6_scopeid_pton.c     |   63 ++++++++++++++++++++
 inet/net-internal.h           |   30 +++++++++
 inet/tst-inet6_scopeid_pton.c |  131 +++++++++++++++++++++++++++++++++++++++++
 resolv/res_init.c             |   27 ++------
 sysdeps/posix/getaddrinfo.c   |   31 ++--------
 8 files changed, 257 insertions(+), 46 deletions(-)
 create mode 100644 inet/inet6_scopeid_pton.c
 create mode 100644 inet/net-internal.h
 create mode 100644 inet/tst-inet6_scopeid_pton.c


hooks/post-receive
-- 
GNU C Library master sources


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