ip_address.cc revision e67a78539a05ea7fc68ed5ca18f6d1de333a3086
1// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/net/ip_address.h"
6
7#include <arpa/inet.h>
8#include <netinet/in.h>
9
10#include <string>
11#include <vector>
12
13#include <base/logging.h>
14#include <base/strings/string_number_conversions.h>
15#include <base/strings/string_split.h>
16
17#include "shill/net/byte_string.h"
18
19using std::string;
20using std::vector;
21
22namespace shill {
23
24namespace {
25const size_t kBitsPerByte = 8;
26}  // namespace
27
28// static
29const IPAddress::Family IPAddress::kFamilyUnknown = AF_UNSPEC;
30// static
31const IPAddress::Family IPAddress::kFamilyIPv4 = AF_INET;
32// static
33const IPAddress::Family IPAddress::kFamilyIPv6 = AF_INET6;
34
35// static
36const char IPAddress::kFamilyNameUnknown[] = "Unknown";
37// static
38const char IPAddress::kFamilyNameIPv4[] = "IPv4";
39// static
40const char IPAddress::kFamilyNameIPv6[] = "IPv6";
41
42IPAddress::IPAddress(Family family, const ByteString& address)
43    : family_(family) ,
44      address_(address),
45      prefix_(0) {}
46
47IPAddress::IPAddress(Family family,
48                     const ByteString& address,
49                     unsigned int prefix)
50    : family_(family) ,
51      address_(address),
52      prefix_(prefix) {}
53
54IPAddress::IPAddress(Family family)
55    : family_(family),
56      prefix_(0) {}
57
58IPAddress::IPAddress(std::string ip_string)
59    : prefix_(0) {
60  family_ = IPAddress::kFamilyIPv4;
61  if (!SetAddressFromString(ip_string)) {
62    family_ = IPAddress::kFamilyIPv6;
63    if (!SetAddressFromString(ip_string)) {
64      family_ = IPAddress::kFamilyUnknown;
65    }
66  }
67}
68
69IPAddress::~IPAddress() {}
70
71// static
72size_t IPAddress::GetAddressLength(Family family) {
73  switch (family) {
74  case kFamilyIPv4:
75    return sizeof(in_addr);
76  case kFamilyIPv6:
77    return sizeof(in6_addr);
78  default:
79    return 0;
80  }
81}
82
83// static
84size_t IPAddress::GetMaxPrefixLength(Family family) {
85  return GetAddressLength(family) * kBitsPerByte;
86}
87
88size_t IPAddress::GetMinPrefixLength() const {
89  if (family() != kFamilyIPv4) {
90    NOTIMPLEMENTED() << ": only implemented for IPv4";
91    return GetMaxPrefixLength(family());
92  }
93
94  CHECK(IsValid());
95  in_addr_t address_val;
96  memcpy(&address_val, GetConstData(), sizeof(address_val));
97  // IN_CLASSx() macros operate on addresses in host-order.
98  address_val = ntohl(address_val);
99  if (IN_CLASSA(address_val)) {
100    return GetMaxPrefixLength(family()) - IN_CLASSA_NSHIFT;
101  } else if (IN_CLASSB(address_val)) {
102    return GetMaxPrefixLength(family()) - IN_CLASSB_NSHIFT;
103  } else if (IN_CLASSC(address_val)) {
104    return GetMaxPrefixLength(family()) - IN_CLASSC_NSHIFT;
105  }
106
107  LOG(ERROR) << "Invalid IPv4 address class";
108  return GetMaxPrefixLength(family());
109}
110
111// static
112size_t IPAddress::GetPrefixLengthFromMask(Family family, const string& mask) {
113  switch (family) {
114    case kFamilyIPv4: {
115      in_addr_t mask_val = inet_network(mask.c_str());
116      int subnet_prefix = 0;
117      while (mask_val) {
118        subnet_prefix++;
119        mask_val <<= 1;
120      }
121      return subnet_prefix;
122    }
123    case kFamilyIPv6:
124      NOTIMPLEMENTED();
125      break;
126    default:
127      LOG(WARNING) << "Unexpected address family: " << family;
128      break;
129  }
130  return 0;
131}
132
133// static
134IPAddress IPAddress::GetAddressMaskFromPrefix(Family family, size_t prefix) {
135  ByteString address_bytes(GetAddressLength(family));
136  unsigned char* address_ptr = address_bytes.GetData();
137
138  size_t bits = prefix;
139  if (bits > GetMaxPrefixLength(family)) {
140    bits = GetMaxPrefixLength(family);
141  }
142
143  while (bits > kBitsPerByte) {
144    bits -= kBitsPerByte;
145    *address_ptr++ = kuint8max;
146  }
147
148  // We are guaranteed to be before the end of the address data since even
149  // if the prefix is the maximum, the loop above will end before we assign
150  // and increment past the last byte.
151  *address_ptr = ~((1 << (kBitsPerByte - bits)) - 1);
152
153  return IPAddress(family, address_bytes);
154}
155
156// static
157string IPAddress::GetAddressFamilyName(Family family) {
158  switch (family) {
159  case kFamilyIPv4:
160    return kFamilyNameIPv4;
161  case kFamilyIPv6:
162    return kFamilyNameIPv6;
163  default:
164    return kFamilyNameUnknown;
165  }
166}
167
168bool IPAddress::SetAddressFromString(const string& address_string) {
169  size_t address_length = GetAddressLength(family_);
170
171  if (!address_length) {
172    return false;
173  }
174
175  ByteString address(address_length);
176  if (inet_pton(family_, address_string.c_str(), address.GetData()) <= 0) {
177    return false;
178  }
179  address_ = address;
180  return true;
181}
182
183bool IPAddress::SetAddressAndPrefixFromString(const string& address_string) {
184  vector<string> address_parts;
185  base::SplitString(address_string, '/', &address_parts);
186  if (address_parts.size() != 2) {
187    LOG(ERROR) << "Cannot split address " << address_string;
188    return false;
189  }
190  if (!SetAddressFromString(address_parts[0])) {
191    LOG(ERROR) << "Cannot parse address string " << address_parts[0];
192    return false;
193  }
194  size_t prefix;
195  if (!base::StringToSizeT(address_parts[1], &prefix) ||
196      prefix > GetMaxPrefixLength(family_)) {
197    LOG(ERROR) << "Cannot parse address prefix " << address_parts[1];
198    return false;
199  }
200  set_prefix(prefix);
201  return true;
202}
203
204void IPAddress::SetAddressToDefault() {
205  address_ = ByteString(GetAddressLength(family_));
206}
207
208bool IPAddress::IntoString(string* address_string) const {
209  // Noting that INET6_ADDRSTRLEN > INET_ADDRSTRLEN
210  char address_buf[INET6_ADDRSTRLEN];
211  if (GetLength() != GetAddressLength(family_) ||
212      !inet_ntop(family_, GetConstData(), address_buf, sizeof(address_buf))) {
213    return false;
214  }
215  *address_string = address_buf;
216  return true;
217}
218
219string IPAddress::ToString() const {
220  string out("<unknown>");
221  IntoString(&out);
222  return out;
223}
224
225bool IPAddress::Equals(const IPAddress& b) const {
226  return family_ == b.family_ && address_.Equals(b.address_) &&
227      prefix_ == b.prefix_;
228}
229
230bool IPAddress::HasSameAddressAs(const IPAddress& b) const {
231  return family_ == b.family_ && address_.Equals(b.address_);
232}
233
234IPAddress IPAddress::MaskWith(const IPAddress& b) const {
235  CHECK(IsValid());
236  CHECK(b.IsValid());
237  CHECK_EQ(family(), b.family());
238
239  ByteString address_bytes(address());
240  address_bytes.BitwiseAnd(b.address());
241
242  return IPAddress(family(), address_bytes);
243}
244
245IPAddress IPAddress::MergeWith(const IPAddress& b) const {
246  CHECK(IsValid());
247  CHECK(b.IsValid());
248  CHECK_EQ(family(), b.family());
249
250  ByteString address_bytes(address());
251  address_bytes.BitwiseOr(b.address());
252
253  return IPAddress(family(), address_bytes);
254}
255
256IPAddress IPAddress::GetNetworkPart() const {
257  return MaskWith(GetAddressMaskFromPrefix(family(), prefix()));
258}
259
260IPAddress IPAddress::GetDefaultBroadcast() {
261  ByteString broadcast_bytes(
262    GetAddressMaskFromPrefix(family(), prefix()).address());
263  broadcast_bytes.BitwiseInvert();
264  return MergeWith(IPAddress(family(), broadcast_bytes));
265}
266
267bool IPAddress::CanReachAddress(const IPAddress& b) const {
268  CHECK_EQ(family(), b.family());
269  IPAddress b_prefixed(b);
270  b_prefixed.set_prefix(prefix());
271  return GetNetworkPart().Equals(b_prefixed.GetNetworkPart());
272}
273
274}  // namespace shill
275