Commit 1b47d1cf authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[trac999] added Client implementation and test files.

parent d8652650
// 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()));
}
// 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:
// 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));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment