Parcourir la source

[trac999] added Client implementation and test files.

JINMEI Tatuya il y a 14 ans
Parent
commit
1b47d1cf3e

+ 60 - 0
src/lib/server_common/client.cc

@@ -0,0 +1,60 @@
+// 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 <acl/ip_check.h>
+
+#include <asiolink/io_endpoint.h>
+#include <asiolink/io_message.h>
+
+#include <server_common/client.h>
+
+using namespace isc::acl;
+using namespace isc::server_common;
+using namespace isc::asiolink;
+
+struct Client::ClientImpl {
+    ClientImpl(const IOMessage& request_message) :
+        request_(request_message),
+        request_src_(request_.getRemoteEndpoint().getSockAddr())
+    {}
+
+    const IOMessage& request_;
+    const IPAddress request_src_;
+};
+
+Client::Client(const IOMessage& request_message) :
+    impl_(new ClientImpl(request_message))
+{}
+
+Client::~Client() {
+    delete impl_;
+}
+
+const IOEndpoint&
+Client::getRequestSourceEndpoint() const {
+    return (impl_->request_.getRemoteEndpoint());
+}
+
+const IPAddress&
+Client::getRequestSourceIPAddress() const {
+    return (impl_->request_src_);
+}
+
+template <>
+bool
+IPCheck<Client>::matches(const Client& client) const {
+    const IPAddress& request_src(client.getRequestSourceIPAddress());
+    return (family_ == request_src.getFamily() &&
+            compare(request_src.getData()));
+}

+ 59 - 0
src/lib/server_common/client.h

@@ -0,0 +1,59 @@
+// 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.
+
+#ifndef __CLIENT_H
+#define __CLIENT_H 1
+
+#include <boost/noncopyable.hpp>
+
+#include <asiolink/io_message.h>
+
+namespace isc {
+namespace acl {
+struct IPAddress;
+}
+
+namespace server_common {
+
+/// May have to be named something like "DNSClient"
+/// should be reusable
+/// may want to use different subclasses for auth clients and resolver clients
+class Client : boost::noncopyable {
+public:
+    explicit Client(const isc::asiolink::IOMessage& request_message);
+    ~Client();
+    const isc::asiolink::IOEndpoint& getRemoteEndpoint() const;
+    const isc::asiolink::IOEndpoint& getRequestSourceEndpoint() const;
+
+    // convenience shortcut
+    const isc::acl::IPAddress& getRequestSourceIPAddress() const;
+
+private:
+    struct ClientImpl;
+    ClientImpl* impl_;
+};
+}
+
+namespace acl {
+template <>
+bool IPCheck<server_common::Client>::matches(
+    const server_common::Client& client) const;
+}
+}
+
+#endif  // __CLIENT_H
+
+// Local Variables:
+// mode: c++
+// End:

+ 121 - 0
src/lib/server_common/tests/client_unittest.cc

@@ -0,0 +1,121 @@
+// 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 <string.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <acl/ip_check.h>
+
+#include <asiolink/io_address.h>
+#include <asiolink/io_socket.h>
+#include <asiolink/io_message.h>
+
+#include <server_common/client.h>
+
+#include <gtest/gtest.h>
+
+using namespace boost; 
+using namespace isc::acl; 
+using namespace isc::asiolink; 
+using namespace isc::server_common; 
+
+namespace {
+
+// copied from auth_srv_unittest.cc.  should share it.
+class DummyUnknownSocket : public IOSocket {
+public:
+    DummyUnknownSocket() {}
+    virtual int getNative() const { return (0); }
+    virtual int getProtocol() const { return (IPPROTO_IP); }
+};
+
+class ClientTest : public ::testing::Test {
+protected:
+    ClientTest() {
+        endpoint4.reset(IOEndpoint::create(IPPROTO_UDP, IOAddress("192.0.2.1"),
+                                           53214));
+        endpoint6.reset(IOEndpoint::create(IPPROTO_TCP,
+                                           IOAddress("2001:db8::1"), 53216));
+        request4.reset(new IOMessage(NULL, 0, IOSocket::getDummyUDPSocket(),
+                                     *endpoint4));
+        request6.reset(new IOMessage(NULL, 0, IOSocket::getDummyTCPSocket(),
+                                     *endpoint6));
+        client4.reset(new Client(*request4));
+        client6.reset(new Client(*request6));
+        
+    }
+    scoped_ptr<const IOEndpoint> endpoint4;
+    scoped_ptr<const IOEndpoint> endpoint6;
+    scoped_ptr<const IOMessage> request4;
+    scoped_ptr<const IOMessage> request6;
+    scoped_ptr<const Client> client4;
+    scoped_ptr<const Client> client6;
+};
+
+TEST_F(ClientTest, constructIPv4) {
+    EXPECT_EQ(AF_INET, client4->getRequestSourceEndpoint().getFamily());
+    EXPECT_EQ(IPPROTO_UDP, client4->getRequestSourceEndpoint().getProtocol());
+    EXPECT_EQ("192.0.2.1",
+              client4->getRequestSourceEndpoint().getAddress().toText());
+    EXPECT_EQ(53214, client4->getRequestSourceEndpoint().getPort());
+
+    const uint8_t expected_data[] = { 192, 0, 2, 1 };
+    EXPECT_EQ(AF_INET, client4->getRequestSourceIPAddress().getFamily());
+    ASSERT_EQ(4, client4->getRequestSourceIPAddress().getLength());
+    EXPECT_EQ(0, memcmp(expected_data,
+                        client4->getRequestSourceIPAddress().getData(), 4));
+}
+
+TEST_F(ClientTest, constructIPv6) {
+    EXPECT_EQ(AF_INET6, client6->getRequestSourceEndpoint().getFamily());
+    EXPECT_EQ(IPPROTO_TCP, client6->getRequestSourceEndpoint().getProtocol());
+    EXPECT_EQ("2001:db8::1",
+              client6->getRequestSourceEndpoint().getAddress().toText());
+    EXPECT_EQ(53216, client6->getRequestSourceEndpoint().getPort());
+
+    const uint8_t expected_data[] = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00,
+                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                      0x00, 0x01 };
+    EXPECT_EQ(AF_INET6, client6->getRequestSourceIPAddress().getFamily());
+    ASSERT_EQ(16, client6->getRequestSourceIPAddress().getLength());
+    EXPECT_EQ(0, memcmp(expected_data,
+                        client6->getRequestSourceIPAddress().getData(), 16));
+}
+
+TEST_F(ClientTest, ACLCheckIPv4) {
+    // Exact match
+    EXPECT_TRUE(IPCheck<Client>("192.0.2.1").matches(*client4));
+    // Exact match (negative)
+    EXPECT_FALSE(IPCheck<Client>("192.0.2.53").matches(*client4));
+    // Prefix match
+    EXPECT_TRUE(IPCheck<Client>("192.0.2.0/24").matches(*client4));
+    // Prefix match (negative)
+    EXPECT_FALSE(IPCheck<Client>("192.0.1.0/24").matches(*client4));
+    // Address family mismatch (the first 4 bytes of the IPv6 address has the
+    // same binary representation as the client's IPv4 address, which
+    // shouldn't confuse the match logic)
+    EXPECT_FALSE(IPCheck<Client>("c000:0201::").matches(*client4));
+}
+
+TEST_F(ClientTest, ACLCheckIPv6) {
+    // The following are a set of tests of the same concept as ACLCheckIPv4
+    EXPECT_TRUE(IPCheck<Client>("2001:db8::1").matches(*client6));
+    EXPECT_FALSE(IPCheck<Client>("2001:db8::53").matches(*client6));
+    EXPECT_TRUE(IPCheck<Client>("2001:db8::/64").matches(*client6));
+    EXPECT_FALSE(IPCheck<Client>("2001:db8:1::/64").matches(*client6));
+    EXPECT_FALSE(IPCheck<Client>("32.1.13.184").matches(*client6));
+}
+}