321 lines
8.9 KiB
C++
321 lines
8.9 KiB
C++
//
|
|
// Copyright (C) 2012 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include "shill/net/ip_address.h"
|
|
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <base/logging.h>
|
|
#include <base/strings/string_number_conversions.h>
|
|
#include <base/strings/string_split.h>
|
|
|
|
#include "shill/net/byte_string.h"
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
namespace shill {
|
|
|
|
namespace {
|
|
const size_t kBitsPerByte = 8;
|
|
} // namespace
|
|
|
|
// static
|
|
const IPAddress::Family IPAddress::kFamilyUnknown = AF_UNSPEC;
|
|
// static
|
|
const IPAddress::Family IPAddress::kFamilyIPv4 = AF_INET;
|
|
// static
|
|
const IPAddress::Family IPAddress::kFamilyIPv6 = AF_INET6;
|
|
|
|
// static
|
|
const char IPAddress::kFamilyNameUnknown[] = "Unknown";
|
|
// static
|
|
const char IPAddress::kFamilyNameIPv4[] = "IPv4";
|
|
// static
|
|
const char IPAddress::kFamilyNameIPv6[] = "IPv6";
|
|
|
|
IPAddress::IPAddress(Family family, const ByteString& address)
|
|
: family_(family) ,
|
|
address_(address),
|
|
prefix_(0) {}
|
|
|
|
IPAddress::IPAddress(Family family,
|
|
const ByteString& address,
|
|
unsigned int prefix)
|
|
: family_(family) ,
|
|
address_(address),
|
|
prefix_(prefix) {}
|
|
|
|
IPAddress::IPAddress(Family family)
|
|
: family_(family),
|
|
prefix_(0) {}
|
|
|
|
IPAddress::IPAddress(std::string ip_string)
|
|
: prefix_(0) {
|
|
family_ = IPAddress::kFamilyIPv4;
|
|
if (!SetAddressFromString(ip_string)) {
|
|
family_ = IPAddress::kFamilyIPv6;
|
|
if (!SetAddressFromString(ip_string)) {
|
|
family_ = IPAddress::kFamilyUnknown;
|
|
}
|
|
}
|
|
}
|
|
|
|
IPAddress::IPAddress(const sockaddr* address_struct, size_t size)
|
|
: family_(kFamilyUnknown),
|
|
prefix_(0) {
|
|
if (address_struct->sa_family == kFamilyIPv4 && size >= sizeof(sockaddr_in)) {
|
|
family_ = address_struct->sa_family;
|
|
auto sin = reinterpret_cast<const sockaddr_in*>(address_struct);
|
|
// Preserve network byte order of s_addr.
|
|
auto bytes = reinterpret_cast<const uint8_t*>(&sin->sin_addr.s_addr);
|
|
address_ = ByteString(bytes, sizeof(sin->sin_addr.s_addr));
|
|
} else if (address_struct->sa_family == kFamilyIPv6 &&
|
|
size >= sizeof(sockaddr_in6)) {
|
|
family_ = address_struct->sa_family;
|
|
auto sin6 = reinterpret_cast<const sockaddr_in6*>(address_struct);
|
|
address_ = ByteString(sin6->sin6_addr.s6_addr,
|
|
sizeof(sin6->sin6_addr.s6_addr));
|
|
}
|
|
}
|
|
|
|
IPAddress::~IPAddress() {}
|
|
|
|
// static
|
|
size_t IPAddress::GetAddressLength(Family family) {
|
|
switch (family) {
|
|
case kFamilyIPv4:
|
|
return sizeof(in_addr);
|
|
case kFamilyIPv6:
|
|
return sizeof(in6_addr);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// static
|
|
size_t IPAddress::GetMaxPrefixLength(Family family) {
|
|
return GetAddressLength(family) * kBitsPerByte;
|
|
}
|
|
|
|
size_t IPAddress::GetMinPrefixLength() const {
|
|
if (family() != kFamilyIPv4) {
|
|
NOTIMPLEMENTED() << ": only implemented for IPv4";
|
|
return GetMaxPrefixLength(family());
|
|
}
|
|
|
|
CHECK(IsValid());
|
|
in_addr_t address_val;
|
|
memcpy(&address_val, GetConstData(), sizeof(address_val));
|
|
// IN_CLASSx() macros operate on addresses in host-order.
|
|
address_val = ntohl(address_val);
|
|
if (IN_CLASSA(address_val)) {
|
|
return GetMaxPrefixLength(family()) - IN_CLASSA_NSHIFT;
|
|
} else if (IN_CLASSB(address_val)) {
|
|
return GetMaxPrefixLength(family()) - IN_CLASSB_NSHIFT;
|
|
} else if (IN_CLASSC(address_val)) {
|
|
return GetMaxPrefixLength(family()) - IN_CLASSC_NSHIFT;
|
|
}
|
|
|
|
LOG(ERROR) << "Invalid IPv4 address class";
|
|
return GetMaxPrefixLength(family());
|
|
}
|
|
|
|
// static
|
|
size_t IPAddress::GetPrefixLengthFromMask(Family family, const string& mask) {
|
|
switch (family) {
|
|
case kFamilyIPv4: {
|
|
in_addr_t mask_val = inet_network(mask.c_str());
|
|
int subnet_prefix = 0;
|
|
while (mask_val) {
|
|
subnet_prefix++;
|
|
mask_val <<= 1;
|
|
}
|
|
return subnet_prefix;
|
|
}
|
|
case kFamilyIPv6:
|
|
NOTIMPLEMENTED();
|
|
break;
|
|
default:
|
|
LOG(WARNING) << "Unexpected address family: " << family;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// static
|
|
IPAddress IPAddress::GetAddressMaskFromPrefix(Family family, size_t prefix) {
|
|
ByteString address_bytes(GetAddressLength(family));
|
|
unsigned char* address_ptr = address_bytes.GetData();
|
|
|
|
size_t bits = prefix;
|
|
if (bits > GetMaxPrefixLength(family)) {
|
|
bits = GetMaxPrefixLength(family);
|
|
}
|
|
|
|
while (bits > kBitsPerByte) {
|
|
bits -= kBitsPerByte;
|
|
*address_ptr++ = std::numeric_limits<uint8_t>::max();
|
|
}
|
|
|
|
// We are guaranteed to be before the end of the address data since even
|
|
// if the prefix is the maximum, the loop above will end before we assign
|
|
// and increment past the last byte.
|
|
*address_ptr = ~((1 << (kBitsPerByte - bits)) - 1);
|
|
|
|
return IPAddress(family, address_bytes);
|
|
}
|
|
|
|
// static
|
|
string IPAddress::GetAddressFamilyName(Family family) {
|
|
switch (family) {
|
|
case kFamilyIPv4:
|
|
return kFamilyNameIPv4;
|
|
case kFamilyIPv6:
|
|
return kFamilyNameIPv6;
|
|
default:
|
|
return kFamilyNameUnknown;
|
|
}
|
|
}
|
|
|
|
bool IPAddress::SetAddressFromString(const string& address_string) {
|
|
size_t address_length = GetAddressLength(family_);
|
|
|
|
if (!address_length) {
|
|
return false;
|
|
}
|
|
|
|
ByteString address(address_length);
|
|
if (inet_pton(family_, address_string.c_str(), address.GetData()) <= 0) {
|
|
return false;
|
|
}
|
|
address_ = address;
|
|
return true;
|
|
}
|
|
|
|
bool IPAddress::SetAddressAndPrefixFromString(const string& address_string) {
|
|
vector<string> address_parts = base::SplitString(
|
|
address_string, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
|
if (address_parts.size() != 2) {
|
|
LOG(ERROR) << "Cannot split address " << address_string;
|
|
return false;
|
|
}
|
|
if (!SetAddressFromString(address_parts[0])) {
|
|
LOG(ERROR) << "Cannot parse address string " << address_parts[0];
|
|
return false;
|
|
}
|
|
size_t prefix;
|
|
if (!base::StringToSizeT(address_parts[1], &prefix) ||
|
|
prefix > GetMaxPrefixLength(family_)) {
|
|
LOG(ERROR) << "Cannot parse address prefix " << address_parts[1];
|
|
return false;
|
|
}
|
|
set_prefix(prefix);
|
|
return true;
|
|
}
|
|
|
|
void IPAddress::SetAddressToDefault() {
|
|
address_ = ByteString(GetAddressLength(family_));
|
|
}
|
|
|
|
bool IPAddress::IntoString(string* address_string) const {
|
|
// Noting that INET6_ADDRSTRLEN > INET_ADDRSTRLEN
|
|
char address_buf[INET6_ADDRSTRLEN];
|
|
if (GetLength() != GetAddressLength(family_) ||
|
|
!inet_ntop(family_, GetConstData(), address_buf, sizeof(address_buf))) {
|
|
return false;
|
|
}
|
|
*address_string = address_buf;
|
|
return true;
|
|
}
|
|
|
|
string IPAddress::ToString() const {
|
|
string out("<unknown>");
|
|
IntoString(&out);
|
|
return out;
|
|
}
|
|
|
|
bool IPAddress::IntoSockAddr(sockaddr* address_struct, size_t size) const {
|
|
if (!IsValid()) {
|
|
return false;
|
|
}
|
|
if (family_ == kFamilyIPv4 && size >= sizeof(sockaddr_in)) {
|
|
auto sin = reinterpret_cast<sockaddr_in*>(address_struct);
|
|
memcpy(&sin->sin_addr.s_addr, GetConstData(), GetLength());
|
|
} else if (family_ == kFamilyIPv6 && size >= sizeof(sockaddr_in6)) {
|
|
auto sin6 = reinterpret_cast<sockaddr_in6*>(address_struct);
|
|
memcpy(&sin6->sin6_addr.s6_addr, GetConstData(), GetLength());
|
|
} else {
|
|
return false;
|
|
}
|
|
address_struct->sa_family = family_;
|
|
return true;
|
|
}
|
|
|
|
bool IPAddress::Equals(const IPAddress& b) const {
|
|
return family_ == b.family_ && address_.Equals(b.address_) &&
|
|
prefix_ == b.prefix_;
|
|
}
|
|
|
|
bool IPAddress::HasSameAddressAs(const IPAddress& b) const {
|
|
return family_ == b.family_ && address_.Equals(b.address_);
|
|
}
|
|
|
|
IPAddress IPAddress::MaskWith(const IPAddress& b) const {
|
|
CHECK(IsValid());
|
|
CHECK(b.IsValid());
|
|
CHECK_EQ(family(), b.family());
|
|
|
|
ByteString address_bytes(address());
|
|
address_bytes.BitwiseAnd(b.address());
|
|
|
|
return IPAddress(family(), address_bytes);
|
|
}
|
|
|
|
IPAddress IPAddress::MergeWith(const IPAddress& b) const {
|
|
CHECK(IsValid());
|
|
CHECK(b.IsValid());
|
|
CHECK_EQ(family(), b.family());
|
|
|
|
ByteString address_bytes(address());
|
|
address_bytes.BitwiseOr(b.address());
|
|
|
|
return IPAddress(family(), address_bytes);
|
|
}
|
|
|
|
IPAddress IPAddress::GetNetworkPart() const {
|
|
return MaskWith(GetAddressMaskFromPrefix(family(), prefix()));
|
|
}
|
|
|
|
IPAddress IPAddress::GetDefaultBroadcast() {
|
|
ByteString broadcast_bytes(
|
|
GetAddressMaskFromPrefix(family(), prefix()).address());
|
|
broadcast_bytes.BitwiseInvert();
|
|
return MergeWith(IPAddress(family(), broadcast_bytes));
|
|
}
|
|
|
|
bool IPAddress::CanReachAddress(const IPAddress& b) const {
|
|
CHECK_EQ(family(), b.family());
|
|
IPAddress b_prefixed(b);
|
|
b_prefixed.set_prefix(prefix());
|
|
return GetNetworkPart().Equals(b_prefixed.GetNetworkPart());
|
|
}
|
|
|
|
} // namespace shill
|