summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrawick <trawick@13f79535-47bb-0310-9956-ffa450edef68>2013-11-12 13:48:16 +0000
committertrawick <trawick@13f79535-47bb-0310-9956-ffa450edef68>2013-11-12 13:48:16 +0000
commit657dd839a69993a02ca672fe4f6d1513afcb5f84 (patch)
tree6acda1edd1523b6c65baf99fdb5a210797f3ad9f
parentda01992d919dba5b641678869e9b4c777cd77d26 (diff)
downloadlibapr-657dd839a69993a02ca672fe4f6d1513afcb5f84.tar.gz
add apr_sockaddr_is_wildcard() API
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@1541061 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--include/apr_network_io.h10
-rw-r--r--network_io/unix/sockaddr.c29
-rw-r--r--test/testsock.c11
3 files changed, 50 insertions, 0 deletions
diff --git a/include/apr_network_io.h b/include/apr_network_io.h
index d7ffaf509..8eaed2607 100644
--- a/include/apr_network_io.h
+++ b/include/apr_network_io.h
@@ -760,6 +760,16 @@ APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
const apr_sockaddr_t *addr2);
/**
+ * See if the IP address in an APR socket address refers to the wildcard
+ * address for the protocol family (e.g., INADDR_ANY for IPv4).
+ *
+ * @param addr The APR socket address to examine.
+ * @remark The return value will be non-zero if the address is
+ * initialized and is the wildcard address.
+ */
+APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr);
+
+/**
* Return the type of the socket.
* @param sock The socket to query.
* @param type The returned type (e.g., SOCK_STREAM).
diff --git a/network_io/unix/sockaddr.c b/network_io/unix/sockaddr.c
index 1ccc3f571..080c7a298 100644
--- a/network_io/unix/sockaddr.c
+++ b/network_io/unix/sockaddr.c
@@ -879,6 +879,35 @@ APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
return 0; /* not equal */
}
+APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr)
+{
+ static const char inaddr_any[
+#if APR_HAVE_IPV6
+ sizeof(struct in6_addr)
+#else
+ sizeof(struct in_addr)
+#endif
+ ] = {0};
+
+ if (addr->ipaddr_ptr /* IP address initialized */
+ && addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */
+ if (!memcmp(inaddr_any, addr->ipaddr_ptr, addr->ipaddr_len)) {
+ return 1;
+ }
+#if APR_HAVE_IPV6
+ if (addr->family == AF_INET6
+ && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)) {
+ struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3];
+
+ if (!memcmp(inaddr_any, v4, sizeof *v4)) {
+ return 1;
+ }
+ }
+#endif
+ }
+ return 0;
+}
+
static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network)
{
/* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
diff --git a/test/testsock.c b/test/testsock.c
index 41b2774f7..b2ef80dd1 100644
--- a/test/testsock.c
+++ b/test/testsock.c
@@ -73,14 +73,21 @@ static void test_addr_info(abts_case *tc, void *data)
{
apr_status_t rv;
apr_sockaddr_t *sa;
+ int rc;
rv = apr_sockaddr_info_get(&sa, NULL, APR_UNSPEC, 80, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+ rc = apr_sockaddr_is_wildcard(sa);
+ ABTS_INT_NEQUAL(tc, 0, rc);
+
rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 80, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname);
+ rc = apr_sockaddr_is_wildcard(sa);
+ ABTS_INT_EQUAL(tc, 0, rc);
+
rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 0, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname);
@@ -324,6 +331,10 @@ static void test_print_addr(abts_case *tc, void *data)
if (rv == APR_SUCCESS && sa) {
/* sa should now be a v4-mapped IPv6 address. */
char buf[128];
+ int rc;
+
+ rc = apr_sockaddr_is_wildcard(sa);
+ ABTS_INT_NEQUAL(tc, 0, rc);
memset(buf, 'z', sizeof buf);