Add an IPPrefix::forString parsing function.
This provides a way to parse IP prefixes from strings, and
addresses a TODO. Instead of reusing NetdConstants' parsePrefix
function, which it cannot depend on, it implements the parsing
using the IPAddress class in the same file and standard string
methods.
Bug: 153694684
Test: new unit tests
Original-Change: https://android-review.googlesource.com/1313840
Merged-In: I47b29c8525f3c0236e48b4bb8dbebb223e83bc31
Change-Id: I47b29c8525f3c0236e48b4bb8dbebb223e83bc31
diff --git a/libnetdutils/InternetAddresses.cpp b/libnetdutils/InternetAddresses.cpp
index 78d30b2..322f1b1 100644
--- a/libnetdutils/InternetAddresses.cpp
+++ b/libnetdutils/InternetAddresses.cpp
@@ -16,6 +16,8 @@
#include "netdutils/InternetAddresses.h"
+#include <string>
+
#include <android-base/stringprintf.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -123,6 +125,28 @@
return mData == empty;
}
+bool IPPrefix::forString(const std::string& repr, IPPrefix* prefix) {
+ size_t index = repr.find('/');
+ if (index == std::string::npos) return false;
+
+ // Parse the IP address.
+ IPAddress ip;
+ if (!IPAddress::forString(repr.substr(0, index), &ip)) return false;
+
+ // Parse the prefix length. Can't use base::ParseUint because it accepts non-base 10 input.
+ const char* prefixString = repr.c_str() + index + 1;
+ if (!isdigit(*prefixString)) return false;
+ char* endptr;
+ unsigned long prefixlen = strtoul(prefixString, &endptr, 10);
+ if (*endptr != '\0') return false;
+
+ uint8_t maxlen = (ip.family() == AF_INET) ? 32 : 128;
+ if (prefixlen > maxlen) return false;
+
+ *prefix = IPPrefix(ip, prefixlen);
+ return true;
+}
+
std::string IPPrefix::toString() const noexcept {
return StringPrintf("%s/%d", ip().toString().c_str(), mData.cidrlen);
}