You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by jo...@apache.org on 2017/11/29 08:53:28 UTC

svn commit: r1816608 - in /apr/apr/branches/1.7.x: ./ CHANGES configure.in include/apr_network_io.h include/arch/win32/apr_private.h network_io/unix/sockaddr.c test/testsock.c

Author: jorton
Date: Wed Nov 29 08:53:28 2017
New Revision: 1816608

URL: http://svn.apache.org/viewvc?rev=1816608&view=rev
Log:
Merge r1816527 from trunk:

Support IPv6 link-local address scope/zone mapping.

* network_io/unix/sockaddr.c (apr_sockaddr_zone_set,
  apr_sockaddr_zone_get): New functions.
  (apr_sockaddr_ip_getbuf): Append %scope for link-local address.
  (apr_sockaddr_equal): Compare link-local address with different
  scopes as not equal.

* include/apr_network_io.h: Add function declarations.

* configure.in: Test for if_indextoname and if_nametoindex.

* test/testsock.c (test_zone): New test case.

* include/arch/win32/apr_private.h: Assume Windows supports
  if_nametoindex and if_indextoname.


Modified:
    apr/apr/branches/1.7.x/   (props changed)
    apr/apr/branches/1.7.x/CHANGES
    apr/apr/branches/1.7.x/configure.in
    apr/apr/branches/1.7.x/include/apr_network_io.h
    apr/apr/branches/1.7.x/include/arch/win32/apr_private.h
    apr/apr/branches/1.7.x/network_io/unix/sockaddr.c
    apr/apr/branches/1.7.x/test/testsock.c

Propchange: apr/apr/branches/1.7.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Nov 29 08:53:28 2017
@@ -1,4 +1,4 @@
 /apr/apr/branches/1.4.x:1003369,1101301
-/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,899905,901088,902077,902090,908427,910419,910597,917819,917837-917838,923311,923320,925965,929796,930508,931973,932585,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,143
 8940,1438957-1438959,1442903,1449568,1456418,1459994,1460179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1589982,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,
 1611466,1611515,1611517,1625173,1626564,1634615,1642159,1648830,1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667900-1667901,1667903,1667914-1667916,1667962,1669077,1671292,1671329,1671356,1671386,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1683521,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1732582,1733451,1733594,1733694,1733706,1733708,1733775,1734816,1736552,1738791,1738925,1750374,1755709,1755740,1755746,1755758,1755954,1761279,1762326,1774712,1774973,1775069,1776994,1776998,1788334,1788337,1788929,1789947,1789998,1790045,1790200,1790296,1790302-1790304,1790330-1790331,1790436,1790439,1790444,1790446,1790488,1790521,1790523,1790569,1790632,1791598,1791718,1791728,1792621-1792622,1792625,1792961,1792963,1797415,1798105,1805380,1808039,1808836,1809649,1810452,1813286
+/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,899905,901088,902077,902090,908427,910419,910597,917819,917837-917838,923311,923320,925965,929796,930508,931973,932585,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,143
 8940,1438957-1438959,1442903,1449568,1456418,1459994,1460179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1589982,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,
 1611466,1611515,1611517,1625173,1626564,1634615,1642159,1648830,1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667900-1667901,1667903,1667914-1667916,1667962,1669077,1671292,1671329,1671356,1671386,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1683521,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1732582,1733451,1733594,1733694,1733706,1733708,1733775,1734816,1736552,1738791,1738925,1750374,1755709,1755740,1755746,1755758,1755954,1761279,1762326,1774712,1774973,1775069,1776994,1776998,1788334,1788337,1788929,1789947,1789998,1790045,1790200,1790296,1790302-1790304,1790330-1790331,1790436,1790439,1790444,1790446,1790488,1790521,1790523,1790569,1790632,1791598,1791718,1791728,1792621-1792622,1792625,1792961,1792963,1797415,1798105,1805380,1808039,1808836,1809649,1810452,1813286,1816527
 /apr/apr/trunk/test/testnames.c:1460405
 /httpd/httpd/trunk:1604590

Modified: apr/apr/branches/1.7.x/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/CHANGES?rev=1816608&r1=1816607&r2=1816608&view=diff
==============================================================================
--- apr/apr/branches/1.7.x/CHANGES [utf-8] (original)
+++ apr/apr/branches/1.7.x/CHANGES [utf-8] Wed Nov 29 08:53:28 2017
@@ -1,6 +1,15 @@
                                                      -*- coding: utf-8 -*-
 Changes for APR 1.7.0
 
+  *) Add apr_sockaddr_zone_set, apr_sockaddr_zone_set to set and retrieve
+     the zone for link-local IPv6 addresses.  [Joe Orton]
+
+  *) apr_sockaddr_equal: Compare link-local IPv6 addresses with different
+     zones as not equal.  [Joe Orton]
+
+  *) apr_sockaddr_ip_getbuf, apr_sockaddr_ip_get: Append "%zone" for
+     IPv6 link-local addresses.  [Joe Orton]
+
   *) Locks: add a --disable-timedlocks config option in case users
      encounter more platforms where it fails [Nick Kew].
 

Modified: apr/apr/branches/1.7.x/configure.in
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/configure.in?rev=1816608&r1=1816607&r2=1816608&view=diff
==============================================================================
--- apr/apr/branches/1.7.x/configure.in (original)
+++ apr/apr/branches/1.7.x/configure.in Wed Nov 29 08:53:28 2017
@@ -1162,7 +1162,9 @@ case $host in
 #endif";;
 esac
 
-AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h sys/shm.h sys/file.h kernel/OS.h os2.h windows.h])
+AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h \
+                  sys/shm.h sys/file.h kernel/OS.h os2.h windows.h \
+                  net/if.h])
 AC_CHECK_FUNCS([mmap munmap shm_open shm_unlink shmget shmat shmdt shmctl \
                 create_area mprotect])
 
@@ -2756,7 +2758,7 @@ esac
 AC_SEARCH_LIBS(getaddrinfo, socket inet6)
 AC_SEARCH_LIBS(gai_strerror, socket inet6)
 AC_SEARCH_LIBS(getnameinfo, socket inet6)
-AC_CHECK_FUNCS(gai_strerror)
+AC_CHECK_FUNCS(gai_strerror if_nametoindex if_indextoname)
 APR_CHECK_WORKING_GETADDRINFO
 APR_CHECK_NEGATIVE_EAI
 APR_CHECK_WORKING_GETNAMEINFO

Modified: apr/apr/branches/1.7.x/include/apr_network_io.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/include/apr_network_io.h?rev=1816608&r1=1816607&r2=1816608&view=diff
==============================================================================
--- apr/apr/branches/1.7.x/include/apr_network_io.h (original)
+++ apr/apr/branches/1.7.x/include/apr_network_io.h Wed Nov 29 08:53:28 2017
@@ -441,6 +441,29 @@ APR_DECLARE(apr_status_t) apr_sockaddr_i
                                                  const apr_sockaddr_t *src,
                                                  apr_pool_t *p);
 
+/* Set the zone of an IPv6 link-local address object.
+ * @param sa Socket address object
+ * @param zone_id Zone ID (textual "eth0" or numeric "3").
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
+                                                const char *zone_id);
+
+
+/* Retrieve the zone of an IPv6 link-local address object.
+ * @param sa Socket address object
+ * @param name If non-NULL, set to the textual representation of the zone id
+ * @param id If non-NULL, set to the integer zone id
+ * @param p Pool from which *name is allocated if used.
+ * @return Returns APR_EBADIP for non-IPv6 socket or socket without any zone id
+ * set, or other error if the interface could not be mapped to a name.
+ * @remark Both name and id may be NULL, neither are modified if
+ * non-NULL in error cases.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
+                                                const char **name,
+                                                apr_uint32_t *id,
+                                                apr_pool_t *p);                                                
+    
 /**
  * Look up the host name from an apr_sockaddr_t.
  * @param hostname The hostname.

Modified: apr/apr/branches/1.7.x/include/arch/win32/apr_private.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/include/arch/win32/apr_private.h?rev=1816608&r1=1816607&r2=1816608&view=diff
==============================================================================
--- apr/apr/branches/1.7.x/include/arch/win32/apr_private.h (original)
+++ apr/apr/branches/1.7.x/include/arch/win32/apr_private.h Wed Nov 29 08:53:28 2017
@@ -140,6 +140,8 @@ APR_DECLARE_DATA int errno;
 #if APR_HAVE_IPV6
 #define HAVE_GETADDRINFO 1
 #define HAVE_GETNAMEINFO 1
+#define HAVE_IF_INDEXTONAME 1
+#define HAVE_IF_NAMETOINDEX 1
 #endif
 
 /* MSVC 7.0 introduced _strtoi64 */

Modified: apr/apr/branches/1.7.x/network_io/unix/sockaddr.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/network_io/unix/sockaddr.c?rev=1816608&r1=1816607&r2=1816608&view=diff
==============================================================================
--- apr/apr/branches/1.7.x/network_io/unix/sockaddr.c (original)
+++ apr/apr/branches/1.7.x/network_io/unix/sockaddr.c Wed Nov 29 08:53:28 2017
@@ -25,6 +25,10 @@
 #include <stdlib.h>
 #endif
 
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
 
@@ -125,9 +129,31 @@ APR_DECLARE(apr_status_t) apr_sockaddr_i
         memmove(buf, buf + strlen("::ffff:"),
                 strlen(buf + strlen("::ffff:"))+1);
     }
-#endif
+
     /* ensure NUL termination if the buffer is too short */
     buf[buflen-1] = '\0';
+
+#ifdef HAVE_IF_INDEXTONAME
+    /* Append scope name for link-local addresses. */
+    if (sockaddr->family == AF_INET6
+        && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sockaddr->ipaddr_ptr)) {
+        char scbuf[IF_NAMESIZE], *p = buf + strlen(buf);
+
+        if (if_indextoname(sockaddr->sa.sin6.sin6_scope_id, scbuf) == scbuf) {
+            /* Space check, need room for buf + '%' + scope + '\0'.
+             * Assert: buflen >= strlen(buf) + strlen(scbuf) + 2
+             * Equiv:  buflen >= (p-buf) + strlen(buf) + 2
+             * Thus, fail in inverse condition: */
+            if (buflen < strlen(scbuf) + (p - buf) + 2) {
+                return APR_ENOSPC;
+            }
+            *p++ = '%';
+            memcpy(p, scbuf, strlen(scbuf) + 1);
+        }
+    }    
+#endif /* HAVE_IF_INDEXTONAME */
+#endif /* APR_HAVE_IPV6 */
+
     return APR_SUCCESS;
 }
 
@@ -900,11 +926,19 @@ APR_DECLARE(apr_status_t) apr_getservbyn
          &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12],  \
          (a)->ipaddr_len))
 
+#if APR_HAVE_IPV6
+#define SCOPE_OR_ZERO(sa_) ((sa_)->family != AF_INET6 ? 0 :   \
+                            ((sa_)->sa.sin6.sin6_scope_id))
+#else
+#define SCOPE_OR_ZERO(sa_) (0)
+#endif
+
 APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
                                     const apr_sockaddr_t *addr2)
 {
-    if (addr1->ipaddr_len == addr2->ipaddr_len &&
-        !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)) {
+    if (addr1->ipaddr_len == addr2->ipaddr_len
+        && !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)
+        && SCOPE_OR_ZERO(addr1) == SCOPE_OR_ZERO(addr2)) {
         return 1;
     }
 #if APR_HAVE_IPV6
@@ -1183,3 +1217,63 @@ APR_DECLARE(int) apr_ipsubnet_test(apr_i
 #endif /* APR_HAVE_IPV6 */
     return 0; /* no match */
 }
+
+APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
+                                                const char *zone_id)
+{
+#if !APR_HAVE_IPV6 || !defined(HAVE_IF_NAMETOINDEX)
+    return APR_ENOTIMPL;
+#else
+    unsigned int idx;
+    
+    if (sa->family != APR_INET6) {
+        return APR_EBADIP;
+    }
+
+    idx = if_nametoindex(zone_id);
+    if (idx) {
+        sa->sa.sin6.sin6_scope_id = idx;
+        return APR_SUCCESS;
+    }
+
+    if (errno != ENODEV) {
+        return errno;
+    }
+    else {
+        char *endptr;
+        apr_int64_t i = apr_strtoi64(zone_id, &endptr, 10);
+
+        if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) {
+            return APR_EGENERAL;
+        }
+
+        sa->sa.sin6.sin6_scope_id = i;
+        return APR_SUCCESS;
+    }
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
+                                                const char **name,
+                                                apr_uint32_t *id,
+                                                apr_pool_t *p)
+{
+#if !APR_HAVE_IPV6 || !defined(HAVE_IF_INDEXTONAME)
+    return APR_ENOTIMPL;
+#else
+    if (sa->family != APR_INET6 || !sa->sa.sin6.sin6_scope_id) {
+        return APR_EBADIP;
+    }        
+
+    if (name) {
+        char *buf = apr_palloc(p, IF_NAMESIZE);
+        if (if_indextoname(sa->sa.sin6.sin6_scope_id, buf) == NULL)
+            return errno;
+        *name = buf;
+    }
+
+    if (id) *id = sa->sa.sin6.sin6_scope_id;
+    
+    return APR_SUCCESS;
+#endif
+}

Modified: apr/apr/branches/1.7.x/test/testsock.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/test/testsock.c?rev=1816608&r1=1816607&r2=1816608&view=diff
==============================================================================
--- apr/apr/branches/1.7.x/test/testsock.c (original)
+++ apr/apr/branches/1.7.x/test/testsock.c Wed Nov 29 08:53:28 2017
@@ -577,6 +577,98 @@ static void test_freebind(abts_case *tc,
 #endif
 }
 
+#define TEST_ZONE_ADDR "fe80::1"
+
+#ifdef __linux__
+/* Reasonable bet that "lo" will exist. */
+#define TEST_ZONE_NAME "lo"
+/* ... fill in other platforms here */
+#endif
+
+#ifdef TEST_ZONE_NAME 
+#define TEST_ZONE_FULLADDR TEST_ZONE_ADDR "%" TEST_ZONE_NAME
+#endif
+
+static void test_zone(abts_case *tc, void *data)
+{
+#if APR_HAVE_IPV6
+    apr_sockaddr_t *sa;
+    apr_status_t rv;
+    const char *name = NULL;
+    apr_uint32_t id = 0;
+    
+    /* RFC 5737 address */
+    rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_INET, 8080, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    /* Fail for an IPv4 address! */
+    ABTS_INT_EQUAL(tc, APR_EBADIP,
+                   apr_sockaddr_zone_set(sa, "1"));
+    ABTS_INT_EQUAL(tc, APR_EBADIP,
+                   apr_sockaddr_zone_get(sa, &name, &id, p));
+
+    rv = apr_sockaddr_info_get(&sa, TEST_ZONE_ADDR, APR_INET6, 8080, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    rv = apr_sockaddr_info_get(&sa, TEST_ZONE_ADDR, APR_INET6, 8080, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    ABTS_INT_EQUAL(tc, APR_EBADIP, apr_sockaddr_zone_get(sa, &name, &id, p));
+
+#ifdef TEST_ZONE_NAME
+    {
+        apr_sockaddr_t *sa2;
+        char buf[50];
+        
+        APR_ASSERT_SUCCESS(tc, "Set zone to " TEST_ZONE_NAME,
+                           apr_sockaddr_zone_set(sa, TEST_ZONE_NAME));
+        
+        APR_ASSERT_SUCCESS(tc, "Get zone",
+                           apr_sockaddr_zone_get(sa, NULL, NULL, p));
+        
+        APR_ASSERT_SUCCESS(tc, "Get zone",
+                           apr_sockaddr_zone_get(sa, &name, &id, p));
+        ABTS_STR_EQUAL(tc, TEST_ZONE_NAME, name);
+        ABTS_INT_NEQUAL(tc, 0, id); /* Only guarantee is that it should be non-zero */
+
+        /* Check string translation. */
+        APR_ASSERT_SUCCESS(tc, "get IP address",
+                           apr_sockaddr_ip_getbuf(buf, 50, sa));
+        ABTS_STR_EQUAL(tc, TEST_ZONE_FULLADDR, buf);
+
+        memset(buf, 'A', sizeof buf);
+        ABTS_INT_EQUAL(tc, APR_ENOSPC, apr_sockaddr_ip_getbuf(buf, strlen(TEST_ZONE_ADDR), sa));
+        ABTS_INT_EQUAL(tc, APR_ENOSPC, apr_sockaddr_ip_getbuf(buf, strlen(TEST_ZONE_FULLADDR), sa));
+        
+        APR_ASSERT_SUCCESS(tc, "get IP address",
+                           apr_sockaddr_ip_getbuf(buf, strlen(TEST_ZONE_FULLADDR) + 1, sa));
+        /* Check for overflow. */
+        ABTS_INT_EQUAL(tc, 'A', buf[strlen(buf) + 1]);
+        
+        rv = apr_sockaddr_info_copy(&sa2, sa, p);
+        APR_ASSERT_SUCCESS(tc, "Problem copying sockaddr", rv);
+
+        /* Copy copied zone matches */
+        APR_ASSERT_SUCCESS(tc, "Get zone",
+                           apr_sockaddr_zone_get(sa2, &name, &id, p));
+        ABTS_STR_EQUAL(tc, TEST_ZONE_NAME, name);
+        ABTS_INT_NEQUAL(tc, 0, id); /* Only guarantee is that it should be non-zero */
+
+        /* Should match self and copy */
+        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa, sa));
+        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa2, sa2));
+        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa2, sa));
+
+        /* Should not match against copy without zone set. */
+        rv = apr_sockaddr_info_get(&sa2, TEST_ZONE_ADDR, APR_INET6, 8080, 0, p);
+        APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+        ABTS_INT_EQUAL(tc, 0, apr_sockaddr_equal(sa2, sa));
+    }
+#endif /* TEST_ZONE_NAME */
+#endif /* APR_HAVE_IPV6 */
+}
+    
 abts_suite *testsock(abts_suite *suite)
 {
     suite = ADD_SUITE(suite)
@@ -593,6 +685,7 @@ abts_suite *testsock(abts_suite *suite)
     abts_run_test(suite, test_get_addr, NULL);
     abts_run_test(suite, test_nonblock_inheritance, NULL);
     abts_run_test(suite, test_freebind, NULL);
+    abts_run_test(suite, test_zone, NULL);
 
 #if APR_HAVE_SOCKADDR_UN
     socket_name = UNIX_SOCKET_NAME;



Re: svn commit: r1816608 - in /apr/apr/branches/1.7.x: ./ CHANGES configure.in include/apr_network_io.h include/arch/win32/apr_private.h network_io/unix/sockaddr.c test/testsock.c

Posted by Joe Orton <jo...@redhat.com>.
On Tue, Mar 19, 2019 at 03:27:23PM -0500, William A Rowe Jr wrote:
> Joe, are we certain zone index 0 is disallowed here?
> 
> +        apr_int64_t i = apr_strtoi64(zone_id, &endptr, 10);
> +
> +        if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) {
> +            return APR_EGENERAL;
> +        }

Apologies Bill - I missed this question.

Yes, I think this is safe, the index value must always be > 0 since 
if_nametoindex() returns zero on error thus that can't be a valid index.

https://tools.ietf.org/html/rfc3493#section-4.1

BTW I didn't test on Windows so I hope the code works OK there too, it 
looked like the standard sockets APIs were available.

If there is some Windows equivalent to "lo" on Linux then you could set:

#define TEST_ZONE_NAME ..

in test/testsock.c to as I did for #ifdef __linux__?

Regards, Joe


> 
> On Wed, Nov 29, 2017 at 2:53 AM <jo...@apache.org> wrote:
> 
> > Author: jorton
> > Date: Wed Nov 29 08:53:28 2017
> > New Revision: 1816608
> >
> > URL: http://svn.apache.org/viewvc?rev=1816608&view=rev
> > Log:
> > Merge r1816527 from trunk:
> >
> > Support IPv6 link-local address scope/zone mapping.
> >
> > * network_io/unix/sockaddr.c (apr_sockaddr_zone_set,
> >   apr_sockaddr_zone_get): New functions.
> >   (apr_sockaddr_ip_getbuf): Append %scope for link-local address.
> >   (apr_sockaddr_equal): Compare link-local address with different
> >   scopes as not equal.
> >
> > * include/apr_network_io.h: Add function declarations.
> >
> > * configure.in: Test for if_indextoname and if_nametoindex.
> >
> > * test/testsock.c (test_zone): New test case.
> >
> > * include/arch/win32/apr_private.h: Assume Windows supports
> >   if_nametoindex and if_indextoname.
> >
> >
> > Modified:
> >     apr/apr/branches/1.7.x/   (props changed)
> >     apr/apr/branches/1.7.x/CHANGES
> >     apr/apr/branches/1.7.x/configure.in
> >     apr/apr/branches/1.7.x/include/apr_network_io.h
> >     apr/apr/branches/1.7.x/include/arch/win32/apr_private.h
> >     apr/apr/branches/1.7.x/network_io/unix/sockaddr.c
> >     apr/apr/branches/1.7.x/test/testsock.c
> >
> > Propchange: apr/apr/branches/1.7.x/
> >
> > ------------------------------------------------------------------------------
> > --- svn:mergeinfo (original)
> > +++ svn:mergeinfo Wed Nov 29 08:53:28 2017
> > @@ -1,4 +1,4 @@
> >  /apr/apr/branches/1.4.x:1003369,1101301
> >
> > -/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,899905,901088,902077,902090,908427,910419,910597,917819,917837-917838,923311,923320,925965,929796,930508,931973,932585,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,143
> >
> >  8940,1438957-1438959,1442903,1449568,1456418,1459994,1460179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1589982,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,
> >
> >  1611466,1611515,1611517,1625173,1626564,1634615,1642159,1648830,1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667900-1667901,1667903,1667914-1667916,1667962,1669077,1671292,1671329,1671356,1671386,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1683521,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1732582,1733451,1733594,1733694,1733706,1733708,1733775,1734816,1736552,1738791,1738925,1750374,1755709,1755740,1755746,1755758,1755954,1761279,1762326,1774712,1774973,1775069,1776994,1776998,1788334,1788337,1788929,1789947,1789998,1790045,1790200,1790296,1790302-1790304,1790330-1790331,1790436,1790439,1790444,1790446,1790488,1790521,1790523,1790569,1790632,1791598,1791718,1791728,1792621-1792622,1792625,1792961,1792963,1797415,1798105,1805380,1808039,1808836,1809649,1810452,1813286
> >
> > +/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,899905,901088,902077,902090,908427,910419,910597,917819,917837-917838,923311,923320,925965,929796,930508,931973,932585,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,143
> >
> >  8940,1438957-1438959,1442903,1449568,1456418,1459994,1460179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1589982,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,
> >
> >  1611466,1611515,1611517,1625173,1626564,1634615,1642159,1648830,1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667900-1667901,1667903,1667914-1667916,1667962,1669077,1671292,1671329,1671356,1671386,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1683521,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1732582,1733451,1733594,1733694,1733706,1733708,1733775,1734816,1736552,1738791,1738925,1750374,1755709,1755740,1755746,1755758,1755954,1761279,1762326,1774712,1774973,1775069,1776994,1776998,1788334,1788337,1788929,1789947,1789998,1790045,1790200,1790296,1790302-1790304,1790330-1790331,1790436,1790439,1790444,1790446,1790488,1790521,1790523,1790569,1790632,1791598,1791718,1791728,1792621-1792622,1792625,1792961,1792963,1797415,1798105,1805380,1808039,1808836,1809649,1810452,1813286,1816527
> >  /apr/apr/trunk/test/testnames.c:1460405
> >  /httpd/httpd/trunk:1604590
> >
> > Modified: apr/apr/branches/1.7.x/CHANGES
> > URL:
> > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/CHANGES?rev=1816608&r1=1816607&r2=1816608&view=diff
> >
> > ==============================================================================
> > --- apr/apr/branches/1.7.x/CHANGES [utf-8] (original)
> > +++ apr/apr/branches/1.7.x/CHANGES [utf-8] Wed Nov 29 08:53:28 2017
> > @@ -1,6 +1,15 @@
> >                                                       -*- coding: utf-8 -*-
> >  Changes for APR 1.7.0
> >
> > +  *) Add apr_sockaddr_zone_set, apr_sockaddr_zone_set to set and retrieve
> > +     the zone for link-local IPv6 addresses.  [Joe Orton]
> > +
> > +  *) apr_sockaddr_equal: Compare link-local IPv6 addresses with different
> > +     zones as not equal.  [Joe Orton]
> > +
> > +  *) apr_sockaddr_ip_getbuf, apr_sockaddr_ip_get: Append "%zone" for
> > +     IPv6 link-local addresses.  [Joe Orton]
> > +
> >    *) Locks: add a --disable-timedlocks config option in case users
> >       encounter more platforms where it fails [Nick Kew].
> >
> >
> > Modified: apr/apr/branches/1.7.x/configure.in
> > URL:
> > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/configure.in?rev=1816608&r1=1816607&r2=1816608&view=diff
> >
> > ==============================================================================
> > --- apr/apr/branches/1.7.x/configure.in (original)
> > +++ apr/apr/branches/1.7.x/configure.in Wed Nov 29 08:53:28 2017
> > @@ -1162,7 +1162,9 @@ case $host in
> >  #endif";;
> >  esac
> >
> > -AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h sys/shm.h
> > sys/file.h kernel/OS.h os2.h windows.h])
> > +AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h \
> > +                  sys/shm.h sys/file.h kernel/OS.h os2.h windows.h \
> > +                  net/if.h])
> >  AC_CHECK_FUNCS([mmap munmap shm_open shm_unlink shmget shmat shmdt shmctl
> > \
> >                  create_area mprotect])
> >
> > @@ -2756,7 +2758,7 @@ esac
> >  AC_SEARCH_LIBS(getaddrinfo, socket inet6)
> >  AC_SEARCH_LIBS(gai_strerror, socket inet6)
> >  AC_SEARCH_LIBS(getnameinfo, socket inet6)
> > -AC_CHECK_FUNCS(gai_strerror)
> > +AC_CHECK_FUNCS(gai_strerror if_nametoindex if_indextoname)
> >  APR_CHECK_WORKING_GETADDRINFO
> >  APR_CHECK_NEGATIVE_EAI
> >  APR_CHECK_WORKING_GETNAMEINFO
> >
> > Modified: apr/apr/branches/1.7.x/include/apr_network_io.h
> > URL:
> > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/include/apr_network_io.h?rev=1816608&r1=1816607&r2=1816608&view=diff
> >
> > ==============================================================================
> > --- apr/apr/branches/1.7.x/include/apr_network_io.h (original)
> > +++ apr/apr/branches/1.7.x/include/apr_network_io.h Wed Nov 29 08:53:28
> > 2017
> > @@ -441,6 +441,29 @@ APR_DECLARE(apr_status_t) apr_sockaddr_i
> >                                                   const apr_sockaddr_t
> > *src,
> >                                                   apr_pool_t *p);
> >
> > +/* Set the zone of an IPv6 link-local address object.
> > + * @param sa Socket address object
> > + * @param zone_id Zone ID (textual "eth0" or numeric "3").
> > + */
> > +APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
> > +                                                const char *zone_id);
> > +
> > +
> > +/* Retrieve the zone of an IPv6 link-local address object.
> > + * @param sa Socket address object
> > + * @param name If non-NULL, set to the textual representation of the zone
> > id
> > + * @param id If non-NULL, set to the integer zone id
> > + * @param p Pool from which *name is allocated if used.
> > + * @return Returns APR_EBADIP for non-IPv6 socket or socket without any
> > zone id
> > + * set, or other error if the interface could not be mapped to a name.
> > + * @remark Both name and id may be NULL, neither are modified if
> > + * non-NULL in error cases.
> > + */
> > +APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
> > +                                                const char **name,
> > +                                                apr_uint32_t *id,
> > +                                                apr_pool_t *p);
> >
> > +
> >  /**
> >   * Look up the host name from an apr_sockaddr_t.
> >   * @param hostname The hostname.
> >
> > Modified: apr/apr/branches/1.7.x/include/arch/win32/apr_private.h
> > URL:
> > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/include/arch/win32/apr_private.h?rev=1816608&r1=1816607&r2=1816608&view=diff
> >
> > ==============================================================================
> > --- apr/apr/branches/1.7.x/include/arch/win32/apr_private.h (original)
> > +++ apr/apr/branches/1.7.x/include/arch/win32/apr_private.h Wed Nov 29
> > 08:53:28 2017
> > @@ -140,6 +140,8 @@ APR_DECLARE_DATA int errno;
> >  #if APR_HAVE_IPV6
> >  #define HAVE_GETADDRINFO 1
> >  #define HAVE_GETNAMEINFO 1
> > +#define HAVE_IF_INDEXTONAME 1
> > +#define HAVE_IF_NAMETOINDEX 1
> >  #endif
> >
> >  /* MSVC 7.0 introduced _strtoi64 */
> >
> > Modified: apr/apr/branches/1.7.x/network_io/unix/sockaddr.c
> > URL:
> > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/network_io/unix/sockaddr.c?rev=1816608&r1=1816607&r2=1816608&view=diff
> >
> > ==============================================================================
> > --- apr/apr/branches/1.7.x/network_io/unix/sockaddr.c (original)
> > +++ apr/apr/branches/1.7.x/network_io/unix/sockaddr.c Wed Nov 29 08:53:28
> > 2017
> > @@ -25,6 +25,10 @@
> >  #include <stdlib.h>
> >  #endif
> >
> > +#ifdef HAVE_NET_IF_H
> > +#include <net/if.h>
> > +#endif
> > +
> >  #define APR_WANT_STRFUNC
> >  #include "apr_want.h"
> >
> > @@ -125,9 +129,31 @@ APR_DECLARE(apr_status_t) apr_sockaddr_i
> >          memmove(buf, buf + strlen("::ffff:"),
> >                  strlen(buf + strlen("::ffff:"))+1);
> >      }
> > -#endif
> > +
> >      /* ensure NUL termination if the buffer is too short */
> >      buf[buflen-1] = '\0';
> > +
> > +#ifdef HAVE_IF_INDEXTONAME
> > +    /* Append scope name for link-local addresses. */
> > +    if (sockaddr->family == AF_INET6
> > +        && IN6_IS_ADDR_LINKLOCAL((struct in6_addr
> > *)sockaddr->ipaddr_ptr)) {
> > +        char scbuf[IF_NAMESIZE], *p = buf + strlen(buf);
> > +
> > +        if (if_indextoname(sockaddr->sa.sin6.sin6_scope_id, scbuf) ==
> > scbuf) {
> > +            /* Space check, need room for buf + '%' + scope + '\0'.
> > +             * Assert: buflen >= strlen(buf) + strlen(scbuf) + 2
> > +             * Equiv:  buflen >= (p-buf) + strlen(buf) + 2
> > +             * Thus, fail in inverse condition: */
> > +            if (buflen < strlen(scbuf) + (p - buf) + 2) {
> > +                return APR_ENOSPC;
> > +            }
> > +            *p++ = '%';
> > +            memcpy(p, scbuf, strlen(scbuf) + 1);
> > +        }
> > +    }
> > +#endif /* HAVE_IF_INDEXTONAME */
> > +#endif /* APR_HAVE_IPV6 */
> > +
> >      return APR_SUCCESS;
> >  }
> >
> > @@ -900,11 +926,19 @@ APR_DECLARE(apr_status_t) apr_getservbyn
> >           &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12],  \
> >           (a)->ipaddr_len))
> >
> > +#if APR_HAVE_IPV6
> > +#define SCOPE_OR_ZERO(sa_) ((sa_)->family != AF_INET6 ? 0 :   \
> > +                            ((sa_)->sa.sin6.sin6_scope_id))
> > +#else
> > +#define SCOPE_OR_ZERO(sa_) (0)
> > +#endif
> > +
> >  APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
> >                                      const apr_sockaddr_t *addr2)
> >  {
> > -    if (addr1->ipaddr_len == addr2->ipaddr_len &&
> > -        !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len))
> > {
> > +    if (addr1->ipaddr_len == addr2->ipaddr_len
> > +        && !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr,
> > addr1->ipaddr_len)
> > +        && SCOPE_OR_ZERO(addr1) == SCOPE_OR_ZERO(addr2)) {
> >          return 1;
> >      }
> >  #if APR_HAVE_IPV6
> > @@ -1183,3 +1217,63 @@ APR_DECLARE(int) apr_ipsubnet_test(apr_i
> >  #endif /* APR_HAVE_IPV6 */
> >      return 0; /* no match */
> >  }
> > +
> > +APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
> > +                                                const char *zone_id)
> > +{
> > +#if !APR_HAVE_IPV6 || !defined(HAVE_IF_NAMETOINDEX)
> > +    return APR_ENOTIMPL;
> > +#else
> > +    unsigned int idx;
> > +
> > +    if (sa->family != APR_INET6) {
> > +        return APR_EBADIP;
> > +    }
> > +
> > +    idx = if_nametoindex(zone_id);
> > +    if (idx) {
> > +        sa->sa.sin6.sin6_scope_id = idx;
> > +        return APR_SUCCESS;
> > +    }
> > +
> > +    if (errno != ENODEV) {
> > +        return errno;
> > +    }
> > +    else {
> > +        char *endptr;
> > +        apr_int64_t i = apr_strtoi64(zone_id, &endptr, 10);
> > +
> > +        if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) {
> > +            return APR_EGENERAL;
> > +        }
> > +
> > +        sa->sa.sin6.sin6_scope_id = i;
> > +        return APR_SUCCESS;
> > +    }
> > +#endif
> > +}
> > +
> > +APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
> > +                                                const char **name,
> > +                                                apr_uint32_t *id,
> > +                                                apr_pool_t *p)
> > +{
> > +#if !APR_HAVE_IPV6 || !defined(HAVE_IF_INDEXTONAME)
> > +    return APR_ENOTIMPL;
> > +#else
> > +    if (sa->family != APR_INET6 || !sa->sa.sin6.sin6_scope_id) {
> > +        return APR_EBADIP;
> > +    }
> > +
> > +    if (name) {
> > +        char *buf = apr_palloc(p, IF_NAMESIZE);
> > +        if (if_indextoname(sa->sa.sin6.sin6_scope_id, buf) == NULL)
> > +            return errno;
> > +        *name = buf;
> > +    }
> > +
> > +    if (id) *id = sa->sa.sin6.sin6_scope_id;
> > +
> > +    return APR_SUCCESS;
> > +#endif
> > +}
> >
> > Modified: apr/apr/branches/1.7.x/test/testsock.c
> > URL:
> > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/test/testsock.c?rev=1816608&r1=1816607&r2=1816608&view=diff
> >
> > ==============================================================================
> > --- apr/apr/branches/1.7.x/test/testsock.c (original)
> > +++ apr/apr/branches/1.7.x/test/testsock.c Wed Nov 29 08:53:28 2017
> > @@ -577,6 +577,98 @@ static void test_freebind(abts_case *tc,
> >  #endif
> >  }
> >
> > +#define TEST_ZONE_ADDR "fe80::1"
> > +
> > +#ifdef __linux__
> > +/* Reasonable bet that "lo" will exist. */
> > +#define TEST_ZONE_NAME "lo"
> > +/* ... fill in other platforms here */
> > +#endif
> > +
> > +#ifdef TEST_ZONE_NAME
> > +#define TEST_ZONE_FULLADDR TEST_ZONE_ADDR "%" TEST_ZONE_NAME
> > +#endif
> > +
> > +static void test_zone(abts_case *tc, void *data)
> > +{
> > +#if APR_HAVE_IPV6
> > +    apr_sockaddr_t *sa;
> > +    apr_status_t rv;
> > +    const char *name = NULL;
> > +    apr_uint32_t id = 0;
> > +
> > +    /* RFC 5737 address */
> > +    rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_INET, 8080, 0, p);
> > +    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
> > +
> > +    /* Fail for an IPv4 address! */
> > +    ABTS_INT_EQUAL(tc, APR_EBADIP,
> > +                   apr_sockaddr_zone_set(sa, "1"));
> > +    ABTS_INT_EQUAL(tc, APR_EBADIP,
> > +                   apr_sockaddr_zone_get(sa, &name, &id, p));
> > +
> > +    rv = apr_sockaddr_info_get(&sa, TEST_ZONE_ADDR, APR_INET6, 8080, 0,
> > p);
> > +    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
> > +
> > +    rv = apr_sockaddr_info_get(&sa, TEST_ZONE_ADDR, APR_INET6, 8080, 0,
> > p);
> > +    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
> > +
> > +    ABTS_INT_EQUAL(tc, APR_EBADIP, apr_sockaddr_zone_get(sa, &name, &id,
> > p));
> > +
> > +#ifdef TEST_ZONE_NAME
> > +    {
> > +        apr_sockaddr_t *sa2;
> > +        char buf[50];
> > +
> > +        APR_ASSERT_SUCCESS(tc, "Set zone to " TEST_ZONE_NAME,
> > +                           apr_sockaddr_zone_set(sa, TEST_ZONE_NAME));
> > +
> > +        APR_ASSERT_SUCCESS(tc, "Get zone",
> > +                           apr_sockaddr_zone_get(sa, NULL, NULL, p));
> > +
> > +        APR_ASSERT_SUCCESS(tc, "Get zone",
> > +                           apr_sockaddr_zone_get(sa, &name, &id, p));
> > +        ABTS_STR_EQUAL(tc, TEST_ZONE_NAME, name);
> > +        ABTS_INT_NEQUAL(tc, 0, id); /* Only guarantee is that it should
> > be non-zero */
> > +
> > +        /* Check string translation. */
> > +        APR_ASSERT_SUCCESS(tc, "get IP address",
> > +                           apr_sockaddr_ip_getbuf(buf, 50, sa));
> > +        ABTS_STR_EQUAL(tc, TEST_ZONE_FULLADDR, buf);
> > +
> > +        memset(buf, 'A', sizeof buf);
> > +        ABTS_INT_EQUAL(tc, APR_ENOSPC, apr_sockaddr_ip_getbuf(buf,
> > strlen(TEST_ZONE_ADDR), sa));
> > +        ABTS_INT_EQUAL(tc, APR_ENOSPC, apr_sockaddr_ip_getbuf(buf,
> > strlen(TEST_ZONE_FULLADDR), sa));
> > +
> > +        APR_ASSERT_SUCCESS(tc, "get IP address",
> > +                           apr_sockaddr_ip_getbuf(buf,
> > strlen(TEST_ZONE_FULLADDR) + 1, sa));
> > +        /* Check for overflow. */
> > +        ABTS_INT_EQUAL(tc, 'A', buf[strlen(buf) + 1]);
> > +
> > +        rv = apr_sockaddr_info_copy(&sa2, sa, p);
> > +        APR_ASSERT_SUCCESS(tc, "Problem copying sockaddr", rv);
> > +
> > +        /* Copy copied zone matches */
> > +        APR_ASSERT_SUCCESS(tc, "Get zone",
> > +                           apr_sockaddr_zone_get(sa2, &name, &id, p));
> > +        ABTS_STR_EQUAL(tc, TEST_ZONE_NAME, name);
> > +        ABTS_INT_NEQUAL(tc, 0, id); /* Only guarantee is that it should
> > be non-zero */
> > +
> > +        /* Should match self and copy */
> > +        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa, sa));
> > +        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa2, sa2));
> > +        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa2, sa));
> > +
> > +        /* Should not match against copy without zone set. */
> > +        rv = apr_sockaddr_info_get(&sa2, TEST_ZONE_ADDR, APR_INET6, 8080,
> > 0, p);
> > +        APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
> > +
> > +        ABTS_INT_EQUAL(tc, 0, apr_sockaddr_equal(sa2, sa));
> > +    }
> > +#endif /* TEST_ZONE_NAME */
> > +#endif /* APR_HAVE_IPV6 */
> > +}
> > +
> >  abts_suite *testsock(abts_suite *suite)
> >  {
> >      suite = ADD_SUITE(suite)
> > @@ -593,6 +685,7 @@ abts_suite *testsock(abts_suite *suite)
> >      abts_run_test(suite, test_get_addr, NULL);
> >      abts_run_test(suite, test_nonblock_inheritance, NULL);
> >      abts_run_test(suite, test_freebind, NULL);
> > +    abts_run_test(suite, test_zone, NULL);
> >
> >  #if APR_HAVE_SOCKADDR_UN
> >      socket_name = UNIX_SOCKET_NAME;
> >
> >
> >

Re: svn commit: r1816608 - in /apr/apr/branches/1.7.x: ./ CHANGES configure.in include/apr_network_io.h include/arch/win32/apr_private.h network_io/unix/sockaddr.c test/testsock.c

Posted by William A Rowe Jr <wr...@rowe-clan.net>.
Joe, are we certain zone index 0 is disallowed here?

+        apr_int64_t i = apr_strtoi64(zone_id, &endptr, 10);
+
+        if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) {
+            return APR_EGENERAL;
+        }

On Wed, Nov 29, 2017 at 2:53 AM <jo...@apache.org> wrote:

> Author: jorton
> Date: Wed Nov 29 08:53:28 2017
> New Revision: 1816608
>
> URL: http://svn.apache.org/viewvc?rev=1816608&view=rev
> Log:
> Merge r1816527 from trunk:
>
> Support IPv6 link-local address scope/zone mapping.
>
> * network_io/unix/sockaddr.c (apr_sockaddr_zone_set,
>   apr_sockaddr_zone_get): New functions.
>   (apr_sockaddr_ip_getbuf): Append %scope for link-local address.
>   (apr_sockaddr_equal): Compare link-local address with different
>   scopes as not equal.
>
> * include/apr_network_io.h: Add function declarations.
>
> * configure.in: Test for if_indextoname and if_nametoindex.
>
> * test/testsock.c (test_zone): New test case.
>
> * include/arch/win32/apr_private.h: Assume Windows supports
>   if_nametoindex and if_indextoname.
>
>
> Modified:
>     apr/apr/branches/1.7.x/   (props changed)
>     apr/apr/branches/1.7.x/CHANGES
>     apr/apr/branches/1.7.x/configure.in
>     apr/apr/branches/1.7.x/include/apr_network_io.h
>     apr/apr/branches/1.7.x/include/arch/win32/apr_private.h
>     apr/apr/branches/1.7.x/network_io/unix/sockaddr.c
>     apr/apr/branches/1.7.x/test/testsock.c
>
> Propchange: apr/apr/branches/1.7.x/
>
> ------------------------------------------------------------------------------
> --- svn:mergeinfo (original)
> +++ svn:mergeinfo Wed Nov 29 08:53:28 2017
> @@ -1,4 +1,4 @@
>  /apr/apr/branches/1.4.x:1003369,1101301
>
> -/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,899905,901088,902077,902090,908427,910419,910597,917819,917837-917838,923311,923320,925965,929796,930508,931973,932585,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,143
>
>  8940,1438957-1438959,1442903,1449568,1456418,1459994,1460179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1589982,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,
>
>  1611466,1611515,1611517,1625173,1626564,1634615,1642159,1648830,1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667900-1667901,1667903,1667914-1667916,1667962,1669077,1671292,1671329,1671356,1671386,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1683521,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1732582,1733451,1733594,1733694,1733706,1733708,1733775,1734816,1736552,1738791,1738925,1750374,1755709,1755740,1755746,1755758,1755954,1761279,1762326,1774712,1774973,1775069,1776994,1776998,1788334,1788337,1788929,1789947,1789998,1790045,1790200,1790296,1790302-1790304,1790330-1790331,1790436,1790439,1790444,1790446,1790488,1790521,1790523,1790569,1790632,1791598,1791718,1791728,1792621-1792622,1792625,1792961,1792963,1797415,1798105,1805380,1808039,1808836,1809649,1810452,1813286
>
> +/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,899905,901088,902077,902090,908427,910419,910597,917819,917837-917838,923311,923320,925965,929796,930508,931973,932585,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,143
>
>  8940,1438957-1438959,1442903,1449568,1456418,1459994,1460179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1589982,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,
>
>  1611466,1611515,1611517,1625173,1626564,1634615,1642159,1648830,1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667900-1667901,1667903,1667914-1667916,1667962,1669077,1671292,1671329,1671356,1671386,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1683521,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1732582,1733451,1733594,1733694,1733706,1733708,1733775,1734816,1736552,1738791,1738925,1750374,1755709,1755740,1755746,1755758,1755954,1761279,1762326,1774712,1774973,1775069,1776994,1776998,1788334,1788337,1788929,1789947,1789998,1790045,1790200,1790296,1790302-1790304,1790330-1790331,1790436,1790439,1790444,1790446,1790488,1790521,1790523,1790569,1790632,1791598,1791718,1791728,1792621-1792622,1792625,1792961,1792963,1797415,1798105,1805380,1808039,1808836,1809649,1810452,1813286,1816527
>  /apr/apr/trunk/test/testnames.c:1460405
>  /httpd/httpd/trunk:1604590
>
> Modified: apr/apr/branches/1.7.x/CHANGES
> URL:
> http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/CHANGES?rev=1816608&r1=1816607&r2=1816608&view=diff
>
> ==============================================================================
> --- apr/apr/branches/1.7.x/CHANGES [utf-8] (original)
> +++ apr/apr/branches/1.7.x/CHANGES [utf-8] Wed Nov 29 08:53:28 2017
> @@ -1,6 +1,15 @@
>                                                       -*- coding: utf-8 -*-
>  Changes for APR 1.7.0
>
> +  *) Add apr_sockaddr_zone_set, apr_sockaddr_zone_set to set and retrieve
> +     the zone for link-local IPv6 addresses.  [Joe Orton]
> +
> +  *) apr_sockaddr_equal: Compare link-local IPv6 addresses with different
> +     zones as not equal.  [Joe Orton]
> +
> +  *) apr_sockaddr_ip_getbuf, apr_sockaddr_ip_get: Append "%zone" for
> +     IPv6 link-local addresses.  [Joe Orton]
> +
>    *) Locks: add a --disable-timedlocks config option in case users
>       encounter more platforms where it fails [Nick Kew].
>
>
> Modified: apr/apr/branches/1.7.x/configure.in
> URL:
> http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/configure.in?rev=1816608&r1=1816607&r2=1816608&view=diff
>
> ==============================================================================
> --- apr/apr/branches/1.7.x/configure.in (original)
> +++ apr/apr/branches/1.7.x/configure.in Wed Nov 29 08:53:28 2017
> @@ -1162,7 +1162,9 @@ case $host in
>  #endif";;
>  esac
>
> -AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h sys/shm.h
> sys/file.h kernel/OS.h os2.h windows.h])
> +AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h \
> +                  sys/shm.h sys/file.h kernel/OS.h os2.h windows.h \
> +                  net/if.h])
>  AC_CHECK_FUNCS([mmap munmap shm_open shm_unlink shmget shmat shmdt shmctl
> \
>                  create_area mprotect])
>
> @@ -2756,7 +2758,7 @@ esac
>  AC_SEARCH_LIBS(getaddrinfo, socket inet6)
>  AC_SEARCH_LIBS(gai_strerror, socket inet6)
>  AC_SEARCH_LIBS(getnameinfo, socket inet6)
> -AC_CHECK_FUNCS(gai_strerror)
> +AC_CHECK_FUNCS(gai_strerror if_nametoindex if_indextoname)
>  APR_CHECK_WORKING_GETADDRINFO
>  APR_CHECK_NEGATIVE_EAI
>  APR_CHECK_WORKING_GETNAMEINFO
>
> Modified: apr/apr/branches/1.7.x/include/apr_network_io.h
> URL:
> http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/include/apr_network_io.h?rev=1816608&r1=1816607&r2=1816608&view=diff
>
> ==============================================================================
> --- apr/apr/branches/1.7.x/include/apr_network_io.h (original)
> +++ apr/apr/branches/1.7.x/include/apr_network_io.h Wed Nov 29 08:53:28
> 2017
> @@ -441,6 +441,29 @@ APR_DECLARE(apr_status_t) apr_sockaddr_i
>                                                   const apr_sockaddr_t
> *src,
>                                                   apr_pool_t *p);
>
> +/* Set the zone of an IPv6 link-local address object.
> + * @param sa Socket address object
> + * @param zone_id Zone ID (textual "eth0" or numeric "3").
> + */
> +APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
> +                                                const char *zone_id);
> +
> +
> +/* Retrieve the zone of an IPv6 link-local address object.
> + * @param sa Socket address object
> + * @param name If non-NULL, set to the textual representation of the zone
> id
> + * @param id If non-NULL, set to the integer zone id
> + * @param p Pool from which *name is allocated if used.
> + * @return Returns APR_EBADIP for non-IPv6 socket or socket without any
> zone id
> + * set, or other error if the interface could not be mapped to a name.
> + * @remark Both name and id may be NULL, neither are modified if
> + * non-NULL in error cases.
> + */
> +APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
> +                                                const char **name,
> +                                                apr_uint32_t *id,
> +                                                apr_pool_t *p);
>
> +
>  /**
>   * Look up the host name from an apr_sockaddr_t.
>   * @param hostname The hostname.
>
> Modified: apr/apr/branches/1.7.x/include/arch/win32/apr_private.h
> URL:
> http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/include/arch/win32/apr_private.h?rev=1816608&r1=1816607&r2=1816608&view=diff
>
> ==============================================================================
> --- apr/apr/branches/1.7.x/include/arch/win32/apr_private.h (original)
> +++ apr/apr/branches/1.7.x/include/arch/win32/apr_private.h Wed Nov 29
> 08:53:28 2017
> @@ -140,6 +140,8 @@ APR_DECLARE_DATA int errno;
>  #if APR_HAVE_IPV6
>  #define HAVE_GETADDRINFO 1
>  #define HAVE_GETNAMEINFO 1
> +#define HAVE_IF_INDEXTONAME 1
> +#define HAVE_IF_NAMETOINDEX 1
>  #endif
>
>  /* MSVC 7.0 introduced _strtoi64 */
>
> Modified: apr/apr/branches/1.7.x/network_io/unix/sockaddr.c
> URL:
> http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/network_io/unix/sockaddr.c?rev=1816608&r1=1816607&r2=1816608&view=diff
>
> ==============================================================================
> --- apr/apr/branches/1.7.x/network_io/unix/sockaddr.c (original)
> +++ apr/apr/branches/1.7.x/network_io/unix/sockaddr.c Wed Nov 29 08:53:28
> 2017
> @@ -25,6 +25,10 @@
>  #include <stdlib.h>
>  #endif
>
> +#ifdef HAVE_NET_IF_H
> +#include <net/if.h>
> +#endif
> +
>  #define APR_WANT_STRFUNC
>  #include "apr_want.h"
>
> @@ -125,9 +129,31 @@ APR_DECLARE(apr_status_t) apr_sockaddr_i
>          memmove(buf, buf + strlen("::ffff:"),
>                  strlen(buf + strlen("::ffff:"))+1);
>      }
> -#endif
> +
>      /* ensure NUL termination if the buffer is too short */
>      buf[buflen-1] = '\0';
> +
> +#ifdef HAVE_IF_INDEXTONAME
> +    /* Append scope name for link-local addresses. */
> +    if (sockaddr->family == AF_INET6
> +        && IN6_IS_ADDR_LINKLOCAL((struct in6_addr
> *)sockaddr->ipaddr_ptr)) {
> +        char scbuf[IF_NAMESIZE], *p = buf + strlen(buf);
> +
> +        if (if_indextoname(sockaddr->sa.sin6.sin6_scope_id, scbuf) ==
> scbuf) {
> +            /* Space check, need room for buf + '%' + scope + '\0'.
> +             * Assert: buflen >= strlen(buf) + strlen(scbuf) + 2
> +             * Equiv:  buflen >= (p-buf) + strlen(buf) + 2
> +             * Thus, fail in inverse condition: */
> +            if (buflen < strlen(scbuf) + (p - buf) + 2) {
> +                return APR_ENOSPC;
> +            }
> +            *p++ = '%';
> +            memcpy(p, scbuf, strlen(scbuf) + 1);
> +        }
> +    }
> +#endif /* HAVE_IF_INDEXTONAME */
> +#endif /* APR_HAVE_IPV6 */
> +
>      return APR_SUCCESS;
>  }
>
> @@ -900,11 +926,19 @@ APR_DECLARE(apr_status_t) apr_getservbyn
>           &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12],  \
>           (a)->ipaddr_len))
>
> +#if APR_HAVE_IPV6
> +#define SCOPE_OR_ZERO(sa_) ((sa_)->family != AF_INET6 ? 0 :   \
> +                            ((sa_)->sa.sin6.sin6_scope_id))
> +#else
> +#define SCOPE_OR_ZERO(sa_) (0)
> +#endif
> +
>  APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
>                                      const apr_sockaddr_t *addr2)
>  {
> -    if (addr1->ipaddr_len == addr2->ipaddr_len &&
> -        !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len))
> {
> +    if (addr1->ipaddr_len == addr2->ipaddr_len
> +        && !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr,
> addr1->ipaddr_len)
> +        && SCOPE_OR_ZERO(addr1) == SCOPE_OR_ZERO(addr2)) {
>          return 1;
>      }
>  #if APR_HAVE_IPV6
> @@ -1183,3 +1217,63 @@ APR_DECLARE(int) apr_ipsubnet_test(apr_i
>  #endif /* APR_HAVE_IPV6 */
>      return 0; /* no match */
>  }
> +
> +APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
> +                                                const char *zone_id)
> +{
> +#if !APR_HAVE_IPV6 || !defined(HAVE_IF_NAMETOINDEX)
> +    return APR_ENOTIMPL;
> +#else
> +    unsigned int idx;
> +
> +    if (sa->family != APR_INET6) {
> +        return APR_EBADIP;
> +    }
> +
> +    idx = if_nametoindex(zone_id);
> +    if (idx) {
> +        sa->sa.sin6.sin6_scope_id = idx;
> +        return APR_SUCCESS;
> +    }
> +
> +    if (errno != ENODEV) {
> +        return errno;
> +    }
> +    else {
> +        char *endptr;
> +        apr_int64_t i = apr_strtoi64(zone_id, &endptr, 10);
> +
> +        if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) {
> +            return APR_EGENERAL;
> +        }
> +
> +        sa->sa.sin6.sin6_scope_id = i;
> +        return APR_SUCCESS;
> +    }
> +#endif
> +}
> +
> +APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
> +                                                const char **name,
> +                                                apr_uint32_t *id,
> +                                                apr_pool_t *p)
> +{
> +#if !APR_HAVE_IPV6 || !defined(HAVE_IF_INDEXTONAME)
> +    return APR_ENOTIMPL;
> +#else
> +    if (sa->family != APR_INET6 || !sa->sa.sin6.sin6_scope_id) {
> +        return APR_EBADIP;
> +    }
> +
> +    if (name) {
> +        char *buf = apr_palloc(p, IF_NAMESIZE);
> +        if (if_indextoname(sa->sa.sin6.sin6_scope_id, buf) == NULL)
> +            return errno;
> +        *name = buf;
> +    }
> +
> +    if (id) *id = sa->sa.sin6.sin6_scope_id;
> +
> +    return APR_SUCCESS;
> +#endif
> +}
>
> Modified: apr/apr/branches/1.7.x/test/testsock.c
> URL:
> http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/test/testsock.c?rev=1816608&r1=1816607&r2=1816608&view=diff
>
> ==============================================================================
> --- apr/apr/branches/1.7.x/test/testsock.c (original)
> +++ apr/apr/branches/1.7.x/test/testsock.c Wed Nov 29 08:53:28 2017
> @@ -577,6 +577,98 @@ static void test_freebind(abts_case *tc,
>  #endif
>  }
>
> +#define TEST_ZONE_ADDR "fe80::1"
> +
> +#ifdef __linux__
> +/* Reasonable bet that "lo" will exist. */
> +#define TEST_ZONE_NAME "lo"
> +/* ... fill in other platforms here */
> +#endif
> +
> +#ifdef TEST_ZONE_NAME
> +#define TEST_ZONE_FULLADDR TEST_ZONE_ADDR "%" TEST_ZONE_NAME
> +#endif
> +
> +static void test_zone(abts_case *tc, void *data)
> +{
> +#if APR_HAVE_IPV6
> +    apr_sockaddr_t *sa;
> +    apr_status_t rv;
> +    const char *name = NULL;
> +    apr_uint32_t id = 0;
> +
> +    /* RFC 5737 address */
> +    rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_INET, 8080, 0, p);
> +    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
> +
> +    /* Fail for an IPv4 address! */
> +    ABTS_INT_EQUAL(tc, APR_EBADIP,
> +                   apr_sockaddr_zone_set(sa, "1"));
> +    ABTS_INT_EQUAL(tc, APR_EBADIP,
> +                   apr_sockaddr_zone_get(sa, &name, &id, p));
> +
> +    rv = apr_sockaddr_info_get(&sa, TEST_ZONE_ADDR, APR_INET6, 8080, 0,
> p);
> +    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
> +
> +    rv = apr_sockaddr_info_get(&sa, TEST_ZONE_ADDR, APR_INET6, 8080, 0,
> p);
> +    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
> +
> +    ABTS_INT_EQUAL(tc, APR_EBADIP, apr_sockaddr_zone_get(sa, &name, &id,
> p));
> +
> +#ifdef TEST_ZONE_NAME
> +    {
> +        apr_sockaddr_t *sa2;
> +        char buf[50];
> +
> +        APR_ASSERT_SUCCESS(tc, "Set zone to " TEST_ZONE_NAME,
> +                           apr_sockaddr_zone_set(sa, TEST_ZONE_NAME));
> +
> +        APR_ASSERT_SUCCESS(tc, "Get zone",
> +                           apr_sockaddr_zone_get(sa, NULL, NULL, p));
> +
> +        APR_ASSERT_SUCCESS(tc, "Get zone",
> +                           apr_sockaddr_zone_get(sa, &name, &id, p));
> +        ABTS_STR_EQUAL(tc, TEST_ZONE_NAME, name);
> +        ABTS_INT_NEQUAL(tc, 0, id); /* Only guarantee is that it should
> be non-zero */
> +
> +        /* Check string translation. */
> +        APR_ASSERT_SUCCESS(tc, "get IP address",
> +                           apr_sockaddr_ip_getbuf(buf, 50, sa));
> +        ABTS_STR_EQUAL(tc, TEST_ZONE_FULLADDR, buf);
> +
> +        memset(buf, 'A', sizeof buf);
> +        ABTS_INT_EQUAL(tc, APR_ENOSPC, apr_sockaddr_ip_getbuf(buf,
> strlen(TEST_ZONE_ADDR), sa));
> +        ABTS_INT_EQUAL(tc, APR_ENOSPC, apr_sockaddr_ip_getbuf(buf,
> strlen(TEST_ZONE_FULLADDR), sa));
> +
> +        APR_ASSERT_SUCCESS(tc, "get IP address",
> +                           apr_sockaddr_ip_getbuf(buf,
> strlen(TEST_ZONE_FULLADDR) + 1, sa));
> +        /* Check for overflow. */
> +        ABTS_INT_EQUAL(tc, 'A', buf[strlen(buf) + 1]);
> +
> +        rv = apr_sockaddr_info_copy(&sa2, sa, p);
> +        APR_ASSERT_SUCCESS(tc, "Problem copying sockaddr", rv);
> +
> +        /* Copy copied zone matches */
> +        APR_ASSERT_SUCCESS(tc, "Get zone",
> +                           apr_sockaddr_zone_get(sa2, &name, &id, p));
> +        ABTS_STR_EQUAL(tc, TEST_ZONE_NAME, name);
> +        ABTS_INT_NEQUAL(tc, 0, id); /* Only guarantee is that it should
> be non-zero */
> +
> +        /* Should match self and copy */
> +        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa, sa));
> +        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa2, sa2));
> +        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa2, sa));
> +
> +        /* Should not match against copy without zone set. */
> +        rv = apr_sockaddr_info_get(&sa2, TEST_ZONE_ADDR, APR_INET6, 8080,
> 0, p);
> +        APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
> +
> +        ABTS_INT_EQUAL(tc, 0, apr_sockaddr_equal(sa2, sa));
> +    }
> +#endif /* TEST_ZONE_NAME */
> +#endif /* APR_HAVE_IPV6 */
> +}
> +
>  abts_suite *testsock(abts_suite *suite)
>  {
>      suite = ADD_SUITE(suite)
> @@ -593,6 +685,7 @@ abts_suite *testsock(abts_suite *suite)
>      abts_run_test(suite, test_get_addr, NULL);
>      abts_run_test(suite, test_nonblock_inheritance, NULL);
>      abts_run_test(suite, test_freebind, NULL);
> +    abts_run_test(suite, test_zone, NULL);
>
>  #if APR_HAVE_SOCKADDR_UN
>      socket_name = UNIX_SOCKET_NAME;
>
>
>