blob: 2ddaeb02e4a61b045e3a50f5132f49e861378eda [file] [log] [blame]
Paul Stewart188a84a2012-01-20 16:28:15 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewart1d18e8c2011-07-15 11:00:31 -07002// 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/ip_address.h"
6
Chris Masone2aa97072011-08-09 17:35:08 -07007#include <arpa/inet.h>
Paul Stewart1d18e8c2011-07-15 11:00:31 -07008#include <netinet/in.h>
9
10#include <string>
Paul Stewartf7bf9bf2012-04-17 17:30:14 -070011#include <vector>
Paul Stewart1d18e8c2011-07-15 11:00:31 -070012
Darin Petkov14c29ec2012-03-02 11:34:19 +010013#include <base/logging.h>
Paul Stewartf7bf9bf2012-04-17 17:30:14 -070014#include <base/string_number_conversions.h>
15#include <base/string_split.h>
Darin Petkov14c29ec2012-03-02 11:34:19 +010016
Paul Stewart1d18e8c2011-07-15 11:00:31 -070017#include "shill/byte_string.h"
18
Paul Stewart188a84a2012-01-20 16:28:15 -080019using std::string;
Paul Stewartf7bf9bf2012-04-17 17:30:14 -070020using std::vector;
Paul Stewart188a84a2012-01-20 16:28:15 -080021
Paul Stewart1d18e8c2011-07-15 11:00:31 -070022namespace shill {
23
Paul Stewartf7bf9bf2012-04-17 17:30:14 -070024namespace {
25const size_t kBitsPerByte = 8;
26} // namespace
27
Chris Masone2aa97072011-08-09 17:35:08 -070028// static
Paul Stewart7355ce12011-09-02 10:47:01 -070029const IPAddress::Family IPAddress::kFamilyUnknown = AF_UNSPEC;
Chris Masone2aa97072011-08-09 17:35:08 -070030// static
Paul Stewart7355ce12011-09-02 10:47:01 -070031const IPAddress::Family IPAddress::kFamilyIPv4 = AF_INET;
Chris Masone2aa97072011-08-09 17:35:08 -070032// static
Paul Stewart7355ce12011-09-02 10:47:01 -070033const IPAddress::Family IPAddress::kFamilyIPv6 = AF_INET6;
Chris Masone2aa97072011-08-09 17:35:08 -070034
Paul Stewartf748a362012-03-07 12:01:20 -080035// static
36const char IPAddress::kFamilyNameUnknown[] = "Unknown";
37// static
38const char IPAddress::kFamilyNameIPv4[] = "IPv4";
39// static
40const char IPAddress::kFamilyNameIPv6[] = "IPv6";
41
Paul Stewart1d18e8c2011-07-15 11:00:31 -070042IPAddress::IPAddress(Family family, const ByteString &address)
43 : family_(family) ,
Paul Stewart9e3fcd72011-08-26 15:46:16 -070044 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) {}
Paul Stewart1d18e8c2011-07-15 11:00:31 -070053
54IPAddress::IPAddress(Family family)
Paul Stewart9e3fcd72011-08-26 15:46:16 -070055 : family_(family),
56 prefix_(0) {}
Paul Stewart1d18e8c2011-07-15 11:00:31 -070057
58IPAddress::~IPAddress() {}
59
Paul Stewartf748a362012-03-07 12:01:20 -080060// static
Eric Shienbroodc74cf9c2012-03-02 15:00:35 -050061size_t IPAddress::GetAddressLength(Family family) {
Paul Stewart1d18e8c2011-07-15 11:00:31 -070062 switch (family) {
Paul Stewart7355ce12011-09-02 10:47:01 -070063 case kFamilyIPv4:
Paul Stewart1d18e8c2011-07-15 11:00:31 -070064 return sizeof(in_addr);
Paul Stewart7355ce12011-09-02 10:47:01 -070065 case kFamilyIPv6:
Paul Stewart1d18e8c2011-07-15 11:00:31 -070066 return sizeof(in6_addr);
67 default:
68 return 0;
69 }
70}
71
Darin Petkov14c29ec2012-03-02 11:34:19 +010072// static
Paul Stewart48100b02012-03-19 07:53:52 -070073size_t IPAddress::GetMaxPrefixLength(Family family) {
Paul Stewartf7bf9bf2012-04-17 17:30:14 -070074 return GetAddressLength(family) * kBitsPerByte;
75}
76
77size_t IPAddress::GetMinPrefixLength() const {
78 if (family() != kFamilyIPv4) {
79 NOTIMPLEMENTED() << ": only implemented for IPv4";
80 return GetMaxPrefixLength(family());
81 }
82
83 CHECK(IsValid());
84 in_addr_t address_val;
85 memcpy(&address_val, GetConstData(), sizeof(address_val));
86 // IN_CLASSx() macros operate on addresses in host-order.
87 address_val = ntohl(address_val);
88 if (IN_CLASSA(address_val)) {
89 return GetMaxPrefixLength(family()) - IN_CLASSA_NSHIFT;
90 } else if (IN_CLASSB(address_val)) {
91 return GetMaxPrefixLength(family()) - IN_CLASSB_NSHIFT;
92 } else if (IN_CLASSC(address_val)) {
93 return GetMaxPrefixLength(family()) - IN_CLASSC_NSHIFT;
94 }
95
96 LOG(ERROR) << "Invalid IPv4 address class";
97 return GetMaxPrefixLength(family());
Paul Stewart48100b02012-03-19 07:53:52 -070098}
99
100// static
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500101size_t IPAddress::GetPrefixLengthFromMask(Family family, const string &mask) {
Darin Petkov14c29ec2012-03-02 11:34:19 +0100102 switch (family) {
103 case kFamilyIPv4: {
104 in_addr_t mask_val = inet_network(mask.c_str());
Paul Stewart48100b02012-03-19 07:53:52 -0700105 int subnet_prefix = 0;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100106 while (mask_val) {
Paul Stewart48100b02012-03-19 07:53:52 -0700107 subnet_prefix++;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100108 mask_val <<= 1;
109 }
Paul Stewart48100b02012-03-19 07:53:52 -0700110 return subnet_prefix;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100111 }
112 case kFamilyIPv6:
113 NOTIMPLEMENTED();
114 break;
115 default:
116 LOG(WARNING) << "Unexpected address family: " << family;
117 break;
118 }
119 return 0;
120}
121
Paul Stewartf748a362012-03-07 12:01:20 -0800122// static
Paul Stewartf7bf9bf2012-04-17 17:30:14 -0700123IPAddress IPAddress::GetAddressMaskFromPrefix(Family family, size_t prefix) {
124 ByteString address_bytes(GetAddressLength(family));
125 unsigned char *address_ptr = address_bytes.GetData();
126
127 size_t bits = prefix;
128 if (bits > GetMaxPrefixLength(family)) {
129 bits = GetMaxPrefixLength(family);
130 }
131
132 while (bits > kBitsPerByte) {
133 bits -= kBitsPerByte;
134 *address_ptr++ = kuint8max;
135 }
136
137 // We are guaranteed to be before the end of the address data since even
138 // if the prefix is the maximum, the loop above will end before we assign
139 // and increment past the last byte.
140 *address_ptr = ~((1 << (kBitsPerByte - bits)) - 1);
141
142 return IPAddress(family, address_bytes);
143}
144
145// static
Paul Stewartf748a362012-03-07 12:01:20 -0800146string IPAddress::GetAddressFamilyName(Family family) {
147 switch (family) {
148 case kFamilyIPv4:
149 return kFamilyNameIPv4;
150 case kFamilyIPv6:
151 return kFamilyNameIPv6;
152 default:
153 return kFamilyNameUnknown;
154 }
155}
156
Paul Stewart188a84a2012-01-20 16:28:15 -0800157bool IPAddress::SetAddressFromString(const string &address_string) {
Eric Shienbroodc74cf9c2012-03-02 15:00:35 -0500158 size_t address_length = GetAddressLength(family_);
Paul Stewart1d18e8c2011-07-15 11:00:31 -0700159
160 if (!address_length) {
161 return false;
162 }
163
164 ByteString address(address_length);
165 if (inet_pton(family_, address_string.c_str(), address.GetData()) <= 0) {
166 return false;
167 }
168 address_ = address;
169 return true;
170}
171
Paul Stewartf7bf9bf2012-04-17 17:30:14 -0700172bool IPAddress::SetAddressAndPrefixFromString(const string &address_string) {
173 vector<string> address_parts;
174 base::SplitString(address_string, '/', &address_parts);
175 if (address_parts.size() != 2) {
176 LOG(ERROR) << "Cannot split address " << address_string;
177 return false;
178 }
179 if (!SetAddressFromString(address_parts[0])) {
180 LOG(ERROR) << "Cannot parse address string " << address_parts[0];
181 return false;
182 }
183 int prefix;
184 if (!base::StringToInt(address_parts[1], &prefix) || prefix < 0) {
185 LOG(ERROR) << "Cannot parse address prefix " << address_parts[1];
186 return false;
187 }
188 set_prefix(prefix);
189 return true;
190}
191
Paul Stewart1d18e8c2011-07-15 11:00:31 -0700192void IPAddress::SetAddressToDefault() {
193 address_ = ByteString(GetAddressLength(family_));
194}
195
mukesh agrawal2c15d2c2012-02-21 16:09:21 -0800196bool IPAddress::IntoString(string *address_string) const {
Paul Stewart188a84a2012-01-20 16:28:15 -0800197 // Noting that INET6_ADDRSTRLEN > INET_ADDRSTRLEN
198 char address_buf[INET6_ADDRSTRLEN];
199 if (GetLength() != GetAddressLength(family_) ||
200 !inet_ntop(family_, GetConstData(), address_buf, sizeof(address_buf))) {
201 return false;
202 }
203 *address_string = address_buf;
204 return true;
205}
206
mukesh agrawal2c15d2c2012-02-21 16:09:21 -0800207string IPAddress::ToString() const {
208 string out("<unknown>");
209 IntoString(&out);
210 return out;
211}
212
Paul Stewartf7bf9bf2012-04-17 17:30:14 -0700213IPAddress IPAddress::MaskWith(const IPAddress &b) {
214 CHECK(IsValid());
215 CHECK(b.IsValid());
216 CHECK_EQ(family(), b.family());
217
218 ByteString address_bytes(address());
Paul Stewartfe1c0e12012-04-30 19:57:04 -0700219 address_bytes.BitwiseAnd(b.address());
220
221 return IPAddress(family(), address_bytes);
222}
223
224IPAddress IPAddress::MergeWith(const IPAddress &b) {
225 CHECK(IsValid());
226 CHECK(b.IsValid());
227 CHECK_EQ(family(), b.family());
228
229 ByteString address_bytes(address());
230 address_bytes.BitwiseOr(b.address());
Paul Stewartf7bf9bf2012-04-17 17:30:14 -0700231
232 return IPAddress(family(), address_bytes);
233}
234
235IPAddress IPAddress::GetNetworkPart() {
236 return MaskWith(GetAddressMaskFromPrefix(family(), prefix()));
237}
238
Paul Stewartfe1c0e12012-04-30 19:57:04 -0700239IPAddress IPAddress::GetDefaultBroadcast() {
240 ByteString broadcast_bytes(
241 GetAddressMaskFromPrefix(family(), prefix()).address());
242 broadcast_bytes.BitwiseInvert();
243 return MergeWith(IPAddress(family(), broadcast_bytes));
244}
245
Paul Stewartf7bf9bf2012-04-17 17:30:14 -0700246bool IPAddress::CanReachAddress(const IPAddress &b) {
247 CHECK_EQ(family(), b.family());
248 IPAddress b_prefixed(b);
249 b_prefixed.set_prefix(prefix());
250 return GetNetworkPart().Equals(b_prefixed.GetNetworkPart());
251}
252
Paul Stewart1d18e8c2011-07-15 11:00:31 -0700253} // namespace shill