ip_address.cc revision 55d9550e72197a203efbe06087edc2424676d886
1188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
21d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart// Use of this source code is governed by a BSD-style license that can be
31d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart// found in the LICENSE file.
41d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
58d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/ip_address.h"
61d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
72aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone#include <arpa/inet.h>
81d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart#include <netinet/in.h>
91d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
101d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart#include <string>
11f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart#include <vector>
121d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
138d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include <base/logging.h>
14a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_number_conversions.h>
15a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_split.h>
1614c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov
178d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/byte_string.h"
181d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
19188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewartusing std::string;
20f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartusing std::vector;
21188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart
221d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewartnamespace shill {
231d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
24f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartnamespace {
25f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartconst size_t kBitsPerByte = 8;
268a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko}  // namespace
27f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
282aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone// static
297355ce1937c504d836a303ac809bd436272212b3Paul Stewartconst IPAddress::Family IPAddress::kFamilyUnknown = AF_UNSPEC;
302aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone// static
317355ce1937c504d836a303ac809bd436272212b3Paul Stewartconst IPAddress::Family IPAddress::kFamilyIPv4 = AF_INET;
322aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone// static
337355ce1937c504d836a303ac809bd436272212b3Paul Stewartconst IPAddress::Family IPAddress::kFamilyIPv6 = AF_INET6;
342aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone
35f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
36f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartconst char IPAddress::kFamilyNameUnknown[] = "Unknown";
37f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
38f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartconst char IPAddress::kFamilyNameIPv4[] = "IPv4";
39f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
40f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartconst char IPAddress::kFamilyNameIPv6[] = "IPv6";
41f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart
421d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul StewartIPAddress::IPAddress(Family family, const ByteString &address)
431d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    : family_(family) ,
449e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      address_(address),
459e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      prefix_(0) {}
469e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart
479e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul StewartIPAddress::IPAddress(Family family,
489e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart                     const ByteString &address,
499e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart                     unsigned int prefix)
509e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart    : family_(family) ,
519e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      address_(address),
529e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      prefix_(prefix) {}
531d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
541d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul StewartIPAddress::IPAddress(Family family)
559e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart    : family_(family),
569e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart      prefix_(0) {}
571d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
58da775de010f64cf404c23632da4da0abce2ad2d8Samuel TanIPAddress::IPAddress(std::string ip_string)
59da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan    : prefix_(0) {
60da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan  family_ = IPAddress::kFamilyIPv4;
61da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan  if (!SetAddressFromString(ip_string)) {
62da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan    family_ = IPAddress::kFamilyIPv6;
63da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan    if (!SetAddressFromString(ip_string)) {
64da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan      family_ = IPAddress::kFamilyUnknown;
65da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan    }
66da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan  }
67da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan}
68da775de010f64cf404c23632da4da0abce2ad2d8Samuel Tan
691d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul StewartIPAddress::~IPAddress() {}
701d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
71f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
72c74cf9cb439ef518bc00210fe5cd3b121f3079b3Eric Shienbroodsize_t IPAddress::GetAddressLength(Family family) {
731d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  switch (family) {
747355ce1937c504d836a303ac809bd436272212b3Paul Stewart  case kFamilyIPv4:
751d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return sizeof(in_addr);
767355ce1937c504d836a303ac809bd436272212b3Paul Stewart  case kFamilyIPv6:
771d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return sizeof(in6_addr);
781d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  default:
791d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return 0;
801d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  }
811d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart}
821d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
8314c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov// static
8448100b0f484fb59d5f34eb4565375759202295e1Paul Stewartsize_t IPAddress::GetMaxPrefixLength(Family family) {
85f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return GetAddressLength(family) * kBitsPerByte;
86f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
87f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
88f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartsize_t IPAddress::GetMinPrefixLength() const {
89f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (family() != kFamilyIPv4) {
90f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    NOTIMPLEMENTED() << ": only implemented for IPv4";
91f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return GetMaxPrefixLength(family());
92f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
93f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
94f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK(IsValid());
95f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  in_addr_t address_val;
96f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  memcpy(&address_val, GetConstData(), sizeof(address_val));
97f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  // IN_CLASSx() macros operate on addresses in host-order.
98f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  address_val = ntohl(address_val);
99f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (IN_CLASSA(address_val)) {
100f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return GetMaxPrefixLength(family()) - IN_CLASSA_NSHIFT;
101f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  } else if (IN_CLASSB(address_val)) {
102f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return GetMaxPrefixLength(family()) - IN_CLASSB_NSHIFT;
103f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  } else if (IN_CLASSC(address_val)) {
104f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return GetMaxPrefixLength(family()) - IN_CLASSC_NSHIFT;
105f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
106f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
107f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  LOG(ERROR) << "Invalid IPv4 address class";
108f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return GetMaxPrefixLength(family());
10948100b0f484fb59d5f34eb4565375759202295e1Paul Stewart}
11048100b0f484fb59d5f34eb4565375759202295e1Paul Stewart
11148100b0f484fb59d5f34eb4565375759202295e1Paul Stewart// static
1123e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodsize_t IPAddress::GetPrefixLengthFromMask(Family family, const string &mask) {
11314c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov  switch (family) {
11414c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov    case kFamilyIPv4: {
11514c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      in_addr_t mask_val = inet_network(mask.c_str());
11648100b0f484fb59d5f34eb4565375759202295e1Paul Stewart      int subnet_prefix = 0;
11714c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      while (mask_val) {
11848100b0f484fb59d5f34eb4565375759202295e1Paul Stewart        subnet_prefix++;
11914c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov        mask_val <<= 1;
12014c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      }
12148100b0f484fb59d5f34eb4565375759202295e1Paul Stewart      return subnet_prefix;
12214c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov    }
12314c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov    case kFamilyIPv6:
12414c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      NOTIMPLEMENTED();
12514c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      break;
12614c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov    default:
12714c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      LOG(WARNING) << "Unexpected address family: " << family;
12814c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov      break;
12914c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov  }
13014c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov  return 0;
13114c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov}
13214c29ec4815e8ecda47b7ce5efdaa444580e20ceDarin Petkov
133f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// static
134f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul StewartIPAddress IPAddress::GetAddressMaskFromPrefix(Family family, size_t prefix) {
135f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  ByteString address_bytes(GetAddressLength(family));
136f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  unsigned char *address_ptr = address_bytes.GetData();
137f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
138f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  size_t bits = prefix;
139f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (bits > GetMaxPrefixLength(family)) {
140f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    bits = GetMaxPrefixLength(family);
141f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
142f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
143f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  while (bits > kBitsPerByte) {
144f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    bits -= kBitsPerByte;
145f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    *address_ptr++ = kuint8max;
146f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
147f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
148f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  // We are guaranteed to be before the end of the address data since even
149f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  // if the prefix is the maximum, the loop above will end before we assign
150f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  // and increment past the last byte.
151f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  *address_ptr = ~((1 << (kBitsPerByte - bits)) - 1);
152f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
153f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return IPAddress(family, address_bytes);
154f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
155f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
156f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart// static
157f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartstring IPAddress::GetAddressFamilyName(Family family) {
158f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  switch (family) {
159f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  case kFamilyIPv4:
160f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    return kFamilyNameIPv4;
161f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  case kFamilyIPv6:
162f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    return kFamilyNameIPv6;
163f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  default:
164f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    return kFamilyNameUnknown;
165f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  }
166f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart}
167f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart
168188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewartbool IPAddress::SetAddressFromString(const string &address_string) {
169c74cf9cb439ef518bc00210fe5cd3b121f3079b3Eric Shienbrood  size_t address_length = GetAddressLength(family_);
1701d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
1711d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  if (!address_length) {
1721d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return false;
1731d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  }
1741d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
1751d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  ByteString address(address_length);
1761d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  if (inet_pton(family_, address_string.c_str(), address.GetData()) <= 0) {
1771d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart    return false;
1781d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  }
1791d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  address_ = address;
1801d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  return true;
1811d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart}
1821d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
183f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewartbool IPAddress::SetAddressAndPrefixFromString(const string &address_string) {
184f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  vector<string> address_parts;
185f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  base::SplitString(address_string, '/', &address_parts);
186f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (address_parts.size() != 2) {
187f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    LOG(ERROR) << "Cannot split address " << address_string;
188f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return false;
189f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
190f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  if (!SetAddressFromString(address_parts[0])) {
191f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    LOG(ERROR) << "Cannot parse address string " << address_parts[0];
192f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return false;
193f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
194762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi  size_t prefix;
195762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi  if (!base::StringToSizeT(address_parts[1], &prefix) ||
196762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi      prefix > GetMaxPrefixLength(family_)) {
197f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    LOG(ERROR) << "Cannot parse address prefix " << address_parts[1];
198f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart    return false;
199f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  }
200f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  set_prefix(prefix);
201f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return true;
202f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
203f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
2041d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewartvoid IPAddress::SetAddressToDefault() {
2051d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart  address_ = ByteString(GetAddressLength(family_));
2061d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart}
2071d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart
2082c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawalbool IPAddress::IntoString(string *address_string) const {
209188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  // Noting that INET6_ADDRSTRLEN > INET_ADDRSTRLEN
210188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  char address_buf[INET6_ADDRSTRLEN];
211188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  if (GetLength() != GetAddressLength(family_) ||
212188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart      !inet_ntop(family_, GetConstData(), address_buf, sizeof(address_buf))) {
213188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart    return false;
214188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  }
215188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  *address_string = address_buf;
216188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart  return true;
217188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart}
218188a84a6f75dcadb972bc33bafa00c6ba7f3bbd6Paul Stewart
2192c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawalstring IPAddress::ToString() const {
2202c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal  string out("<unknown>");
2212c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal  IntoString(&out);
2222c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal  return out;
2232c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal}
2242c15d2c7ae814d95673ea48ec8f4eb582ef3652emukesh agrawal
22555d9550e72197a203efbe06087edc2424676d886Paul Stewartbool IPAddress::Equals(const IPAddress &b) const {
22655d9550e72197a203efbe06087edc2424676d886Paul Stewart  return family_ == b.family_ && address_.Equals(b.address_) &&
22755d9550e72197a203efbe06087edc2424676d886Paul Stewart      prefix_ == b.prefix_;
22855d9550e72197a203efbe06087edc2424676d886Paul Stewart}
22955d9550e72197a203efbe06087edc2424676d886Paul Stewart
23055d9550e72197a203efbe06087edc2424676d886Paul Stewartbool IPAddress::HasSameAddressAs(const IPAddress &b) const {
23155d9550e72197a203efbe06087edc2424676d886Paul Stewart  return family_ == b.family_ && address_.Equals(b.address_);
23255d9550e72197a203efbe06087edc2424676d886Paul Stewart}
23355d9550e72197a203efbe06087edc2424676d886Paul Stewart
2344a6748d492214afcb7c484668fa8cfd3ad963f10Paul StewartIPAddress IPAddress::MaskWith(const IPAddress &b) const {
235f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK(IsValid());
236f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK(b.IsValid());
237f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK_EQ(family(), b.family());
238f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
239f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  ByteString address_bytes(address());
240fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  address_bytes.BitwiseAnd(b.address());
241fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart
242fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  return IPAddress(family(), address_bytes);
243fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart}
244fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart
2454a6748d492214afcb7c484668fa8cfd3ad963f10Paul StewartIPAddress IPAddress::MergeWith(const IPAddress &b) const {
246fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  CHECK(IsValid());
247fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  CHECK(b.IsValid());
248fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  CHECK_EQ(family(), b.family());
249fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart
250fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  ByteString address_bytes(address());
251fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  address_bytes.BitwiseOr(b.address());
252f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
253f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return IPAddress(family(), address_bytes);
254f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
255f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
2564a6748d492214afcb7c484668fa8cfd3ad963f10Paul StewartIPAddress IPAddress::GetNetworkPart() const {
257f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return MaskWith(GetAddressMaskFromPrefix(family(), prefix()));
258f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
259f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
260fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul StewartIPAddress IPAddress::GetDefaultBroadcast() {
261fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  ByteString broadcast_bytes(
262fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart    GetAddressMaskFromPrefix(family(), prefix()).address());
263fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  broadcast_bytes.BitwiseInvert();
264fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart  return MergeWith(IPAddress(family(), broadcast_bytes));
265fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart}
266fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart
2674a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewartbool IPAddress::CanReachAddress(const IPAddress &b) const {
268f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  CHECK_EQ(family(), b.family());
269f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  IPAddress b_prefixed(b);
270f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  b_prefixed.set_prefix(prefix());
271f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart  return GetNetworkPart().Equals(b_prefixed.GetNetworkPart());
272f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart}
273f7bf9bf2d7cb7fe7ebf98c7a575a267c190f6ec1Paul Stewart
2741d18e8cd593cc8dce91a6faabe2f0cae700b7e38Paul Stewart}  // namespace shill
275