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.