BIND 10 master, updated. 877e89713ad2398b6637b843a22c3b12607fe5bb Merge branch 'trac998'
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Jun 24 15:00:08 UTC 2011
The branch, master has been updated
via 877e89713ad2398b6637b843a22c3b12607fe5bb (commit)
via 33e08ca107c127d5c158882e7f2e86770a48c572 (commit)
via 04e7fe3f480462d288c17bd121a368b74292cfd3 (commit)
via ea15d26afc9ced4a11aea6733ea3df0969c5618b (commit)
via f685e5c06c382180eb1775bce714ea60154b08f2 (commit)
via 5a19ee14367d9bb796c8e43c034ee9f327052c86 (commit)
via f92d30bb55decf9ed4d7cdf10231dfe2913ca11a (commit)
via 461a9d0a1e896e0a1b676c6873f74404d5ab95c1 (commit)
via bc81810505f7263aedb8654d139510058c251626 (commit)
via b57c51e6ddfc6770d5c66eab5aeb1a5238e5a7ea (commit)
via ddb1b2241fc03a1d08dea42907ee8f859d3b2f46 (commit)
via 0b838ba0d3c60203a52d1a918333846116e607cb (commit)
via f77021d7838e33e1662b42776ccc49be4435b1f2 (commit)
via 632cd6151b871e060d09a79f6b8a283cc0ab469c (commit)
via 81a2df84a879ca5cbaaa61dffce5c413d920011d (commit)
via 59b380d3682bb9fca26cae2c70c6c49934823f01 (commit)
via 8b2247a6ae88fbf16bfd65852feb0216a4ea4dac (commit)
via 1b01a9d09e5ecf21ff8bd9cce1c20372846a775c (commit)
via 735f817c7f66813135b4ef576c117aa424a5bdad (commit)
via 79ec6c320ec5c24036856fd6b589ba8bf8b26ffc (commit)
via 8f5fafa643f2d908b9e97b6d08aeb55c4b96addf (commit)
via 01f9c1c0adfb37d11133c87056161f1edfba2672 (commit)
via ac7aaa887d827f8bdf1c2881d245cc655c6847b7 (commit)
via ebb6493b8ff763d42fe99438c8befe48c381b4aa (commit)
via c786a61641a965545c2e304b1c946afdedc6dc1a (commit)
via e5251c4886f626e6ef9f6ba82771c0e949e0071f (commit)
via 792c8b202cffc8fed726f10b3514523b1fc92469 (commit)
via 8c624c6644563ed9c4fecec8b0b5f5dd115fe7ef (commit)
via d1c7f98e910bd19d21a649386f1a8066e4f41677 (commit)
via a90c8a06056300e0f9f5ffdae72b8a2ba26346fc (commit)
via 30570ab2d917dc6adec02ba272ee50c17124b688 (commit)
via 59908b70a929baf829202197d6e7ab5a3557da32 (commit)
via 585d1c63d6d0126607f424571e38a4a60683cf4b (commit)
via d335ae50bb855b7b302dab852005385c0227dcfb (commit)
via 8034dbfe87c45eaa2c0aef0e715b86fa79a7c4e3 (commit)
via 0ddf0f5fa4d9d18599a1642b9f87caaa1f463c5e (commit)
via 5a75094dfdd5f2307c4a1669e05db70355b08682 (commit)
via df5bad72ac8dac07a038f29823a1938bc9bbe72c (commit)
via 6c5a9b252b7bc062ed807aff342d0314811b5bde (commit)
via 8320629b004d5fc8194afb5d277a0d9e01299121 (commit)
via 287edb431de6ae5d7106dd4e593a193908b9ba9f (commit)
via 99d7c21284686ba3d021a6d09938b82ea56de783 (commit)
via 309b24ff461b623770e950d6ff12654241bdd39b (commit)
via 52d165984d1a7784a1a6e0a3b845b19559698203 (commit)
via 67a88d3fd748cc42730e142cbfa79d0b7fb7a813 (commit)
via bfd50c768ccf03b2e4f3d3ecbeb5fb344ff79129 (commit)
via ae21ebb0f609f8a2aa8ffc3d4b84c465111ec2c3 (commit)
via 7cf66b7e44e389205ae4344764fbf136550854ce (commit)
via 0c3b69c6e170bee7dd775090af2bdd1cae900080 (commit)
via f5edd310465966137f0cd4e2109d90f7e5d5965f (commit)
via 73ac6b09eeeebcdb03965076d4aa8a8a7a361ebe (commit)
via 86a307f08882d02ad443e848e096a30ca14ec918 (commit)
from 32fb3ad97a7ccc65ef391b84c8f488d4ea71e963 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 877e89713ad2398b6637b843a22c3b12607fe5bb
Merge: 32fb3ad97a7ccc65ef391b84c8f488d4ea71e963 33e08ca107c127d5c158882e7f2e86770a48c572
Author: Stephen Morris <stephen at isc.org>
Date: Fri Jun 24 15:48:01 2011 +0100
Merge branch 'trac998'
-----------------------------------------------------------------------
Summary of changes:
src/lib/acl/Makefile.am | 5 +-
src/lib/acl/ip_check.cc | 111 ++++++
src/lib/acl/ip_check.h | 346 +++++++++++++++++++
src/lib/acl/tests/Makefile.am | 9 +-
src/lib/acl/tests/ip_check_unittest.cc | 588 ++++++++++++++++++++++++++++++++
src/lib/acl/tests/run_unittests.cc | 3 +-
6 files changed, 1058 insertions(+), 4 deletions(-)
create mode 100644 src/lib/acl/ip_check.cc
create mode 100644 src/lib/acl/ip_check.h
create mode 100644 src/lib/acl/tests/ip_check_unittest.cc
-----------------------------------------------------------------------
diff --git a/src/lib/acl/Makefile.am b/src/lib/acl/Makefile.am
index 890851e..a5ce86f 100644
--- a/src/lib/acl/Makefile.am
+++ b/src/lib/acl/Makefile.am
@@ -7,11 +7,14 @@ AM_CXXFLAGS = $(B10_CXXFLAGS)
# The core library
lib_LTLIBRARIES = libacl.la
-libacl_la_SOURCES = check.h acl.h
+libacl_la_SOURCES = acl.h
+libacl_la_SOURCES += check.h
+libacl_la_SOURCES += ip_check.h ip_check.cc
libacl_la_SOURCES += loader.h loader.cc
libacl_la_LIBADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
libacl_la_LIBADD += $(top_builddir)/src/lib/cc/libcc.la
+libacl_la_LIBADD += $(top_builddir)/src/lib/util/libutil.la
# DNS specialized one
lib_LTLIBRARIES += libdnsacl.la
diff --git a/src/lib/acl/ip_check.cc b/src/lib/acl/ip_check.cc
new file mode 100644
index 0000000..08c8431
--- /dev/null
+++ b/src/lib/acl/ip_check.cc
@@ -0,0 +1,111 @@
+// 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 <boost/lexical_cast.hpp>
+
+#include <acl/ip_check.h>
+
+using namespace std;
+
+// Split the IP Address prefix
+
+namespace isc {
+namespace acl {
+namespace internal {
+
+uint8_t
+createMask(size_t prefixlen) {
+
+ if (prefixlen == 0) {
+ return (0);
+
+ } else if (prefixlen <= 8) {
+
+ // In the following discussion:
+ //
+ // w is the width of the data type in bits.
+ // m is the value of prefixlen, the number of most signifcant bits we
+ // want to set.
+ // ** is exponentiation (i.e. 2**n is 2 raised to the power of n).
+ //
+ // We note that the value of 2**m - 1 gives a value with the least
+ // significant m bits set. For a data type of width w, this means that
+ // the most signficant (w-m) bits are clear.
+ //
+ // Hence the value 2**(w-m) - 1 gives a result with the least signficant
+ // w-m bits set and the most significant m bits clear. The 1's
+ // complement of this value gives is the result we want.
+ //
+ // Final note: at this point in the logic, m is non-zero, so w-m < w.
+ // This means 1<<(w-m) will fit into a variable of width w bits. In
+ // other words, in the expression below, no term will cause an integer
+ // overflow.
+ return (~((1 << (8 - prefixlen)) - 1));
+ }
+
+ // Mask size is too large. (Note that prefixlen is unsigned, so can't be
+ // negative.)
+ isc_throw(isc::OutOfRange, "prefixlen argument must be between 0 and 8");
+}
+
+pair<string, int>
+splitIPAddress(const string& ipprefix) {
+
+ // Split string into its components - an address and a prefix length.
+ // We initialize by assuming that there is no slash in the string given.
+ string address = ipprefix;
+ string prefixlen = "";
+
+ const size_t slashpos = ipprefix.find('/');
+ if ((ipprefix.size() == 0) || (slashpos == 0) ||
+ (slashpos == (ipprefix.size() - 1))) {
+ // Nothing in prefix, or it starts with or ends with a slash.
+ isc_throw(isc::InvalidParameter, "address prefix of " << ipprefix <<
+ " is not valid");
+
+ } else if (slashpos != string::npos) {
+ // There is a slash somewhere in the string, split the string on it.
+ // Don't worry about multiple slashes - if there are some, they will
+ // appear in the prefixlen segment and will be detected when an attempt
+ // is made to convert it to a number.
+ address = ipprefix.substr(0, slashpos);
+ prefixlen = ipprefix.substr(slashpos + 1);
+ }
+
+ // Set the default value for the prefix length. As the type of the address
+ // is not known at the point this function is called, the maximum
+ // allowable value is also not known. The value of 0 is reserved for
+ // a "match any address" match.
+ int prefix_size = -1;
+
+ // If there is a prefixlength, attempt to convert it.
+ if (!prefixlen.empty()) {
+ try {
+ prefix_size = boost::lexical_cast<int>(prefixlen);
+ if (prefix_size < 0) {
+ isc_throw(isc::InvalidParameter, "address prefix of " <<
+ ipprefix << " is not valid");
+ }
+ } catch (boost::bad_lexical_cast&) {
+ isc_throw(isc::InvalidParameter, "prefix length of '" <<
+ prefixlen << "' is not valid");
+ }
+ }
+
+ return (make_pair(address, prefix_size));
+}
+
+} // namespace internal
+} // namespace acl
+} // namespace isc
diff --git a/src/lib/acl/ip_check.h b/src/lib/acl/ip_check.h
new file mode 100644
index 0000000..619d8ed
--- /dev/null
+++ b/src/lib/acl/ip_check.h
@@ -0,0 +1,346 @@
+// 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 __IP_CHECK_H
+#define __IP_CHECK_H
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+#include <boost/static_assert.hpp>
+
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <acl/check.h>
+#include <exceptions/exceptions.h>
+#include <util/strutil.h>
+
+namespace isc {
+namespace acl {
+
+// Free functions. These are not supposed to be used outside this module,
+// but are declared public for testing. To try to conceal them, they are
+// put in an "internal" namespace.
+
+namespace internal {
+
+/// \brief Convert prefix length to mask
+///
+/// Given a prefix length and a data type, return a value of that data type
+/// with the most significant "prefix length" bits set. For example, if the
+/// data type is an uint8_t and the prefix length is 3, the function would
+/// return a uint8_t holding the binary value 11100000. This value is used as
+/// a mask in the address checks.
+///
+/// \param prefixlen number of bits to be set in the mask. This must be
+/// between 0 and 8.
+///
+/// \return uint8_t with the most significant "prefixlen" bits set.
+///
+/// \exception OutOfRange prefixlen is too large for the data type.
+
+uint8_t createMask(size_t prefixlen);
+
+/// \brief Split IP Address Prefix
+///
+/// Splits an IP address prefix (given in the form of "xxxxxx/n" or "xxxxx" into
+/// a string representing the IP address and a number giving the length of the
+/// prefix. (In the latter case, the prefix is equal in length to the width in
+/// width in bits of the data type holding the address.) An exception will be
+/// thrown if the string format is invalid or if the prefix length is invalid.
+///
+/// N.B. This function does NOT check that the address component is a valid IP
+/// address; this is done elsewhere in the address parsing process.
+///
+/// \param ipprefix Address or address prefix. The string should be passed
+/// without leading or trailing spaces.
+///
+/// \return Pair of (string, int) holding the address string and the prefix
+/// length. The second element is -1 if no prefix was given.
+///
+/// \exception InvalidParameter Address prefix not of the expected syntax
+
+std::pair<std::string, int>
+splitIPAddress(const std::string& ipprefix);
+
+} // namespace internal
+
+
+
+/// \brief IP Check
+///
+/// This class performs a match between an IP address prefix specified in an ACL
+/// and a given IP address. The check works for both IPv4 and IPv6 addresses.
+///
+/// The class is templated on the type of a context structure passed to the
+/// matches() method, and a template specialisation for that method must be
+/// supplied for the class to be used.
+
+template <typename Context>
+class IPCheck : public Check<Context> {
+private:
+ // Size of uint8_t array needed to hold different address types
+ static const size_t IPV6_SIZE = sizeof(struct in6_addr);
+ static const size_t IPV4_SIZE = sizeof(struct in_addr);
+
+ // Confirm our assumption of relative sizes - this allows us to assume that
+ // an array sized for an IPv6 address can hold an IPv4 address.
+ BOOST_STATIC_ASSERT(IPV6_SIZE > IPV4_SIZE);
+
+public:
+ /// \brief String Constructor
+ ///
+ /// Constructs an IP Check object from an address or address prefix in the
+ /// form <ip-address>/n".
+ ///
+ /// Also allowed are the special keywords "any4" and "any6", which match
+ /// any IPv4 or IPv6 address. These must be specified in lowercase.
+ ///
+ /// \param ipprefix IP address prefix in the form "<ip-address>/n"
+ /// (where the "/n" part is optional and should be valid for the
+ /// address). If "n" is specified as zero, the match is for any
+ /// address in that address family. The address can also be
+ /// given as "any4" or "any6".
+ IPCheck(const std::string& ipprefix) : family_(0) {
+
+ // Ensure array elements are correctly initialized with zeroes.
+ std::fill(address_, address_ + IPV6_SIZE, 0);
+ std::fill(mask_, mask_ + IPV6_SIZE, 0);
+
+ // Only deal with the string after we've removed leading and trailing
+ // spaces.
+ const std::string mod_prefix = isc::util::str::trim(ipprefix);
+
+ // Check for special cases first.
+ if (mod_prefix == "any4") {
+ family_ = AF_INET;
+
+ } else if (mod_prefix == "any6") {
+ family_ = AF_INET6;
+
+ } else {
+
+ // General address prefix. Split into address part and prefix
+ // length.
+ const std::pair<std::string, int> result =
+ internal::splitIPAddress(mod_prefix);
+
+ // Try to convert the address. If successful, the result is in
+ // network-byte order (most significant components at lower
+ // addresses).
+ int status = inet_pton(AF_INET6, result.first.c_str(), address_);
+ if (status == 1) {
+ // It was an IPv6 address.
+ family_ = AF_INET6;
+ } else {
+ // IPv6 interpretation failed, try IPv4.
+ status = inet_pton(AF_INET, result.first.c_str(), address_);
+ if (status == 1) {
+ family_ = AF_INET;
+ }
+ }
+
+ // Handle errors.
+ if (status == 0) {
+ isc_throw(isc::InvalidParameter, "address prefix of " <<
+ ipprefix << " is not valid");
+ } else if (status < 0) {
+ isc_throw(isc::Unexpected, "address conversion of " <<
+ ipprefix << " failed due to a system error");
+ }
+
+ // All done, so set the mask used in the address comparison.
+ setMask(result.second);
+ }
+ }
+
+ /// \brief Destructor
+ virtual ~IPCheck() {}
+
+ /// \brief The check itself
+ ///
+ /// Matches the passed argument to the condition stored here. Different
+ /// specialisations must be provided for different argument types, and the
+ /// program will fail to compile if a required specialisation is not
+ /// provided.
+ ///
+ /// It is expected that matches() will extract the address information from
+ /// the Context structure, and use compare() to actually perform the
+ /// comparison.
+ ///
+ /// \param context Information to be matched
+ virtual bool matches(const Context& context) const;
+
+ /// \brief Estimated cost
+ ///
+ /// Assume that the cost of the match is linear and depends on the
+ /// maximum number of comparison operations.
+ ///
+ /// \return Estimated cost of the comparison
+ virtual unsigned cost() const {
+ return ((family_ == AF_INET) ? IPV4_SIZE : IPV6_SIZE);
+ }
+
+ ///@{
+ /// Access methods - mainly for testing
+
+ /// \return Stored IP address
+ std::vector<uint8_t> getAddress() const {
+ const size_t vector_len = (family_ == AF_INET ? IPV4_SIZE : IPV6_SIZE);
+ return (std::vector<uint8_t>(address_, address_ + vector_len));
+ }
+
+ /// \return Network mask applied to match
+ std::vector<uint8_t> getMask() const {
+ const size_t vector_len = (family_ == AF_INET ? IPV4_SIZE : IPV6_SIZE);
+ return (std::vector<uint8_t>(mask_, mask_ + vector_len));
+ }
+
+ /// \return Prefix length of the match
+ size_t getPrefixlen() const {
+ // Work this out by counting bits in the mask.
+ size_t count = 0;
+ for (size_t i = 0; i < IPV6_SIZE; ++i) {
+ if (mask_[i] == 0xff) {
+ // All bits set in this byte
+ count += 8;
+ continue;
+
+ } else if (mask_[i] != 0) {
+ // Only some bits set in this byte. Count them.
+ uint8_t byte = mask_[i];
+ for (int j = 0; j < 8; ++j) {
+ count += byte & 0x01; // Add one if the bit is set
+ byte >>= 1; // Go for next bit
+ }
+ }
+ break;
+ }
+ return (count);
+ }
+
+ /// \return Address family
+ int getFamily() const {
+ return (family_);
+ }
+ ///@}
+
+protected:
+ /// \brief Comparison
+ ///
+ /// This is the actual comparison function that checks the IP address passed
+ /// to this class with the matching information in the class itself. It is
+ /// expected to be called from matches().
+ ///
+ /// \param testaddr Address (in network byte order) to test against the
+ /// check condition in the class. This is expected to
+ /// be IPV6_SIZE or IPV4_SIZE bytes long.
+ /// \param family Address family of testaddr.
+ ///
+ /// \return true if the address matches, false if it does not.
+ virtual bool compare(const uint8_t* testaddr, int family) const {
+
+ if (family != family_) {
+ // Can't match if the address is of the wrong family
+ return (false);
+ }
+
+ // Simple check failed, so have to do a complete match. To check that
+ // the address given matches the stored network address and mask, we
+ // check the simple condition that:
+ //
+ // address_given & mask_ == stored_address & mask_
+ //
+ // The result is checked for all bytes for which there are bits set in
+ // the mask. We stop at the first non-match (or when we run out of bits
+ // in the mask).
+ //
+ // Note that the mask represents a contiguous set of bits. As such, as
+ // soon as we find a mask byte of zeroes, we have run past the part of
+ // the address where we need to match.
+ //
+ // Note also that when checking an IPv4 address, the constructor has
+ // set all bytes in the mask beyond the first four bytes to zero.
+ // As the loop stops when it encounters a zero mask byte, if the
+ // ACL is for an IPV4 address, the loop will never check more than four
+ // bytes.
+
+ bool match = true;
+ for (int i = 0; match && (i < IPV6_SIZE) && (mask_[i] != 0); ++i) {
+ match = ((testaddr[i] & mask_[i]) == (address_[i] & mask_[i]));
+ }
+ return (match);
+ }
+
+private:
+ /// \brief Set Mask
+ ///
+ /// Sets up the mask from the prefix length. This involves setting
+ /// an individual mask in each byte of the mask array.
+ ///
+ /// The actual allowed value of the prefix length depends on the address
+ /// family.
+ ///
+ /// \param requested Requested prefix length size. If negative, the
+ /// maximum for the address family is assumed. (A negative value
+ /// will arise if the string constructor was used and no mask size
+ /// was given.)
+ void setMask(int requested) {
+
+ // Set the maximum number of bits allowed in the mask, and request
+ // that number of bits if no prefix length was given in the constructor.
+ const int maxmask = 8 * ((family_ == AF_INET) ? IPV4_SIZE : IPV6_SIZE);
+ if (requested < 0) {
+ requested = maxmask;
+ }
+
+ // Validate that the mask is valid.
+ if (requested <= maxmask) {
+
+ // Loop, setting the bits in the set of mask bytes until all the
+ // specified bits have been used up. As both IPv4 and IPv6
+ // addresses are stored in network-byte order, this works in
+ // both cases.
+ size_t bits_left = requested; // Bits remaining to set
+ int i = -1;
+ while (bits_left > 0) {
+ if (bits_left >= 8) {
+ mask_[++i] = ~0; // All bits set
+ bits_left -= 8;
+
+ } else if (bits_left > 0) {
+ mask_[++i] = internal::createMask(bits_left);
+ bits_left = 0;
+ }
+ }
+ } else {
+ isc_throw(isc::OutOfRange,
+ "mask size of " << requested << " is invalid " <<
+ "for the given address family");
+ }
+ }
+
+ // Member variables.
+ uint8_t address_[IPV6_SIZE]; ///< Address in binary form
+ uint8_t mask_[IPV6_SIZE]; ///< Address mask
+ int family_; ///< Address family
+};
+
+} // namespace acl
+} // namespace isc
+
+#endif // __IP_CHECK_H
diff --git a/src/lib/acl/tests/Makefile.am b/src/lib/acl/tests/Makefile.am
index 9328c68..0f17e37 100644
--- a/src/lib/acl/tests/Makefile.am
+++ b/src/lib/acl/tests/Makefile.am
@@ -5,16 +5,21 @@ TESTS =
if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = run_unittests.cc
-run_unittests_SOURCES += check_test.cc acl_test.cc loader_test.cc
-run_unittests_SOURCES += logcheck.h
+run_unittests_SOURCES += acl_test.cc
+run_unittests_SOURCES += check_test.cc
run_unittests_SOURCES += dns_test.cc
+run_unittests_SOURCES += ip_check_unittest.cc
+run_unittests_SOURCES += loader_test.cc
+run_unittests_SOURCES += logcheck.h
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(GTEST_LDADD)
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/acl/libacl.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
run_unittests_LDADD += $(top_builddir)/src/lib/acl/libdnsacl.la
endif
diff --git a/src/lib/acl/tests/ip_check_unittest.cc b/src/lib/acl/tests/ip_check_unittest.cc
new file mode 100644
index 0000000..3fcb05b
--- /dev/null
+++ b/src/lib/acl/tests/ip_check_unittest.cc
@@ -0,0 +1,588 @@
+// 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 <gtest/gtest.h>
+#include <acl/ip_check.h>
+
+using namespace isc::acl;
+using namespace isc::acl::internal;
+using namespace std;
+
+namespace {
+const size_t IPV4_SIZE = 4;
+const size_t IPV6_SIZE = 16;
+
+// Simple struct holding either an IPV4 or IPV6 address. This is the "Context"
+// used for the tests.
+//
+// The structure is also used for converting an IPV4 address to a four-byte
+// array.
+struct GeneralAddress {
+ int family; // Family of the address
+ vector<uint8_t> addr; // Address type. Size indicates what it holds
+
+ // Convert uint32_t address in host-byte order to a uint8_t vector in
+ // network-byte order.
+ vector<uint8_t> convertUint32(uint32_t address) {
+ BOOST_STATIC_ASSERT(sizeof(uint32_t) == IPV4_SIZE);
+
+ vector<uint8_t> result(IPV4_SIZE);
+
+ // Address is in network-byte order, so copy to the array. The
+ // MS byte is at the lowest address.
+ result[3] = address & 0xff;
+ result[2] = (address >> 8) & 0xff;
+ result[1] = (address >> 16) & 0xff;
+ result[0] = (address >> 24) & 0xff;
+
+ return (result);
+ }
+
+ // Convenience constructor for V4 address. As it is not marked as explicit,
+ // it allows the automatic promotion of a uint32_t to a GeneralAddress data
+ // type in calls to matches().
+ GeneralAddress(uint32_t address) : family(AF_INET), addr()
+ {
+ addr = convertUint32(address);
+ }
+
+ // Convenience constructor for V6 address. As it is not marked as explicit,
+ // it allows the automatic promotion of a vector<uint8_t> to a
+ // GeneralAddress data type in calls to matches().
+ GeneralAddress(const vector<uint8_t>& address) : family(AF_INET6),
+ addr(address)
+ {
+ if (address.size() != IPV6_SIZE) {
+ isc_throw(isc::InvalidParameter, "vector passed to GeneralAddress "
+ "constructor is " << address.size() << " bytes long - it "
+ "should be " << IPV6_SIZE << " bytes instead");
+ }
+ }
+
+ // A couple of convenience methods for checking equality with different
+ // representations of an address.
+
+ // Check that the IPV4 address is the same as that given.
+ bool equals(uint32_t address) {
+ if (family == AF_INET) {
+ const vector<uint8_t> byte_address = convertUint32(address);
+ return (equal(byte_address.begin(), byte_address.end(),
+ addr.begin()));
+ }
+ return (false);
+ }
+
+ // Check that the array is equal to that given.
+ bool equals(const vector<uint8_t>& byte_address) {
+ if (addr.size() == byte_address.size()) {
+ return (equal(byte_address.begin(), byte_address.end(),
+ addr.begin()));
+ }
+ return (false);
+ }
+};
+} // Unnamed namespace
+
+// Provide a specialisation of the IPCheck::matches() method for the
+// GeneralAddress class.
+
+namespace isc {
+namespace acl {
+template <>
+bool IPCheck<GeneralAddress>::matches(const GeneralAddress& address) const {
+ return (compare(&address.addr[0], address.family));
+}
+} // namespace acl
+} // namespace isc
+
+namespace {
+/// *** Free Function Tests ***
+
+// Test the createMask() function.
+TEST(IPFunctionCheck, CreateMask) {
+
+ // Invalid arguments should throw.
+ EXPECT_THROW(createMask(9), isc::OutOfRange);
+
+ // Check on all possible 8-bit values.
+ uint16_t expected = 0xff00;
+ for (size_t i = 0; i <= 8; ++i, expected >>= 1) {
+ EXPECT_EQ(static_cast<uint8_t>(expected & 0xff), createMask(i));
+ }
+}
+
+// Test the splitIPAddress() function.
+TEST(IPFunctionCheck, SplitIPAddress) {
+ pair<string, uint32_t> result;
+
+ result = splitIPAddress("192.0.2.1");
+ EXPECT_EQ(string("192.0.2.1"), result.first);
+ EXPECT_EQ(-1, result.second);
+
+ result = splitIPAddress("192.0.2.1/24");
+ EXPECT_EQ(string("192.0.2.1"), result.first);
+ EXPECT_EQ(24, result.second);
+
+ result = splitIPAddress("2001:db8::/128");
+ EXPECT_EQ(string("2001:db8::"), result.first);
+ EXPECT_EQ(128, result.second);
+
+ result = splitIPAddress("192.0.2.1/0");
+ EXPECT_EQ(string("192.0.2.1"), result.first);
+ EXPECT_EQ(0, result.second);
+
+ EXPECT_THROW(splitIPAddress("192.0.2.43/27 "), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress("192.0.2.43/-1"), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress("192.0.2.43//1"), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress("192.0.2.43/1/"), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress("/192.0.2.43/1"), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress("2001:db8::/xxxx"), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress("2001:db8::/32/s"), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress("1/"), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress("/1"), isc::InvalidParameter);
+ EXPECT_THROW(splitIPAddress(" 1/ "), isc::InvalidParameter);
+}
+
+// *** IPv4 Tests ***
+
+TEST(IPCheck, V4StringConstructor) {
+
+ // Constructor with no prefix length given (32 is assumed).
+ IPCheck<GeneralAddress> acl1("192.0.2.255");
+ EXPECT_EQ(32, acl1.getPrefixlen());
+ EXPECT_EQ(AF_INET, acl1.getFamily());
+
+ vector<uint8_t> stored1 = acl1.getAddress();
+ EXPECT_EQ(IPV4_SIZE, stored1.size());
+ GeneralAddress expected1(0xc00002ff);
+ EXPECT_TRUE(expected1.equals(stored1));
+
+ // Constructor with valid mask given
+ IPCheck<GeneralAddress> acl2("192.0.2.0/24");
+ EXPECT_EQ(24, acl2.getPrefixlen());
+ EXPECT_EQ(AF_INET, acl2.getFamily());
+
+ vector<uint8_t> stored2 = acl2.getAddress();
+ EXPECT_EQ(IPV4_SIZE, stored2.size());
+ GeneralAddress expected2(0xc0000200);
+ EXPECT_TRUE(expected2.equals(stored2));
+
+ // More valid masks
+ IPCheck<GeneralAddress> acl3("192.0.2.1/0");
+ EXPECT_EQ(0, acl3.getPrefixlen());
+ EXPECT_EQ(AF_INET, acl3.getFamily());
+
+ vector<uint8_t> stored3 = acl3.getAddress();
+ EXPECT_EQ(IPV4_SIZE, stored3.size());
+ GeneralAddress expected3(0xc0000201);
+ EXPECT_TRUE(expected3.equals(stored3));
+
+ IPCheck<GeneralAddress> acl4("192.0.2.2/32");
+ EXPECT_EQ(32, acl4.getPrefixlen());
+ EXPECT_EQ(AF_INET, acl4.getFamily());
+
+ vector<uint8_t> stored4 = acl4.getAddress();
+ EXPECT_EQ(IPV4_SIZE, stored4.size());
+ GeneralAddress expected4(0xc0000202);
+ EXPECT_TRUE(expected4.equals(stored4));
+
+ // Any match
+ IPCheck<GeneralAddress> acl5("any4");
+ EXPECT_EQ(0, acl5.getPrefixlen());
+ EXPECT_EQ(AF_INET, acl5.getFamily());
+
+ vector<uint8_t> stored5 = acl5.getAddress();
+ EXPECT_EQ(IPV4_SIZE, stored5.size());
+ GeneralAddress expected5(0);
+ EXPECT_TRUE(expected5.equals(stored5));
+
+ // Invalid prefix lengths
+ EXPECT_THROW(IPCheck<GeneralAddress>("192.0.2.0/33"), isc::OutOfRange);
+
+ // ... and invalid strings
+ EXPECT_THROW(IPCheck<GeneralAddress>("192.0.2.0/-1"),
+ isc::InvalidParameter);
+ EXPECT_THROW(IPCheck<GeneralAddress>("192.0.2.0/24/3"),
+ isc::InvalidParameter);
+ EXPECT_THROW(IPCheck<GeneralAddress>("192.0.2.0/ww"),
+ isc::InvalidParameter);
+ EXPECT_THROW(IPCheck<GeneralAddress>("aa.255.255.0/ww"),
+ isc::InvalidParameter);
+}
+
+TEST(IPCheck, V4CopyConstructor) {
+ IPCheck<GeneralAddress> acl1("192.0.2.1/24");
+ IPCheck<GeneralAddress> acl2(acl1);
+
+ EXPECT_EQ(acl1.getPrefixlen(), acl2.getPrefixlen());
+ EXPECT_EQ(acl1.getFamily(), acl2.getFamily());
+
+ vector<uint8_t> net1 = acl1.getMask();
+ vector<uint8_t> net2 = acl2.getMask();
+ EXPECT_EQ(net1.size(), net2.size());
+ EXPECT_TRUE(equal(net1.begin(), net1.end(), net2.begin()));
+
+ net1 = acl1.getAddress();
+ net2 = acl2.getAddress();
+ EXPECT_EQ(net1.size(), net2.size());
+ EXPECT_TRUE(equal(net1.begin(), net1.end(), net2.begin()));
+}
+
+TEST(IPCheck, V4AssignmentOperator) {
+ IPCheck<GeneralAddress> acl1("192.0.2.0/24");
+ IPCheck<GeneralAddress> acl2("192.0.2.128/25");
+ acl2 = acl1;
+
+ EXPECT_EQ(acl1.getPrefixlen(), acl2.getPrefixlen());
+ EXPECT_EQ(acl1.getFamily(), acl2.getFamily());
+
+ vector<uint8_t> net1 = acl1.getMask();
+ vector<uint8_t> net2 = acl2.getMask();
+ EXPECT_EQ(net1.size(), net2.size());
+ EXPECT_TRUE(equal(net1.begin(), net1.end(), net2.begin()));
+
+ net1 = acl1.getAddress();
+ net2 = acl2.getAddress();
+ EXPECT_EQ(net1.size(), net2.size());
+ EXPECT_TRUE(equal(net1.begin(), net1.end(), net2.begin()));
+}
+
+// Check that the comparison works - note that "matches" just calls the
+// internal compare() code. (Also note that the argument to matches() will be
+// automatically converted to the GeneralAddress data type used for the tests
+// because of its constructor taking a uint32_t argument.
+
+TEST(IPCheck, V4Compare) {
+ // Exact address - match if given address matches stored address.
+ IPCheck<GeneralAddress> acl1("192.0.2.255/32");
+ EXPECT_TRUE(acl1.matches(0xc00002ff));
+ EXPECT_FALSE(acl1.matches(0xc00002fe));
+ EXPECT_FALSE(acl1.matches(0x13457f13));
+
+ IPCheck<GeneralAddress> acl2("192.0.2.255/27");
+ EXPECT_TRUE(acl2.matches(0xc00002ff));
+ EXPECT_TRUE(acl2.matches(0xc00002fe));
+ EXPECT_TRUE(acl2.matches(0xc00002ee));
+ EXPECT_FALSE(acl2.matches(0xc00002de));
+ EXPECT_FALSE(acl2.matches(0xd00002fe));
+ EXPECT_FALSE(acl2.matches(0x13457f13));
+
+ // Match if "any4" is specified
+ IPCheck<GeneralAddress> acl3("any4");
+ EXPECT_TRUE(acl3.matches(0xc00002ff));
+ EXPECT_TRUE(acl3.matches(0xc00002fe));
+ EXPECT_TRUE(acl3.matches(0xc00002ee));
+ EXPECT_TRUE(acl3.matches(0xc00002de));
+ EXPECT_TRUE(acl3.matches(0xd00002fe));
+ EXPECT_TRUE(acl3.matches(0x13457f13));
+
+ IPCheck<GeneralAddress> acl4("0.0.0.0/0");
+ EXPECT_TRUE(acl4.matches(0xc00002ff));
+ EXPECT_TRUE(acl4.matches(0xc00002fe));
+ EXPECT_TRUE(acl4.matches(0xc00002ee));
+ EXPECT_TRUE(acl4.matches(0xc00002de));
+ EXPECT_TRUE(acl4.matches(0xd00002fe));
+ EXPECT_TRUE(acl4.matches(0x13457f13));
+
+ IPCheck<GeneralAddress> acl5("192.0.2.255/0");
+ EXPECT_TRUE(acl5.matches(0xc00002ff));
+ EXPECT_TRUE(acl5.matches(0xc00002fe));
+ EXPECT_TRUE(acl5.matches(0xc00002ee));
+ EXPECT_TRUE(acl5.matches(0xc00002de));
+ EXPECT_TRUE(acl5.matches(0xd00002fe));
+ EXPECT_TRUE(acl5.matches(0x13457f13));
+}
+
+// *** IPV6 Tests ***
+
+// Some constants used in the tests
+
+const char* V6ADDR_1_STRING = "2001:0db8:1122:3344:5566:7788:99aa:bbcc";
+const uint8_t V6ADDR_1[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x11, 0x22, 0x33, 0x44,
+ 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc
+};
+
+const char* V6ADDR_2_STRING = "2001:0db8::dead:beef";
+const uint8_t V6ADDR_2[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef
+};
+
+// Identical to V6ADDR_2 to 48 bits
+const uint8_t V6ADDR_2_48[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0xff, 0x66,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef
+};
+
+// Identical to V6ADDR_2 to 49 bits
+const uint8_t V6ADDR_2_49[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x7f, 0x66,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef
+};
+
+// Identical to V6ADDR_2 to 50 bits
+const uint8_t V6ADDR_2_50[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x3f, 0x66,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef
+};
+
+// Identical to V6ADDR_2 to 51 bits
+const uint8_t V6ADDR_2_51[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x1f, 0x66,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef
+};
+
+// Identical to V6ADDR_2 to 51 bits
+const uint8_t V6ADDR_2_52[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x0f, 0x66,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef
+};
+
+// Identical to V6ADDR_2 to 127 bits
+const uint8_t V6ADDR_2_127[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xee
+};
+
+const uint8_t V6ADDR_3[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+};
+
+const uint8_t V6ADDR_4[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+TEST(IPCheck, V6StringConstructor) {
+ IPCheck<GeneralAddress> acl1(V6ADDR_1_STRING);
+ vector<uint8_t> address = acl1.getAddress();
+
+ EXPECT_EQ(128, acl1.getPrefixlen());
+ EXPECT_EQ(AF_INET6, acl1.getFamily());
+ EXPECT_EQ(IPV6_SIZE, address.size());
+ EXPECT_TRUE(equal(address.begin(), address.end(), V6ADDR_1));
+
+ IPCheck<GeneralAddress> acl2(string(V6ADDR_2_STRING) + string("/51"));
+ address = acl2.getAddress();
+ EXPECT_EQ(IPV6_SIZE, address.size());
+ EXPECT_EQ(51, acl2.getPrefixlen());
+ EXPECT_EQ(AF_INET6, acl2.getFamily());
+ EXPECT_TRUE(equal(address.begin(), address.end(), V6ADDR_2));
+
+ IPCheck<GeneralAddress> acl3(string(V6ADDR_2_STRING) + string("/127"));
+ address = acl3.getAddress();
+ EXPECT_EQ(IPV6_SIZE, address.size());
+ EXPECT_EQ(127, acl3.getPrefixlen());
+ EXPECT_EQ(AF_INET6, acl3.getFamily());
+ EXPECT_TRUE(equal(address.begin(), address.end(), V6ADDR_2));
+
+ IPCheck<GeneralAddress> acl4("::1");
+ address = acl4.getAddress();
+ EXPECT_EQ(IPV6_SIZE, address.size());
+ EXPECT_EQ(128, acl4.getPrefixlen());
+ EXPECT_EQ(AF_INET6, acl4.getFamily());
+ EXPECT_TRUE(equal(address.begin(), address.end(), V6ADDR_3));
+
+ // Any match. In these cases, the address should all be zeroes.
+ IPCheck<GeneralAddress> acl5("any6");
+ address = acl5.getAddress();
+ EXPECT_EQ(IPV6_SIZE, address.size());
+ EXPECT_EQ(0, acl5.getPrefixlen());
+ EXPECT_EQ(AF_INET6, acl5.getFamily());
+ EXPECT_TRUE(equal(address.begin(), address.end(), V6ADDR_4));
+
+ IPCheck<GeneralAddress> acl6("::/0");
+ address = acl6.getAddress();
+ EXPECT_EQ(0, acl6.getPrefixlen());
+ EXPECT_EQ(AF_INET6, acl6.getFamily());
+ EXPECT_TRUE(equal(address.begin(), address.end(), V6ADDR_4));
+
+ // Some invalid strings
+ EXPECT_THROW(IPCheck<GeneralAddress>("::1/129"), isc::OutOfRange);
+ EXPECT_THROW(IPCheck<GeneralAddress>("::1/24/3"), isc::InvalidParameter);
+ EXPECT_THROW(IPCheck<GeneralAddress>(":::1/24"), isc::InvalidParameter);
+ EXPECT_THROW(IPCheck<GeneralAddress>("2001:0db8::abcd/ww"),
+ isc::InvalidParameter);
+ EXPECT_THROW(IPCheck<GeneralAddress>("2xx1:0db8::abcd/32"),
+ isc::InvalidParameter);
+}
+
+TEST(IPCheck, V6CopyConstructor) {
+ IPCheck<GeneralAddress> acl1(string(V6ADDR_2_STRING) + string("/52"));
+ IPCheck<GeneralAddress> acl2(acl1);
+
+ vector<uint8_t> acl1_address = acl1.getAddress();
+ vector<uint8_t> acl2_address = acl1.getAddress();
+ EXPECT_EQ(sizeof(V6ADDR_1), acl1_address.size());
+ EXPECT_EQ(acl1_address.size(), acl2_address.size());
+ EXPECT_TRUE(equal(acl1_address.begin(), acl1_address.end(),
+ acl2_address.begin()));
+
+ EXPECT_EQ(acl1.getPrefixlen(), acl2.getPrefixlen());
+
+ vector<uint8_t> acl1_mask = acl1.getMask();
+ vector<uint8_t> acl2_mask = acl1.getMask();
+ EXPECT_EQ(sizeof(V6ADDR_1), acl1_mask.size());
+ EXPECT_EQ(acl1_mask.size(), acl2_mask.size());
+ EXPECT_TRUE(equal(acl1_mask.begin(), acl1_mask.end(),
+ acl2_mask.begin()));
+}
+
+TEST(IPCheck, V6AssignmentOperator) {
+ IPCheck<GeneralAddress> acl1(string(V6ADDR_2_STRING) + string("/52"));
+ IPCheck<GeneralAddress> acl2(string(V6ADDR_1_STRING) + string("/48"));
+
+ acl2 = acl1;
+
+ vector<uint8_t> acl1_address = acl1.getAddress();
+ vector<uint8_t> acl2_address = acl2.getAddress();
+ EXPECT_EQ(sizeof(V6ADDR_1), acl1_address.size());
+ EXPECT_EQ(acl1_address.size(), acl2_address.size());
+ EXPECT_TRUE(equal(acl1_address.begin(), acl1_address.end(),
+ acl2_address.begin()));
+
+ EXPECT_EQ(acl1.getPrefixlen(), acl2.getPrefixlen());
+
+ vector<uint8_t> acl1_mask = acl1.getMask();
+ vector<uint8_t> acl2_mask = acl2.getMask();
+ EXPECT_EQ(sizeof(V6ADDR_1), acl1_mask.size());
+ EXPECT_EQ(acl1_mask.size(), acl2_mask.size());
+ EXPECT_TRUE(equal(acl1_mask.begin(), acl1_mask.end(),
+ acl2_mask.begin()));
+}
+
+TEST(IPCheck, V6Compare) {
+ // Set up some data.
+ vector<uint8_t> v6addr_2(V6ADDR_2, V6ADDR_2 + IPV6_SIZE);
+ vector<uint8_t> v6addr_2_48(V6ADDR_2_48, V6ADDR_2_48 + IPV6_SIZE);
+ vector<uint8_t> v6addr_2_49(V6ADDR_2_49, V6ADDR_2_49 + IPV6_SIZE);
+ vector<uint8_t> v6addr_2_50(V6ADDR_2_50, V6ADDR_2_50 + IPV6_SIZE);
+ vector<uint8_t> v6addr_2_51(V6ADDR_2_51, V6ADDR_2_51 + IPV6_SIZE);
+ vector<uint8_t> v6addr_2_52(V6ADDR_2_52, V6ADDR_2_52 + IPV6_SIZE);
+ vector<uint8_t> v6addr_2_127(V6ADDR_2_127, V6ADDR_2_127 + IPV6_SIZE);
+ vector<uint8_t> v6addr_3(V6ADDR_3, V6ADDR_3 + IPV6_SIZE);
+
+ // Exact address - match if given address matches stored address.
+ IPCheck<GeneralAddress> acl1(string(V6ADDR_2_STRING) + string("/128"));
+ EXPECT_TRUE(acl1.matches(v6addr_2));
+ EXPECT_FALSE(acl1.matches(v6addr_2_127));
+ EXPECT_FALSE(acl1.matches(v6addr_2_52));
+ EXPECT_FALSE(acl1.matches(v6addr_2_51));
+ EXPECT_FALSE(acl1.matches(v6addr_2_50));
+ EXPECT_FALSE(acl1.matches(v6addr_2_49));
+ EXPECT_FALSE(acl1.matches(v6addr_2_48));
+ EXPECT_FALSE(acl1.matches(v6addr_3));
+
+ // Match to various prefixes.
+ IPCheck<GeneralAddress> acl2(string(V6ADDR_2_STRING) + string("/127"));
+ EXPECT_TRUE(acl2.matches(v6addr_2));
+ EXPECT_TRUE(acl2.matches(v6addr_2_127));
+ EXPECT_FALSE(acl2.matches(v6addr_2_52));
+ EXPECT_FALSE(acl2.matches(v6addr_2_51));
+ EXPECT_FALSE(acl2.matches(v6addr_2_50));
+ EXPECT_FALSE(acl2.matches(v6addr_2_49));
+ EXPECT_FALSE(acl2.matches(v6addr_2_48));
+ EXPECT_FALSE(acl2.matches(v6addr_3));
+
+ IPCheck<GeneralAddress> acl3(string(V6ADDR_2_STRING) + string("/52"));
+ EXPECT_TRUE(acl3.matches(v6addr_2));
+ EXPECT_TRUE(acl3.matches(v6addr_2_127));
+ EXPECT_TRUE(acl3.matches(v6addr_2_52));
+ EXPECT_FALSE(acl3.matches(v6addr_2_51));
+ EXPECT_FALSE(acl3.matches(v6addr_2_50));
+ EXPECT_FALSE(acl3.matches(v6addr_2_49));
+ EXPECT_FALSE(acl3.matches(v6addr_2_48));
+ EXPECT_FALSE(acl3.matches(v6addr_3));
+
+ IPCheck<GeneralAddress> acl4(string(V6ADDR_2_STRING) + string("/51"));
+ EXPECT_TRUE(acl4.matches(v6addr_2));
+ EXPECT_TRUE(acl4.matches(v6addr_2_127));
+ EXPECT_TRUE(acl4.matches(v6addr_2_52));
+ EXPECT_TRUE(acl4.matches(v6addr_2_51));
+ EXPECT_FALSE(acl4.matches(v6addr_2_50));
+ EXPECT_FALSE(acl4.matches(v6addr_2_49));
+ EXPECT_FALSE(acl4.matches(v6addr_2_48));
+ EXPECT_FALSE(acl4.matches(v6addr_3));
+
+ IPCheck<GeneralAddress> acl5(string(V6ADDR_2_STRING) + string("/50"));
+ EXPECT_TRUE(acl5.matches(v6addr_2));
+ EXPECT_TRUE(acl5.matches(v6addr_2_127));
+ EXPECT_TRUE(acl5.matches(v6addr_2_52));
+ EXPECT_TRUE(acl5.matches(v6addr_2_51));
+ EXPECT_TRUE(acl5.matches(v6addr_2_50));
+ EXPECT_FALSE(acl5.matches(v6addr_2_49));
+ EXPECT_FALSE(acl5.matches(v6addr_2_48));
+ EXPECT_FALSE(acl5.matches(v6addr_3));
+
+ IPCheck<GeneralAddress> acl6(string(V6ADDR_2_STRING) + string("/0"));
+ EXPECT_TRUE(acl6.matches(v6addr_2));
+ EXPECT_TRUE(acl6.matches(v6addr_2_127));
+ EXPECT_TRUE(acl6.matches(v6addr_2_52));
+ EXPECT_TRUE(acl6.matches(v6addr_2_51));
+ EXPECT_TRUE(acl6.matches(v6addr_2_50));
+ EXPECT_TRUE(acl6.matches(v6addr_2_49));
+ EXPECT_TRUE(acl6.matches(v6addr_2_48));
+ EXPECT_TRUE(acl6.matches(v6addr_3));
+
+ // Match on any address
+ IPCheck<GeneralAddress> acl7("any6");
+ EXPECT_TRUE(acl7.matches(v6addr_2));
+ EXPECT_TRUE(acl7.matches(v6addr_2_127));
+ EXPECT_TRUE(acl7.matches(v6addr_2_52));
+ EXPECT_TRUE(acl7.matches(v6addr_2_51));
+ EXPECT_TRUE(acl7.matches(v6addr_2_50));
+ EXPECT_TRUE(acl7.matches(v6addr_2_49));
+ EXPECT_TRUE(acl7.matches(v6addr_2_48));
+}
+
+// *** Mixed-mode tests - mainly to check that no exception is thrown ***
+
+TEST(IPCheck, MixedMode) {
+
+ // ACL has a V4 address specified, check against a V6 address.
+ IPCheck<GeneralAddress> acl1("192.0.2.255/24");
+ GeneralAddress test1(vector<uint8_t>(V6ADDR_1, V6ADDR_1 + IPV6_SIZE));
+ EXPECT_NO_THROW(acl1.matches(test1));
+ EXPECT_FALSE(acl1.matches(test1));
+
+ // Now the reverse - the ACL is specified with a V6 address.
+ IPCheck<GeneralAddress> acl2(V6ADDR_2_STRING);
+ GeneralAddress test2(0x12345678);
+ EXPECT_FALSE(acl2.matches(test2));
+
+ // Ensure only a V4 address matches "any4".
+ IPCheck<GeneralAddress> acl3("any4");
+ EXPECT_FALSE(acl3.matches(test1));
+ EXPECT_TRUE(acl3.matches(test2));
+
+ // ... and check the reverse
+ IPCheck<GeneralAddress> acl4("any6");
+ EXPECT_TRUE(acl4.matches(test1));
+ EXPECT_FALSE(acl4.matches(test2));
+
+ // Check where the bit pattern of an IPv4 address matches that of an IPv6
+ // one.
+ IPCheck<GeneralAddress> acl5("2001:db8::/32");
+ GeneralAddress test5(0x20010db8);
+ EXPECT_FALSE(acl5.matches(test5));
+
+ // ... and where the reverse is true. (2001:db8 corresponds to 32.1.13.184).
+ IPCheck<GeneralAddress> acl6("32.1.13.184");
+ GeneralAddress test6(vector<uint8_t>(V6ADDR_1, V6ADDR_1 + IPV6_SIZE));
+ EXPECT_FALSE(acl6.matches(test6));
+}
+} // Unnamed namespace
diff --git a/src/lib/acl/tests/run_unittests.cc b/src/lib/acl/tests/run_unittests.cc
index 61df6cf..8dc59a2 100644
--- a/src/lib/acl/tests/run_unittests.cc
+++ b/src/lib/acl/tests/run_unittests.cc
@@ -13,11 +13,12 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <gtest/gtest.h>
+#include <log/logger_support.h>
#include <util/unittests/run_all.h>
int
main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
+ isc::log::initLogger();
return (isc::util::unittests::run_all());
}
-
More information about the bind10-changes
mailing list