1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project
3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License.
6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at
7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software
11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and
14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License.
15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
161d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
178d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/ip_address.h"
181d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
192aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone#include <arpa/inet.h>
201d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart#include <netinet/in.h>
211d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
221d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart#include <string>
23f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart#include <vector>
241d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
258d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include <base/logging.h>
26a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_number_conversions.h>
27a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_split.h>
2814c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov
298d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/byte_string.h"
301d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
31188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewartusing std::string;
32f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartusing std::vector;
33188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart
341d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewartnamespace shill {
351d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
36f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartnamespace {
37f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartconst size_t kBitsPerByte = 8;
388a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko}  // namespace
39f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
402aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone// static
417355ce1937c504d836a303ac809bd436272212b3Paul Stewartconst IPAddress::Family IPAddress::kFamilyUnknown = AF_UNSPEC;
422aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone// static
437355ce1937c504d836a303ac809bd436272212b3Paul Stewartconst IPAddress::Family IPAddress::kFamilyIPv4 = AF_INET;
442aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone// static
457355ce1937c504d836a303ac809bd436272212b3Paul Stewartconst IPAddress::Family IPAddress::kFamilyIPv6 = AF_INET6;
462aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone
47f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
48f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartconst char IPAddress::kFamilyNameUnknown[] = "Unknown";
49f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
50f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartconst char IPAddress::kFamilyNameIPv4[] = "IPv4";
51f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
52f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartconst char IPAddress::kFamilyNameIPv6[] = "IPv6";
53f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart
54e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul StewartIPAddress::IPAddress(Family family, const ByteString& address)
551d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    : family_(family) ,
569e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      address_(address),
579e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      prefix_(0) {}
589e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart
599e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul StewartIPAddress::IPAddress(Family family,
60e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart                     const ByteString& address,
619e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart                     unsigned int prefix)
629e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart    : family_(family) ,
639e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      address_(address),
649e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      prefix_(prefix) {}
651d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
661d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul StewartIPAddress::IPAddress(Family family)
679e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart    : family_(family),
689e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      prefix_(0) {}
691d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
70da775de010f64cf404c23632da4da0abce2ad2d8Samuel TanIPAddress::IPAddress(std::string ip_string)
71da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan    : prefix_(0) {
72da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan  family_ = IPAddress::kFamilyIPv4;
73da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan  if (!SetAddressFromString(ip_string)) {
74da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan    family_ = IPAddress::kFamilyIPv6;
75da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan    if (!SetAddressFromString(ip_string)) {
76da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan      family_ = IPAddress::kFamilyUnknown;
77da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan    }
78da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan  }
79da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan}
80da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan
81b3953b8fa428c46b48598396d2a8270a85934f72Christopher GrantIPAddress::IPAddress(const sockaddr* address_struct, size_t size)
82b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    : family_(kFamilyUnknown),
83b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant      prefix_(0) {
84b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  if (address_struct->sa_family == kFamilyIPv4 && size >= sizeof(sockaddr_in)) {
85b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    family_ = address_struct->sa_family;
86b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    auto sin = reinterpret_cast<const sockaddr_in*>(address_struct);
87b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    // Preserve network byte order of s_addr.
88b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    auto bytes = reinterpret_cast<const uint8_t*>(&sin->sin_addr.s_addr);
89b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    address_ = ByteString(bytes, sizeof(sin->sin_addr.s_addr));
90b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  } else if (address_struct->sa_family == kFamilyIPv6 &&
91b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant             size >= sizeof(sockaddr_in6)) {
92b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    family_ = address_struct->sa_family;
93b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    auto sin6 = reinterpret_cast<const sockaddr_in6*>(address_struct);
94b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    address_ = ByteString(sin6->sin6_addr.s6_addr,
95b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant                          sizeof(sin6->sin6_addr.s6_addr));
96b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  }
97b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant}
98b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant
991d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul StewartIPAddress::~IPAddress() {}
1001d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
101f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
102c74cf9cb439ef518bc00210fe5cd3b121f3079b3Eric Shienbroodsize_t IPAddress::GetAddressLength(Family family) {
1031d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  switch (family) {
1047355ce1937c504d836a303ac809bd436272212b3Paul Stewart  case kFamilyIPv4:
1051d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return sizeof(in_addr);
1067355ce1937c504d836a303ac809bd436272212b3Paul Stewart  case kFamilyIPv6:
1071d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return sizeof(in6_addr);
1081d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  default:
1091d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return 0;
1101d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  }
1111d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart}
1121d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
11314c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov// static
11448100b0f484fb59d5f34eb4565375759202295e1Paul Stewartsize_t IPAddress::GetMaxPrefixLength(Family family) {
115f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return GetAddressLength(family) * kBitsPerByte;
116f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
117f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
118f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartsize_t IPAddress::GetMinPrefixLength() const {
119f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (family() != kFamilyIPv4) {
120f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    NOTIMPLEMENTED() << ": only implemented for IPv4";
121f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return GetMaxPrefixLength(family());
122f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
123f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
124f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK(IsValid());
125f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  in_addr_t address_val;
126f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  memcpy(&address_val, GetConstData(), sizeof(address_val));
127f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  // IN_CLASSx() macros operate on addresses in host-order.
128f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  address_val = ntohl(address_val);
129f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (IN_CLASSA(address_val)) {
130f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return GetMaxPrefixLength(family()) - IN_CLASSA_NSHIFT;
131f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  } else if (IN_CLASSB(address_val)) {
132f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return GetMaxPrefixLength(family()) - IN_CLASSB_NSHIFT;
133f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  } else if (IN_CLASSC(address_val)) {
134f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return GetMaxPrefixLength(family()) - IN_CLASSC_NSHIFT;
135f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
136f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
137f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  LOG(ERROR) << "Invalid IPv4 address class";
138f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return GetMaxPrefixLength(family());
13948100b0f484fb59d5f34eb4565375759202295e1Paul Stewart}
14048100b0f484fb59d5f34eb4565375759202295e1Paul Stewart
14148100b0f484fb59d5f34eb4565375759202295e1Paul Stewart// static
142e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartsize_t IPAddress::GetPrefixLengthFromMask(Family family, const string& mask) {
14314c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov  switch (family) {
14414c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov    case kFamilyIPv4: {
14514c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      in_addr_t mask_val = inet_network(mask.c_str());
14648100b0f484fb59d5f34eb4565375759202295e1Paul Stewart      int subnet_prefix = 0;
14714c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      while (mask_val) {
14848100b0f484fb59d5f34eb4565375759202295e1Paul Stewart        subnet_prefix++;
14914c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov        mask_val <<= 1;
15014c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      }
15148100b0f484fb59d5f34eb4565375759202295e1Paul Stewart      return subnet_prefix;
15214c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov    }
15314c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov    case kFamilyIPv6:
15414c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      NOTIMPLEMENTED();
15514c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      break;
15614c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov    default:
15714c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      LOG(WARNING) << "Unexpected address family: " << family;
15814c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      break;
15914c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov  }
16014c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov  return 0;
16114c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov}
16214c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov
163f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
164f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul StewartIPAddress IPAddress::GetAddressMaskFromPrefix(Family family, size_t prefix) {
165f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  ByteString address_bytes(GetAddressLength(family));
166e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart  unsigned char* address_ptr = address_bytes.GetData();
167f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
168f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  size_t bits = prefix;
169f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (bits > GetMaxPrefixLength(family)) {
170f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    bits = GetMaxPrefixLength(family);
171f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
172f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
173f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  while (bits > kBitsPerByte) {
174f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    bits -= kBitsPerByte;
1753a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko    *address_ptr++ = std::numeric_limits<uint8_t>::max();
176f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
177f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
178f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  // We are guaranteed to be before the end of the address data since even
179f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  // if the prefix is the maximum, the loop above will end before we assign
180f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  // and increment past the last byte.
181f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  *address_ptr = ~((1 << (kBitsPerByte - bits)) - 1);
182f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
183f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return IPAddress(family, address_bytes);
184f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
185f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
186f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart// static
187f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartstring IPAddress::GetAddressFamilyName(Family family) {
188f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  switch (family) {
189f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  case kFamilyIPv4:
190f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    return kFamilyNameIPv4;
191f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  case kFamilyIPv6:
192f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    return kFamilyNameIPv6;
193f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  default:
194f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    return kFamilyNameUnknown;
195f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  }
196f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart}
197f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart
198e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool IPAddress::SetAddressFromString(const string& address_string) {
199c74cf9cb439ef518bc00210fe5cd3b121f3079b3Eric Shienbrood  size_t address_length = GetAddressLength(family_);
2001d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
2011d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  if (!address_length) {
2021d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return false;
2031d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  }
2041d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
2051d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  ByteString address(address_length);
2061d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  if (inet_pton(family_, address_string.c_str(), address.GetData()) <= 0) {
2071d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return false;
2081d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  }
2091d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  address_ = address;
2101d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  return true;
2111d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart}
2121d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
213e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool IPAddress::SetAddressAndPrefixFromString(const string& address_string) {
2143a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko  vector<string> address_parts = base::SplitString(
2153a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko      address_string, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
216f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (address_parts.size() != 2) {
217f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    LOG(ERROR) << "Cannot split address " << address_string;
218f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return false;
219f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
220f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (!SetAddressFromString(address_parts[0])) {
221f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    LOG(ERROR) << "Cannot parse address string " << address_parts[0];
222f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return false;
223f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
224762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi  size_t prefix;
225762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi  if (!base::StringToSizeT(address_parts[1], &prefix) ||
226762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi      prefix > GetMaxPrefixLength(family_)) {
227f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    LOG(ERROR) << "Cannot parse address prefix " << address_parts[1];
228f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return false;
229f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
230f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  set_prefix(prefix);
231f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return true;
232f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
233f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
2341d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewartvoid IPAddress::SetAddressToDefault() {
2351d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  address_ = ByteString(GetAddressLength(family_));
2361d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart}
2371d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
238e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool IPAddress::IntoString(string* address_string) const {
239188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  // Noting that INET6_ADDRSTRLEN > INET_ADDRSTRLEN
240188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  char address_buf[INET6_ADDRSTRLEN];
241188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  if (GetLength() != GetAddressLength(family_) ||
242188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart      !inet_ntop(family_, GetConstData(), address_buf, sizeof(address_buf))) {
243188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart    return false;
244188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  }
245188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  *address_string = address_buf;
246188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  return true;
247188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart}
248188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart
2492c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawalstring IPAddress::ToString() const {
2502c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal  string out("<unknown>");
2512c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal  IntoString(&out);
2522c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal  return out;
2532c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal}
2542c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal
255b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grantbool IPAddress::IntoSockAddr(sockaddr* address_struct, size_t size) const {
256b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  if (!IsValid()) {
257b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    return false;
258b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  }
259b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  if (family_ == kFamilyIPv4 && size >= sizeof(sockaddr_in)) {
260b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    auto sin = reinterpret_cast<sockaddr_in*>(address_struct);
261b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    memcpy(&sin->sin_addr.s_addr, GetConstData(), GetLength());
262b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  } else if (family_ == kFamilyIPv6 && size >= sizeof(sockaddr_in6)) {
263b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    auto sin6 = reinterpret_cast<sockaddr_in6*>(address_struct);
264b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    memcpy(&sin6->sin6_addr.s6_addr, GetConstData(), GetLength());
265b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  } else {
266b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant    return false;
267b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  }
268b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  address_struct->sa_family = family_;
269b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant  return true;
270b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant}
271b3953b8fa428c46b48598396d2a8270a85934f72Christopher Grant
272e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool IPAddress::Equals(const IPAddress& b) const {
27355d9550e72197a203efbe06087edc2424676d886Paul Stewart  return family_ == b.family_ && address_.Equals(b.address_) &&
27455d9550e72197a203efbe06087edc2424676d886Paul Stewart      prefix_ == b.prefix_;
27555d9550e72197a203efbe06087edc2424676d886Paul Stewart}
27655d9550e72197a203efbe06087edc2424676d886Paul Stewart
277e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool IPAddress::HasSameAddressAs(const IPAddress& b) const {
27855d9550e72197a203efbe06087edc2424676d886Paul Stewart  return family_ == b.family_ && address_.Equals(b.address_);
27955d9550e72197a203efbe06087edc2424676d886Paul Stewart}
28055d9550e72197a203efbe06087edc2424676d886Paul Stewart
281e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul StewartIPAddress IPAddress::MaskWith(const IPAddress& b) const {
282f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK(IsValid());
283f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK(b.IsValid());
284f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK_EQ(family(), b.family());
285f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
286f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  ByteString address_bytes(address());
287fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  address_bytes.BitwiseAnd(b.address());
288fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart
289fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  return IPAddress(family(), address_bytes);
290fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart}
291fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart
292e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul StewartIPAddress IPAddress::MergeWith(const IPAddress& b) const {
293fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  CHECK(IsValid());
294fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  CHECK(b.IsValid());
295fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  CHECK_EQ(family(), b.family());
296fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart
297fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  ByteString address_bytes(address());
298fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  address_bytes.BitwiseOr(b.address());
299f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
300f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return IPAddress(family(), address_bytes);
301f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
302f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
3034a6748d492214afcb7c484668fa8cfd3ad963f10Paul StewartIPAddress IPAddress::GetNetworkPart() const {
304f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return MaskWith(GetAddressMaskFromPrefix(family(), prefix()));
305f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
306f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
307fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul StewartIPAddress IPAddress::GetDefaultBroadcast() {
308fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  ByteString broadcast_bytes(
309fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart    GetAddressMaskFromPrefix(family(), prefix()).address());
310fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  broadcast_bytes.BitwiseInvert();
311fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  return MergeWith(IPAddress(family(), broadcast_bytes));
312fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart}
313fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart
314e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool IPAddress::CanReachAddress(const IPAddress& b) const {
315f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK_EQ(family(), b.family());
316f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  IPAddress b_prefixed(b);
317f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  b_prefixed.set_prefix(prefix());
318f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return GetNetworkPart().Equals(b_prefixed.GetNetworkPart());
319f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
320f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
3211d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart}  // namespace shill
322