You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2018/04/12 22:40:11 UTC

[trafficserver] branch master updated: Add ats_ip_range_parse to ink_net.h to improve/replace ExtractIpRange.

This is an automated email from the ASF dual-hosted git repository.

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 2acce75  Add ats_ip_range_parse to ink_net.h to improve/replace ExtractIpRange.
2acce75 is described below

commit 2acce75b844069ae89f3f0d96ed7564c66b7ef4d
Author: Alan M. Carroll <am...@apache.org>
AuthorDate: Wed Apr 11 14:49:54 2018 -0500

    Add ats_ip_range_parse to ink_net.h to improve/replace ExtractIpRange.
---
 lib/ts/ink_inet.cc                 | 92 +++++++++++++++++++++++++++++++++++++-
 lib/ts/ink_inet.h                  |  2 +
 lib/ts/unit-tests/test_ink_inet.cc | 64 ++++++++++++++++++++++++++
 3 files changed, 156 insertions(+), 2 deletions(-)

diff --git a/lib/ts/ink_inet.cc b/lib/ts/ink_inet.cc
index d6bd3a6..5879600 100644
--- a/lib/ts/ink_inet.cc
+++ b/lib/ts/ink_inet.cc
@@ -21,14 +21,18 @@
   limitations under the License.
  */
 
+#include <fstream>
+
 #include "ts/ink_platform.h"
 #include "ts/ink_defs.h"
 #include "ts/ink_inet.h"
 #include "ts/ParseRules.h"
 #include "ts/CryptoHash.h"
 #include "ts/ink_assert.h"
-#include <fstream>
-#include <ts/TextView.h>
+#include "ts/apidefs.h"
+#include "ts/TextView.h"
+#include "ts/ink_inet.h"
+#include "ink_inet.h"
 
 IpAddr const IpAddr::INVALID;
 
@@ -262,6 +266,90 @@ ats_ip_pton(const ts::string_view &src, sockaddr *ip)
   return zret;
 }
 
+int
+ats_ip_range_parse(ts::string_view src, IpAddr &lower, IpAddr &upper)
+{
+  int zret = TS_ERROR;
+  IpAddr addr, addr2;
+  static const IpAddr ZERO_ADDR4{INADDR_ANY};
+  static const IpAddr MAX_ADDR4{INADDR_BROADCAST};
+  static const IpAddr ZERO_ADDR6{in6addr_any};
+  // I can't find a clean way to static const initialize an IPv6 address to all ones.
+  // This is the best I can find that's portable.
+  static const uint64_t ones[]{UINT64_MAX, UINT64_MAX};
+  static const IpAddr MAX_ADDR6{reinterpret_cast<in6_addr const &>(ones)};
+
+  auto idx = src.find_first_of("/-"_sv);
+  if (idx != src.npos) {
+    if (idx + 1 >= src.size()) { // must have something past the separator or it's bogus.
+      zret = TS_ERROR;
+    } else if ('/' == src[idx]) {
+      if (TS_SUCCESS == addr.load(src.substr(0, idx))) { // load the address
+        ts::TextView parsed;
+        src.remove_prefix(idx + 1); // drop address and separator.
+        int cidr = ts::svtoi(src, &parsed);
+        if (parsed.size() && 0 <= cidr) { // a cidr that's a positive integer.
+          // Special case the cidr sizes for 0, maximum, and for IPv6 64 bit boundaries.
+          if (addr.isIp4()) {
+            zret = TS_SUCCESS;
+            if (0 == cidr) {
+              lower = ZERO_ADDR4;
+              upper = MAX_ADDR4;
+            } else if (cidr <= 32) {
+              lower = upper = addr;
+              if (cidr < 32) {
+                in_addr_t mask = htonl(INADDR_BROADCAST << (32 - cidr));
+                lower._addr._ip4 &= mask;
+                upper._addr._ip4 |= ~mask;
+              }
+            } else {
+              zret = TS_ERROR;
+            }
+          } else if (addr.isIp6()) {
+            uint64_t mask;
+            zret = TS_SUCCESS;
+            if (cidr == 0) {
+              lower = ZERO_ADDR6;
+              upper = MAX_ADDR6;
+            } else if (cidr < 64) { // only upper bytes affected, lower bytes are forced.
+              mask          = htobe64(~static_cast<uint64_t>(0) << (64 - cidr));
+              lower._family = upper._family = addr._family;
+              lower._addr._u64[0]           = addr._addr._u64[0] & mask;
+              lower._addr._u64[1]           = 0;
+              upper._addr._u64[0]           = addr._addr._u64[0] | ~mask;
+              upper._addr._u64[1]           = ~static_cast<uint64_t>(0);
+            } else if (cidr == 64) {
+              lower._family = upper._family = addr._family;
+              lower._addr._u64[0] = upper._addr._u64[0] = addr._addr._u64[0];
+              lower._addr._u64[1]                       = 0;
+              upper._addr._u64[1]                       = ~static_cast<uint64_t>(0);
+            } else if (cidr <= 128) { // lower bytes changed, upper bytes unaffected.
+              lower = upper = addr;
+              if (cidr < 128) {
+                mask = htobe64(~static_cast<uint64_t>(0) << (128 - cidr));
+                lower._addr._u64[1] &= mask;
+                upper._addr._u64[1] |= ~mask;
+              }
+            } else {
+              zret = TS_ERROR;
+            }
+          }
+        }
+      }
+    } else if (TS_SUCCESS == addr.load(src.substr(0, idx)) && TS_SUCCESS == addr2.load(src.substr(idx + 1)) &&
+               addr.family() == addr2.family()) {
+      zret = TS_SUCCESS;
+      // not '/' so must be '-'
+      lower = addr;
+      upper = addr2;
+    }
+  } else if (TS_SUCCESS == addr.load(src)) {
+    zret  = TS_SUCCESS;
+    lower = upper = addr;
+  }
+  return zret;
+}
+
 uint32_t
 ats_ip_hash(sockaddr const *addr)
 {
diff --git a/lib/ts/ink_inet.h b/lib/ts/ink_inet.h
index fdb5f4a..351a70c 100644
--- a/lib/ts/ink_inet.h
+++ b/lib/ts/ink_inet.h
@@ -1448,6 +1448,8 @@ ats_ip_pton(const char *text, ///< [in] text.
   return addr.load(text) ? 0 : -1;
 }
 
+int ats_ip_range_parse(ts::string_view src, IpAddr &lower, IpAddr &upper);
+
 inline IpEndpoint &
 IpEndpoint::assign(IpAddr const &addr, in_port_t port)
 {
diff --git a/lib/ts/unit-tests/test_ink_inet.cc b/lib/ts/unit-tests/test_ink_inet.cc
index e7461d6..e40ba47 100644
--- a/lib/ts/unit-tests/test_ink_inet.cc
+++ b/lib/ts/unit-tests/test_ink_inet.cc
@@ -25,6 +25,9 @@
 #include <ts/ink_inet.h>
 #include <catch.hpp>
 #include <iostream>
+#include <ts/apidefs.h>
+#include <ts/ink_inet.h>
+#include <ts/BufferWriter.h>
 
 TEST_CASE("ink_inet", "[libts][inet][ink_inet]")
 {
@@ -65,6 +68,7 @@ TEST_CASE("ats_ip_pton", "[libts][inet][ink_inet]")
 {
   IpEndpoint ep;
   IpAddr addr;
+  IpAddr lower, upper;
 
   REQUIRE(0 == ats_ip_pton("76.14.64.156", &ep.sa));
   REQUIRE(0 == addr.load("76.14.64.156"));
@@ -79,4 +83,64 @@ TEST_CASE("ats_ip_pton", "[libts][inet][ink_inet]")
     break;
   default:;
   }
+
+  REQUIRE(TS_SUCCESS != addr.load("Evil Dave Rulz!"));
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("1.1.1.1-2.2.2.2"_sv, lower, upper));
+  REQUIRE(TS_SUCCESS != ats_ip_range_parse("172.16.39.0/", lower, upper));
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("172.16.39.0/24", lower, upper));
+  REQUIRE(TS_SUCCESS != ats_ip_range_parse("172.16.39.0-", lower, upper));
+  REQUIRE(TS_SUCCESS != ats_ip_range_parse("172.16.39.0/35", lower, upper));
+  REQUIRE(TS_SUCCESS != ats_ip_range_parse("172.16.39.0/-20", lower, upper));
+  REQUIRE(TS_SUCCESS != ats_ip_range_parse("Thanks, Persia! You're the best.", lower, upper));
+
+  addr.load("172.16.39.0");
+  REQUIRE(addr == lower);
+  addr.load("172.16.39.255");
+  REQUIRE(addr == upper);
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("10.169.243.105/23", lower, upper));
+  addr.load("10.169.242.0");
+  REQUIRE(lower == addr);
+  addr.load("10.169.243.255");
+  REQUIRE(upper == addr);
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("192.168.99.22", lower, upper));
+  REQUIRE(lower == upper);
+  REQUIRE(lower != IpAddr{INADDR_ANY});
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("0/0", lower, upper));
+  REQUIRE(lower == IpAddr{INADDR_ANY});
+  REQUIRE(upper == IpAddr{INADDR_BROADCAST});
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("c600::-d900::"_sv, lower, upper));
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("1300::/96", lower, upper));
+  REQUIRE(TS_SUCCESS != ats_ip_range_parse("ffee::24c3:3349:3cee:0143/", lower, upper));
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("ffee:1337:beef:dead:24c3:3349:3cee:0143/80", lower, upper));
+  addr.load("ffee:1337:beef:dead:24c3::"_sv);
+  REQUIRE(lower == addr);
+  addr.load("ffee:1337:beef:dead:24c3:FFFF:FFFF:FFFF"_sv);
+  REQUIRE(upper == addr);
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("ffee:1337:beef:dead:24c3:3349:3cee:0143/57", lower, upper));
+  addr.load("ffee:1337:beef:de80::"_sv);
+  REQUIRE(lower == addr);
+  addr.load("ffee:1337:beef:deff:FFFF:FFFF:FFFF:FFFF"_sv);
+  REQUIRE(upper == addr);
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("ffee::24c3:3349:3cee:0143", lower, upper));
+  REQUIRE(lower == upper);
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("::/0", lower, upper));
+  REQUIRE(lower._addr._u64[0] == 0);
+  REQUIRE(lower._addr._u64[1] == 0);
+  REQUIRE(upper._addr._u64[0] == ~static_cast<uint64_t>(0));
+  REQUIRE(upper._addr._u64[1] == static_cast<uint64_t>(-1));
+
+  REQUIRE(TS_SUCCESS == ats_ip_range_parse("c000::/32", lower, upper));
+  addr.load("c000::");
+  REQUIRE(addr == lower);
+  addr.load("c000::ffff:ffff:ffff:ffff:ffff:ffff");
+  REQUIRE(addr == upper);
 }

-- 
To stop receiving notification emails like this one, please contact
amc@apache.org.