Parcourir la source

[trac999] introduced a supplemental IPAddress structure

JINMEI Tatuya il y a 14 ans
Parent
commit
112aa5ce69

+ 11 - 4
src/lib/acl/Makefile.am

@@ -1,6 +1,13 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
-EXTRA_DIST = check.h acl.h ip_check.h
+AM_CPPFLAGS = -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CXXFLAGS = $(B10_CXXFLAGS)
 
-# TODO: Once we have some cc file we are able to compile, create the library.
-# For now, we have only header files, not creating empty library.
+CLEANFILES = *.gcno *.gcda
+
+EXTRA_DIST = check.h acl.h
+
+lib_LTLIBRARIES = libacl.la
+
+libacl_la_SOURCES = ip_check.h ip_check.cc

+ 54 - 0
src/lib/acl/ip_check.cc

@@ -0,0 +1,54 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <sys/socket.h>
+
+#include <exceptions/exceptions.h>
+
+#include <acl/ip_check.h>
+
+using namespace isc;
+
+namespace isc {
+namespace acl {
+
+namespace {
+const uint8_t*
+getSockAddrData(const struct sockaddr& sa) {
+    const void* sa_ptr = &sa;
+    const void* data_ptr;
+    if (sa.sa_family == AF_INET) {
+        const struct sockaddr_in* sin =
+            static_cast<const struct sockaddr_in*>(sa_ptr);
+        data_ptr = &sin->sin_addr;
+    } else if (sa.sa_family == AF_INET6) {
+        const struct sockaddr_in6* sin6 =
+            static_cast<const struct sockaddr_in6*>(sa_ptr);
+        data_ptr = &sin6->sin6_addr;
+    } else {
+        isc_throw(BadValue, "Unsupported address family for IPAddress: " <<
+                  static_cast<int>(sa.sa_family));
+    }
+    return (static_cast<const uint8_t*>(data_ptr));
+}
+}
+
+IPAddress::IPAddress(const struct sockaddr& sa) :
+    family(sa.sa_family),
+    data(getSockAddrData(sa)),
+    length(family == AF_INET ?
+           sizeof(struct in_addr) : sizeof(struct in6_addr))
+{}
+} // namespace acl
+} // namespace isc

+ 15 - 2
src/lib/acl/ip_check.h

@@ -15,6 +15,8 @@
 #ifndef __IP_CHECK_H
 #define __IP_CHECK_H
 
+#include <sys/socket.h>
+
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -157,7 +159,14 @@ splitIpAddress(const std::string& addrmask, size_t maxmask) {
     return (std::make_pair(components[0], masksize));
 }
 
-
+/// \brief A simple representation of IP address
+///
+struct IPAddress {
+    explicit IPAddress(const struct sockaddr& sa);
+    const int family;
+    const uint8_t* const data;
+    const size_t length;
+};
 
 /// \brief IPV4 Check
 ///
@@ -264,7 +273,7 @@ public:
     }
 
     /// \return Network mask applied to match
-    const uint32_t getNetmask() const {
+    uint32_t getNetmask() const {
         return (netmask_);
     }
 
@@ -671,3 +680,7 @@ private:
 } // namespace isc
 
 #endif // __IP_CHECK_H
+
+// Local Variables:
+// mode: c++
+// End:

+ 54 - 0
src/lib/acl/tests/ip_check_unittest.cc

@@ -12,6 +12,10 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
 
 #include <gtest/gtest.h>
 #include <acl/ip_check.h>
@@ -69,6 +73,7 @@ bool Ipv6Check<GeneralAddress>::matches(const GeneralAddress& addr) const {
 } // namespace acl
 } // namespace isc
 
+namespace {
 /// *** Free Function Tests ***
 
 // Test the createNetmask() function.
@@ -118,6 +123,54 @@ TEST(IpFunctionCheck, SplitIpAddress) {
     EXPECT_THROW(splitIpAddress("2001:db8::/32/s", 32), isc::InvalidParameter);
 }
 
+const struct sockaddr&
+getSockAddr(const char* const addr) {
+    struct addrinfo hints, *res;
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_NUMERICHOST;
+
+    if (getaddrinfo(addr, NULL, &hints, &res) == 0) {
+        static struct sockaddr_storage ss;
+        void* ss_ptr = &ss;
+        memcpy(ss_ptr, res->ai_addr, res->ai_addrlen);
+        freeaddrinfo(res);
+        return (*static_cast<struct sockaddr*>(ss_ptr));
+    }
+
+    // We don't expect getaddrinfo to fail for our tests.  But if that
+    // ever happens we return a dummy value that would make subsequent test
+    // fail.
+    static struct sockaddr sa_dummy;
+    sa_dummy.sa_family = AF_UNSPEC;
+    return (sa_dummy);
+}
+
+TEST(IPAddress, constructIPv4) {
+    IPAddress ipaddr(getSockAddr("192.0.2.1"));
+    const char expected_data[4] = { 192, 0, 2, 1 };
+    EXPECT_EQ(AF_INET, ipaddr.family);
+    EXPECT_EQ(4, ipaddr.length);
+    EXPECT_EQ(0, memcmp(expected_data, ipaddr.data, 4));
+}
+
+TEST(IPAddress, constructIPv6) {
+    IPAddress ipaddr(getSockAddr("2001:db8:1234:abcd::53"));
+    const char expected_data[16] = { 0x20, 0x01, 0x0d, 0xb8, 0x12, 0x34, 0xab,
+                                     0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                     0x00, 0x53 };
+    EXPECT_EQ(AF_INET6, ipaddr.family);
+    EXPECT_EQ(16, ipaddr.length);
+    EXPECT_EQ(0, memcmp(expected_data, ipaddr.data, 16));
+}
+
+TEST(IPAddress, badConstruct) {
+    struct sockaddr sa;
+    sa.sa_family = AF_UNSPEC;
+    EXPECT_THROW(IPAddress ipaddr(sa), isc::BadValue);
+}
+
 // *** IPV4 Tests ***
 // Check that a default constructor can be instantiated.
 
@@ -572,3 +625,4 @@ TEST(IpCheck, V6Copying) {
     acl2 = acl;
     EXPECT_TRUE(acl2.matches(test));
 }
+}