1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #if defined(WEBRTC_POSIX)
12 #include <netinet/in.h>
13 #include <sys/socket.h>
14
15 #include "absl/strings/string_view.h"
16 #ifdef OPENBSD
17 #include <netinet/in_systm.h>
18 #endif
19 #ifndef __native_client__
20 #include <netinet/ip.h>
21 #endif
22 #include <netdb.h>
23 #endif
24
25 #include "rtc_base/ip_address.h"
26
27 #include "rtc_base/byte_order.h"
28 #include "rtc_base/net_helpers.h"
29 #include "rtc_base/string_utils.h"
30
31 #if defined(WEBRTC_WIN)
32 #include "rtc_base/win32.h"
33 #endif // WEBRTC_WIN
34
35 namespace rtc {
36
37 // Prefixes used for categorizing IPv6 addresses.
38 static const in6_addr kV4MappedPrefix = {
39 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0}}};
40 static const in6_addr k6To4Prefix = {{{0x20, 0x02, 0}}};
41 static const in6_addr kTeredoPrefix = {{{0x20, 0x01, 0x00, 0x00}}};
42 static const in6_addr kV4CompatibilityPrefix = {{{0}}};
43 static const in6_addr k6BonePrefix = {{{0x3f, 0xfe, 0}}};
44 static const in6_addr kPrivateNetworkPrefix = {{{0xFD}}};
45
46 static bool IPIsHelper(const IPAddress& ip,
47 const in6_addr& tomatch,
48 int length);
49 static in_addr ExtractMappedAddress(const in6_addr& addr);
50
v4AddressAsHostOrderInteger() const51 uint32_t IPAddress::v4AddressAsHostOrderInteger() const {
52 if (family_ == AF_INET) {
53 return NetworkToHost32(u_.ip4.s_addr);
54 } else {
55 return 0;
56 }
57 }
58
overhead() const59 int IPAddress::overhead() const {
60 switch (family_) {
61 case AF_INET: // IPv4
62 return 20;
63 case AF_INET6: // IPv6
64 return 40;
65 default:
66 return 0;
67 }
68 }
69
IsNil() const70 bool IPAddress::IsNil() const {
71 return IPIsUnspec(*this);
72 }
73
Size() const74 size_t IPAddress::Size() const {
75 switch (family_) {
76 case AF_INET:
77 return sizeof(in_addr);
78 case AF_INET6:
79 return sizeof(in6_addr);
80 }
81 return 0;
82 }
83
operator ==(const IPAddress & other) const84 bool IPAddress::operator==(const IPAddress& other) const {
85 if (family_ != other.family_) {
86 return false;
87 }
88 if (family_ == AF_INET) {
89 return memcmp(&u_.ip4, &other.u_.ip4, sizeof(u_.ip4)) == 0;
90 }
91 if (family_ == AF_INET6) {
92 return memcmp(&u_.ip6, &other.u_.ip6, sizeof(u_.ip6)) == 0;
93 }
94 return family_ == AF_UNSPEC;
95 }
96
operator !=(const IPAddress & other) const97 bool IPAddress::operator!=(const IPAddress& other) const {
98 return !((*this) == other);
99 }
100
operator >(const IPAddress & other) const101 bool IPAddress::operator>(const IPAddress& other) const {
102 return (*this) != other && !((*this) < other);
103 }
104
operator <(const IPAddress & other) const105 bool IPAddress::operator<(const IPAddress& other) const {
106 // IPv4 is 'less than' IPv6
107 if (family_ != other.family_) {
108 if (family_ == AF_UNSPEC) {
109 return true;
110 }
111 if (family_ == AF_INET && other.family_ == AF_INET6) {
112 return true;
113 }
114 return false;
115 }
116 // Comparing addresses of the same family.
117 switch (family_) {
118 case AF_INET: {
119 return NetworkToHost32(u_.ip4.s_addr) <
120 NetworkToHost32(other.u_.ip4.s_addr);
121 }
122 case AF_INET6: {
123 return memcmp(&u_.ip6.s6_addr, &other.u_.ip6.s6_addr, 16) < 0;
124 }
125 }
126 // Catches AF_UNSPEC and invalid addresses.
127 return false;
128 }
129
ipv6_address() const130 in6_addr IPAddress::ipv6_address() const {
131 return u_.ip6;
132 }
133
ipv4_address() const134 in_addr IPAddress::ipv4_address() const {
135 return u_.ip4;
136 }
137
ToString() const138 std::string IPAddress::ToString() const {
139 if (family_ != AF_INET && family_ != AF_INET6) {
140 return std::string();
141 }
142 char buf[INET6_ADDRSTRLEN] = {0};
143 const void* src = &u_.ip4;
144 if (family_ == AF_INET6) {
145 src = &u_.ip6;
146 }
147 if (!rtc::inet_ntop(family_, src, buf, sizeof(buf))) {
148 return std::string();
149 }
150 return std::string(buf);
151 }
152
ToSensitiveString() const153 std::string IPAddress::ToSensitiveString() const {
154 switch (family_) {
155 case AF_INET: {
156 std::string address = ToString();
157 size_t find_pos = address.rfind('.');
158 if (find_pos == std::string::npos)
159 return std::string();
160 address.resize(find_pos);
161 address += ".x";
162 return address;
163 }
164 case AF_INET6: {
165 std::string result;
166 result.resize(INET6_ADDRSTRLEN);
167 in6_addr addr = ipv6_address();
168 size_t len = snprintf(&(result[0]), result.size(), "%x:%x:%x:x:x:x:x:x",
169 (addr.s6_addr[0] << 8) + addr.s6_addr[1],
170 (addr.s6_addr[2] << 8) + addr.s6_addr[3],
171 (addr.s6_addr[4] << 8) + addr.s6_addr[5]);
172 result.resize(len);
173 return result;
174 }
175 }
176 return std::string();
177 }
178
Normalized() const179 IPAddress IPAddress::Normalized() const {
180 if (family_ != AF_INET6) {
181 return *this;
182 }
183 if (!IPIsV4Mapped(*this)) {
184 return *this;
185 }
186 in_addr addr = ExtractMappedAddress(u_.ip6);
187 return IPAddress(addr);
188 }
189
AsIPv6Address() const190 IPAddress IPAddress::AsIPv6Address() const {
191 if (family_ != AF_INET) {
192 return *this;
193 }
194 in6_addr v6addr = kV4MappedPrefix;
195 ::memcpy(&v6addr.s6_addr[12], &u_.ip4.s_addr, sizeof(u_.ip4.s_addr));
196 return IPAddress(v6addr);
197 }
198
operator ==(const InterfaceAddress & other) const199 bool InterfaceAddress::operator==(const InterfaceAddress& other) const {
200 return ipv6_flags_ == other.ipv6_flags() &&
201 static_cast<const IPAddress&>(*this) == other;
202 }
203
operator !=(const InterfaceAddress & other) const204 bool InterfaceAddress::operator!=(const InterfaceAddress& other) const {
205 return !((*this) == other);
206 }
207
operator =(const InterfaceAddress & other)208 const InterfaceAddress& InterfaceAddress::operator=(
209 const InterfaceAddress& other) {
210 ipv6_flags_ = other.ipv6_flags_;
211 static_cast<IPAddress&>(*this) = other;
212 return *this;
213 }
214
ToString() const215 std::string InterfaceAddress::ToString() const {
216 std::string result = IPAddress::ToString();
217
218 if (family() == AF_INET6)
219 result += "|flags:0x" + rtc::ToHex(ipv6_flags());
220
221 return result;
222 }
223
IPIsPrivateNetworkV4(const IPAddress & ip)224 static bool IPIsPrivateNetworkV4(const IPAddress& ip) {
225 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
226 return ((ip_in_host_order >> 24) == 10) ||
227 ((ip_in_host_order >> 20) == ((172 << 4) | 1)) ||
228 ((ip_in_host_order >> 16) == ((192 << 8) | 168));
229 }
230
IPIsPrivateNetworkV6(const IPAddress & ip)231 static bool IPIsPrivateNetworkV6(const IPAddress& ip) {
232 return IPIsHelper(ip, kPrivateNetworkPrefix, 8);
233 }
234
IPIsPrivateNetwork(const IPAddress & ip)235 bool IPIsPrivateNetwork(const IPAddress& ip) {
236 switch (ip.family()) {
237 case AF_INET: {
238 return IPIsPrivateNetworkV4(ip);
239 }
240 case AF_INET6: {
241 return IPIsPrivateNetworkV6(ip);
242 }
243 }
244 return false;
245 }
246
IPIsSharedNetworkV4(const IPAddress & ip)247 static bool IPIsSharedNetworkV4(const IPAddress& ip) {
248 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
249 return (ip_in_host_order >> 22) == ((100 << 2) | 1);
250 }
251
IPIsSharedNetwork(const IPAddress & ip)252 bool IPIsSharedNetwork(const IPAddress& ip) {
253 if (ip.family() == AF_INET) {
254 return IPIsSharedNetworkV4(ip);
255 }
256 return false;
257 }
258
ExtractMappedAddress(const in6_addr & in6)259 in_addr ExtractMappedAddress(const in6_addr& in6) {
260 in_addr ipv4;
261 ::memcpy(&ipv4.s_addr, &in6.s6_addr[12], sizeof(ipv4.s_addr));
262 return ipv4;
263 }
264
IPFromAddrInfo(struct addrinfo * info,IPAddress * out)265 bool IPFromAddrInfo(struct addrinfo* info, IPAddress* out) {
266 if (!info || !info->ai_addr) {
267 return false;
268 }
269 if (info->ai_addr->sa_family == AF_INET) {
270 sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(info->ai_addr);
271 *out = IPAddress(addr->sin_addr);
272 return true;
273 } else if (info->ai_addr->sa_family == AF_INET6) {
274 sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(info->ai_addr);
275 *out = IPAddress(addr->sin6_addr);
276 return true;
277 }
278 return false;
279 }
280
IPFromString(absl::string_view str,IPAddress * out)281 bool IPFromString(absl::string_view str, IPAddress* out) {
282 if (!out) {
283 return false;
284 }
285 in_addr addr;
286 if (rtc::inet_pton(AF_INET, str, &addr) == 0) {
287 in6_addr addr6;
288 if (rtc::inet_pton(AF_INET6, str, &addr6) == 0) {
289 *out = IPAddress();
290 return false;
291 }
292 *out = IPAddress(addr6);
293 } else {
294 *out = IPAddress(addr);
295 }
296 return true;
297 }
298
IPFromString(absl::string_view str,int flags,InterfaceAddress * out)299 bool IPFromString(absl::string_view str, int flags, InterfaceAddress* out) {
300 IPAddress ip;
301 if (!IPFromString(str, &ip)) {
302 return false;
303 }
304
305 *out = InterfaceAddress(ip, flags);
306 return true;
307 }
308
IPIsAny(const IPAddress & ip)309 bool IPIsAny(const IPAddress& ip) {
310 switch (ip.family()) {
311 case AF_INET:
312 return ip == IPAddress(INADDR_ANY);
313 case AF_INET6:
314 return ip == IPAddress(in6addr_any) || ip == IPAddress(kV4MappedPrefix);
315 case AF_UNSPEC:
316 return false;
317 }
318 return false;
319 }
320
IPIsLoopbackV4(const IPAddress & ip)321 static bool IPIsLoopbackV4(const IPAddress& ip) {
322 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
323 return ((ip_in_host_order >> 24) == 127);
324 }
325
IPIsLoopbackV6(const IPAddress & ip)326 static bool IPIsLoopbackV6(const IPAddress& ip) {
327 return ip == IPAddress(in6addr_loopback);
328 }
329
IPIsLoopback(const IPAddress & ip)330 bool IPIsLoopback(const IPAddress& ip) {
331 switch (ip.family()) {
332 case AF_INET: {
333 return IPIsLoopbackV4(ip);
334 }
335 case AF_INET6: {
336 return IPIsLoopbackV6(ip);
337 }
338 }
339 return false;
340 }
341
IPIsPrivate(const IPAddress & ip)342 bool IPIsPrivate(const IPAddress& ip) {
343 return IPIsLinkLocal(ip) || IPIsLoopback(ip) || IPIsPrivateNetwork(ip) ||
344 IPIsSharedNetwork(ip);
345 }
346
IPIsUnspec(const IPAddress & ip)347 bool IPIsUnspec(const IPAddress& ip) {
348 return ip.family() == AF_UNSPEC;
349 }
350
HashIP(const IPAddress & ip)351 size_t HashIP(const IPAddress& ip) {
352 switch (ip.family()) {
353 case AF_INET: {
354 return ip.ipv4_address().s_addr;
355 }
356 case AF_INET6: {
357 in6_addr v6addr = ip.ipv6_address();
358 const uint32_t* v6_as_ints =
359 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr);
360 return v6_as_ints[0] ^ v6_as_ints[1] ^ v6_as_ints[2] ^ v6_as_ints[3];
361 }
362 }
363 return 0;
364 }
365
TruncateIP(const IPAddress & ip,int length)366 IPAddress TruncateIP(const IPAddress& ip, int length) {
367 if (length < 0) {
368 return IPAddress();
369 }
370 if (ip.family() == AF_INET) {
371 if (length > 31) {
372 return ip;
373 }
374 if (length == 0) {
375 return IPAddress(INADDR_ANY);
376 }
377 int mask = (0xFFFFFFFF << (32 - length));
378 uint32_t host_order_ip = NetworkToHost32(ip.ipv4_address().s_addr);
379 in_addr masked;
380 masked.s_addr = HostToNetwork32(host_order_ip & mask);
381 return IPAddress(masked);
382 } else if (ip.family() == AF_INET6) {
383 if (length > 127) {
384 return ip;
385 }
386 if (length == 0) {
387 return IPAddress(in6addr_any);
388 }
389 in6_addr v6addr = ip.ipv6_address();
390 int position = length / 32;
391 int inner_length = 32 - (length - (position * 32));
392 // Note: 64bit mask constant needed to allow possible 32-bit left shift.
393 uint32_t inner_mask = 0xFFFFFFFFLL << inner_length;
394 uint32_t* v6_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr);
395 for (int i = 0; i < 4; ++i) {
396 if (i == position) {
397 uint32_t host_order_inner = NetworkToHost32(v6_as_ints[i]);
398 v6_as_ints[i] = HostToNetwork32(host_order_inner & inner_mask);
399 } else if (i > position) {
400 v6_as_ints[i] = 0;
401 }
402 }
403 return IPAddress(v6addr);
404 }
405 return IPAddress();
406 }
407
CountIPMaskBits(const IPAddress & mask)408 int CountIPMaskBits(const IPAddress& mask) {
409 uint32_t word_to_count = 0;
410 int bits = 0;
411 switch (mask.family()) {
412 case AF_INET: {
413 word_to_count = NetworkToHost32(mask.ipv4_address().s_addr);
414 break;
415 }
416 case AF_INET6: {
417 in6_addr v6addr = mask.ipv6_address();
418 const uint32_t* v6_as_ints =
419 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr);
420 int i = 0;
421 for (; i < 4; ++i) {
422 if (v6_as_ints[i] != 0xFFFFFFFF) {
423 break;
424 }
425 }
426 if (i < 4) {
427 word_to_count = NetworkToHost32(v6_as_ints[i]);
428 }
429 bits = (i * 32);
430 break;
431 }
432 default: {
433 return 0;
434 }
435 }
436 if (word_to_count == 0) {
437 return bits;
438 }
439
440 // Public domain bit-twiddling hack from:
441 // http://graphics.stanford.edu/~seander/bithacks.html
442 // Counts the trailing 0s in the word.
443 unsigned int zeroes = 32;
444 // This could also be written word_to_count &= -word_to_count, but
445 // MSVC emits warning C4146 when negating an unsigned number.
446 word_to_count &= ~word_to_count + 1; // Isolate lowest set bit.
447 if (word_to_count)
448 zeroes--;
449 if (word_to_count & 0x0000FFFF)
450 zeroes -= 16;
451 if (word_to_count & 0x00FF00FF)
452 zeroes -= 8;
453 if (word_to_count & 0x0F0F0F0F)
454 zeroes -= 4;
455 if (word_to_count & 0x33333333)
456 zeroes -= 2;
457 if (word_to_count & 0x55555555)
458 zeroes -= 1;
459
460 return bits + (32 - zeroes);
461 }
462
IPIsHelper(const IPAddress & ip,const in6_addr & tomatch,int length)463 bool IPIsHelper(const IPAddress& ip, const in6_addr& tomatch, int length) {
464 // Helper method for checking IP prefix matches (but only on whole byte
465 // lengths). Length is in bits.
466 in6_addr addr = ip.ipv6_address();
467 return ::memcmp(&addr, &tomatch, (length >> 3)) == 0;
468 }
469
IPIs6Bone(const IPAddress & ip)470 bool IPIs6Bone(const IPAddress& ip) {
471 return IPIsHelper(ip, k6BonePrefix, 16);
472 }
473
IPIs6To4(const IPAddress & ip)474 bool IPIs6To4(const IPAddress& ip) {
475 return IPIsHelper(ip, k6To4Prefix, 16);
476 }
477
IPIsLinkLocalV4(const IPAddress & ip)478 static bool IPIsLinkLocalV4(const IPAddress& ip) {
479 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
480 return ((ip_in_host_order >> 16) == ((169 << 8) | 254));
481 }
482
IPIsLinkLocalV6(const IPAddress & ip)483 static bool IPIsLinkLocalV6(const IPAddress& ip) {
484 // Can't use the helper because the prefix is 10 bits.
485 in6_addr addr = ip.ipv6_address();
486 return (addr.s6_addr[0] == 0xFE) && ((addr.s6_addr[1] & 0xC0) == 0x80);
487 }
488
IPIsLinkLocal(const IPAddress & ip)489 bool IPIsLinkLocal(const IPAddress& ip) {
490 switch (ip.family()) {
491 case AF_INET: {
492 return IPIsLinkLocalV4(ip);
493 }
494 case AF_INET6: {
495 return IPIsLinkLocalV6(ip);
496 }
497 }
498 return false;
499 }
500
501 // According to http://www.ietf.org/rfc/rfc2373.txt, Appendix A, page 19. An
502 // address which contains MAC will have its 11th and 12th bytes as FF:FE as well
503 // as the U/L bit as 1.
IPIsMacBased(const IPAddress & ip)504 bool IPIsMacBased(const IPAddress& ip) {
505 in6_addr addr = ip.ipv6_address();
506 return ((addr.s6_addr[8] & 0x02) && addr.s6_addr[11] == 0xFF &&
507 addr.s6_addr[12] == 0xFE);
508 }
509
IPIsSiteLocal(const IPAddress & ip)510 bool IPIsSiteLocal(const IPAddress& ip) {
511 // Can't use the helper because the prefix is 10 bits.
512 in6_addr addr = ip.ipv6_address();
513 return addr.s6_addr[0] == 0xFE && (addr.s6_addr[1] & 0xC0) == 0xC0;
514 }
515
IPIsULA(const IPAddress & ip)516 bool IPIsULA(const IPAddress& ip) {
517 // Can't use the helper because the prefix is 7 bits.
518 in6_addr addr = ip.ipv6_address();
519 return (addr.s6_addr[0] & 0xFE) == 0xFC;
520 }
521
IPIsTeredo(const IPAddress & ip)522 bool IPIsTeredo(const IPAddress& ip) {
523 return IPIsHelper(ip, kTeredoPrefix, 32);
524 }
525
IPIsV4Compatibility(const IPAddress & ip)526 bool IPIsV4Compatibility(const IPAddress& ip) {
527 return IPIsHelper(ip, kV4CompatibilityPrefix, 96);
528 }
529
IPIsV4Mapped(const IPAddress & ip)530 bool IPIsV4Mapped(const IPAddress& ip) {
531 return IPIsHelper(ip, kV4MappedPrefix, 96);
532 }
533
IPAddressPrecedence(const IPAddress & ip)534 int IPAddressPrecedence(const IPAddress& ip) {
535 // Precedence values from RFC 3484-bis. Prefers native v4 over 6to4/Teredo.
536 if (ip.family() == AF_INET) {
537 return 30;
538 } else if (ip.family() == AF_INET6) {
539 if (IPIsLoopback(ip)) {
540 return 60;
541 } else if (IPIsULA(ip)) {
542 return 50;
543 } else if (IPIsV4Mapped(ip)) {
544 return 30;
545 } else if (IPIs6To4(ip)) {
546 return 20;
547 } else if (IPIsTeredo(ip)) {
548 return 10;
549 } else if (IPIsV4Compatibility(ip) || IPIsSiteLocal(ip) || IPIs6Bone(ip)) {
550 return 1;
551 } else {
552 // A 'normal' IPv6 address.
553 return 40;
554 }
555 }
556 return 0;
557 }
558
GetLoopbackIP(int family)559 IPAddress GetLoopbackIP(int family) {
560 if (family == AF_INET) {
561 return rtc::IPAddress(INADDR_LOOPBACK);
562 }
563 if (family == AF_INET6) {
564 return rtc::IPAddress(in6addr_loopback);
565 }
566 return rtc::IPAddress();
567 }
568
GetAnyIP(int family)569 IPAddress GetAnyIP(int family) {
570 if (family == AF_INET) {
571 return rtc::IPAddress(INADDR_ANY);
572 }
573 if (family == AF_INET6) {
574 return rtc::IPAddress(in6addr_any);
575 }
576 return rtc::IPAddress();
577 }
578
579 } // namespace rtc
580