Browse Source

[trac998] Add any4 and any6 as valid address prefixes

Stephen Morris 14 years ago
parent
commit
5a75094dfd
2 changed files with 72 additions and 38 deletions
  1. 39 20
      src/lib/acl/ip_check.h
  2. 33 18
      src/lib/acl/tests/ip_check_unittest.cc

+ 39 - 20
src/lib/acl/ip_check.h

@@ -244,43 +244,62 @@ public:
     ///
     /// 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 exactly as-is
+    /// (i.e. lowercase, with no leading or trailing spaces).
     ///
-    /// \param address IP address and mask in the form "<ip-address>/n"
+    /// \param addrprfx 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.
+    ///        address in that address family.  The address can also be
+    ///        given as "any4" or "any6".
     /// \param inverse If false (the default), matches() returns true if the
     ///        condition matches.  If true, matches() returns true if the
     ///        condition does not match.
-    IPCheck(const std::string& address, bool inverse = false) :
+    IPCheck(const std::string& addrprfx, bool inverse = false) :
             address_(), mask_(), prefixlen_(0), inverse_(inverse),
-            family_(0), straddr_(address)
+            family_(0), straddr_(addrprfx)
     {
         // Initialize.
         std::fill(address_.word, address_.word + IPV6_SIZE32, 0);
         std::fill(mask_.word, mask_.word + IPV6_SIZE32, 0);
 
-        // Split the address into address part and mask.
-        std::pair<std::string, int> result = splitIPAddress(address);
+        // Check for special cases first
+        if (addrprfx == "any4") {
+            family_ = AF_INET;
 
-        // Try to convert the address.  If successful, the result is in
-        // network-byte order (most significant components at lower addresses).
-        family_ = AF_INET6;
-        int status = inet_pton(AF_INET6, result.first.c_str(), address_.byte);
-        if (status == 0) {
+        } else if (addrprfx == "any6") {
+            family_ = AF_INET6;
 
-            // Not IPV6, try IPv4
-            family_ = AF_INET;
-            int status = inet_pton(AF_INET, result.first.c_str(),
-                                   address_.word);
+        } else {
+
+            // General address prefix.  Split into address part and prefix
+            // length.
+
+            std::pair<std::string, int> result = splitIPAddress(addrprfx);
+
+            // Try to convert the address.  If successful, the result is in
+            // network-byte order (most significant components at lower
+            // addresses).
+            family_ = AF_INET6;
+            int status = inet_pton(AF_INET6, result.first.c_str(),
+                                   address_.byte);
             if (status == 0) {
-                isc_throw(isc::InvalidParameter, "address of " <<
-                          result.first << " is a not valid IP address");
+
+                // Not IPV6, try IPv4
+                family_ = AF_INET;
+                int status = inet_pton(AF_INET, result.first.c_str(),
+                                       address_.word);
+                if (status == 0) {
+                    isc_throw(isc::InvalidParameter, "address prefix of " <<
+                              result.first << " is a not valid");
+                }
             }
-        }
 
-        // All done, so set the mask used in checking.
-        setMask(result.second);
+            // All done, so set the mask used in checking.
+            setMask(result.second);
+        }
     }
 
     /// \brief Copy constructor

+ 33 - 18
src/lib/acl/tests/ip_check_unittest.cc

@@ -178,16 +178,16 @@ TEST(IPCheck, V4ConstructorMask) {
     // use the general address structure to handle conversions between words
     // and bytes
     IPCheck<GeneralAddress> acl1(1, 1);         // Address of 1 is placeholder
-    GeneralAddress netmask1(htonl(0x80000000)); // Expected mask
+    GeneralAddress mask1(htonl(0x80000000));    // Expected mask
     vector<uint8_t> stored1 = acl1.getNetmask();
-    EXPECT_TRUE(netmask1.equals(stored1));
+    EXPECT_TRUE(mask1.equals(stored1));
     EXPECT_EQ(1, acl1.getPrefixlen());
 
     // Different check
     IPCheck<GeneralAddress> acl2(1, 24);
-    GeneralAddress netmask2(htonl(0xffffff00));
+    GeneralAddress mask2(htonl(0xffffff00));
     vector<uint8_t> stored2 = acl2.getNetmask();
-    EXPECT_TRUE(netmask2.equals(stored2));
+    EXPECT_TRUE(mask2.equals(stored2));
     EXPECT_EQ(24, acl2.getPrefixlen());
 
     // ... and some invalid network masks
@@ -197,7 +197,7 @@ TEST(IPCheck, V4ConstructorMask) {
 }
 
 TEST(IPCheck, V4ConstructorInverse) {
-    // Valid values. Address/mask of "1" is used as a placeholder
+    // Valid values. Address ands mask of "1" are used as placeholders
     IPCheck<GeneralAddress> acl1(1, 1);
     EXPECT_FALSE(acl1.getInverse());
 
@@ -212,6 +212,7 @@ TEST(IPCheck, V4StringConstructor) {
     // Constructor with no mask given
     IPCheck<GeneralAddress> acl1("192.0.2.255");
     EXPECT_EQ(32, acl1.getPrefixlen());
+    EXPECT_EQ(AF_INET, acl1.getFamily());
 
     vector<uint8_t> stored1 = acl1.getAddress();
     GeneralAddress expected1(htonl(0xc00002ff));
@@ -220,12 +221,18 @@ TEST(IPCheck, V4StringConstructor) {
     // 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();
     GeneralAddress expected2(htonl(0xc0000200));
     EXPECT_TRUE(expected2.equals(stored2));
 
-    // Invalid masks
+    // Any match
+    IPCheck<GeneralAddress> acl3("any4");
+    EXPECT_EQ(0, acl3.getPrefixlen());
+    EXPECT_EQ(AF_INET, acl3.getFamily());
+
+    // Invalid prefix lengths
     EXPECT_THROW(IPCheck<GeneralAddress>("192.0.2.0/33"), isc::OutOfRange);
     EXPECT_THROW(IPCheck<GeneralAddress>("192.0.2.0/24/3"),
                  isc::InvalidParameter);
@@ -433,18 +440,26 @@ 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_TRUE(equal(address.begin(), address.end(), V6ADDR_1));
 
     IPCheck<GeneralAddress> acl2(string(V6ADDR_2_STRING) + string("/48"));
     address = acl2.getAddress();
     EXPECT_EQ(48, acl2.getPrefixlen());
+    EXPECT_EQ(AF_INET6, acl2.getFamily());
     EXPECT_TRUE(equal(address.begin(), address.end(), V6ADDR_2));
 
     IPCheck<GeneralAddress> acl3("::1");
     address = acl3.getAddress();
     EXPECT_EQ(128, acl3.getPrefixlen());
+    EXPECT_EQ(AF_INET6, acl3.getFamily());
     EXPECT_TRUE(equal(address.begin(), address.end(), V6ADDR_3));
 
+    // Any match
+    IPCheck<GeneralAddress> acl4("any6");
+    EXPECT_EQ(0, acl4.getPrefixlen());
+    EXPECT_EQ(AF_INET6, acl4.getFamily());
+
     EXPECT_NO_THROW(IPCheck<GeneralAddress>("::1/0"));
     EXPECT_THROW(IPCheck<GeneralAddress>("::1/129"), isc::OutOfRange);
     EXPECT_THROW(IPCheck<GeneralAddress>("::1/24/3"), isc::InvalidParameter);
@@ -467,12 +482,12 @@ TEST(IPCheck, V6CopyConstructor) {
 
     EXPECT_EQ(acl1.getPrefixlen(), acl2.getPrefixlen());
 
-    vector<uint8_t> acl1_netmask = acl1.getNetmask();
-    vector<uint8_t> acl2_netmask = acl1.getNetmask();
-    EXPECT_EQ(sizeof(V6ADDR_1), acl1_netmask.size());
-    EXPECT_EQ(acl1_netmask.size(), acl2_netmask.size());
-    EXPECT_TRUE(equal(acl1_netmask.begin(), acl1_netmask.end(),
-                acl2_netmask.begin()));
+    vector<uint8_t> acl1_mask = acl1.getNetmask();
+    vector<uint8_t> acl2_mask = acl1.getNetmask();
+    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()));
 
     EXPECT_EQ(acl1.getInverse(), acl2.getInverse());
 }
@@ -492,12 +507,12 @@ TEST(IPCheck, V6AssignmentOperator) {
 
     EXPECT_EQ(acl1.getPrefixlen(), acl2.getPrefixlen());
 
-    vector<uint8_t> acl1_netmask = acl1.getNetmask();
-    vector<uint8_t> acl2_netmask = acl2.getNetmask();
-    EXPECT_EQ(sizeof(V6ADDR_1), acl1_netmask.size());
-    EXPECT_EQ(acl1_netmask.size(), acl2_netmask.size());
-    EXPECT_TRUE(equal(acl1_netmask.begin(), acl1_netmask.end(),
-                acl2_netmask.begin()));
+    vector<uint8_t> acl1_mask = acl1.getNetmask();
+    vector<uint8_t> acl2_mask = acl2.getNetmask();
+    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()));
 
     EXPECT_EQ(acl1.getInverse(), acl2.getInverse());
 }