blob: 96d100187b0c892df0ca5181defd3e0747831829 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012#include <netinet/in.h>
Yves Gerey665174f2018-06-19 15:03:05 +020013#include <sys/socket.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000014#ifdef OPENBSD
15#include <netinet/in_systm.h>
16#endif
17#ifndef __native_client__
18#include <netinet/ip.h>
19#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000020#include <netdb.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000021#endif
22
Steve Anton10542f22019-01-11 09:11:00 -080023#include "rtc_base/byte_order.h"
24#include "rtc_base/ip_address.h"
25#include "rtc_base/net_helpers.h"
26#include "rtc_base/string_utils.h"
Mirko Bonadeie0623852018-02-01 11:17:40 +010027
28#if defined(WEBRTC_WIN)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "rtc_base/win32.h"
Mirko Bonadeie0623852018-02-01 11:17:40 +010030#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000031
32namespace rtc {
33
34// Prefixes used for categorizing IPv6 addresses.
Yves Gerey665174f2018-06-19 15:03:05 +020035static const in6_addr kV4MappedPrefix = {
36 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0}}};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000037static const in6_addr k6To4Prefix = {{{0x20, 0x02, 0}}};
38static const in6_addr kTeredoPrefix = {{{0x20, 0x01, 0x00, 0x00}}};
39static const in6_addr kV4CompatibilityPrefix = {{{0}}};
40static const in6_addr k6BonePrefix = {{{0x3f, 0xfe, 0}}};
Daniel Lazarenko2870b0a2018-01-25 10:30:22 +010041static const in6_addr kPrivateNetworkPrefix = {{{0xFD}}};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000042
Daniel Lazarenko2870b0a2018-01-25 10:30:22 +010043static bool IPIsHelper(const IPAddress& ip,
Yves Gerey665174f2018-06-19 15:03:05 +020044 const in6_addr& tomatch,
45 int length);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000046static in_addr ExtractMappedAddress(const in6_addr& addr);
47
Peter Boström0c4e06b2015-10-07 12:23:21 +020048uint32_t IPAddress::v4AddressAsHostOrderInteger() const {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000049 if (family_ == AF_INET) {
50 return NetworkToHost32(u_.ip4.s_addr);
51 } else {
52 return 0;
53 }
54}
55
Guo-wei Shieh11477022015-08-15 09:28:41 -070056bool IPAddress::IsNil() const {
57 return IPIsUnspec(*this);
58}
59
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000060size_t IPAddress::Size() const {
61 switch (family_) {
62 case AF_INET:
63 return sizeof(in_addr);
64 case AF_INET6:
65 return sizeof(in6_addr);
66 }
67 return 0;
68}
69
Yves Gerey665174f2018-06-19 15:03:05 +020070bool IPAddress::operator==(const IPAddress& other) const {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000071 if (family_ != other.family_) {
72 return false;
73 }
74 if (family_ == AF_INET) {
75 return memcmp(&u_.ip4, &other.u_.ip4, sizeof(u_.ip4)) == 0;
76 }
77 if (family_ == AF_INET6) {
78 return memcmp(&u_.ip6, &other.u_.ip6, sizeof(u_.ip6)) == 0;
79 }
80 return family_ == AF_UNSPEC;
81}
82
Yves Gerey665174f2018-06-19 15:03:05 +020083bool IPAddress::operator!=(const IPAddress& other) const {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000084 return !((*this) == other);
85}
86
Yves Gerey665174f2018-06-19 15:03:05 +020087bool IPAddress::operator>(const IPAddress& other) const {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000088 return (*this) != other && !((*this) < other);
89}
90
Yves Gerey665174f2018-06-19 15:03:05 +020091bool IPAddress::operator<(const IPAddress& other) const {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000092 // IPv4 is 'less than' IPv6
93 if (family_ != other.family_) {
94 if (family_ == AF_UNSPEC) {
95 return true;
96 }
97 if (family_ == AF_INET && other.family_ == AF_INET6) {
98 return true;
99 }
100 return false;
101 }
102 // Comparing addresses of the same family.
103 switch (family_) {
104 case AF_INET: {
105 return NetworkToHost32(u_.ip4.s_addr) <
Yves Gerey665174f2018-06-19 15:03:05 +0200106 NetworkToHost32(other.u_.ip4.s_addr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000107 }
108 case AF_INET6: {
109 return memcmp(&u_.ip6.s6_addr, &other.u_.ip6.s6_addr, 16) < 0;
110 }
111 }
112 // Catches AF_UNSPEC and invalid addresses.
113 return false;
114}
115
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000116in6_addr IPAddress::ipv6_address() const {
117 return u_.ip6;
118}
119
120in_addr IPAddress::ipv4_address() const {
121 return u_.ip4;
122}
123
124std::string IPAddress::ToString() const {
125 if (family_ != AF_INET && family_ != AF_INET6) {
126 return std::string();
127 }
128 char buf[INET6_ADDRSTRLEN] = {0};
129 const void* src = &u_.ip4;
130 if (family_ == AF_INET6) {
131 src = &u_.ip6;
132 }
133 if (!rtc::inet_ntop(family_, src, buf, sizeof(buf))) {
134 return std::string();
135 }
136 return std::string(buf);
137}
138
139std::string IPAddress::ToSensitiveString() const {
Peter Boströmcdb38e52015-11-26 00:35:49 +0100140#if !defined(NDEBUG)
141 // Return non-stripped in debug.
142 return ToString();
143#else
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000144 switch (family_) {
145 case AF_INET: {
146 std::string address = ToString();
147 size_t find_pos = address.rfind('.');
148 if (find_pos == std::string::npos)
149 return std::string();
150 address.resize(find_pos);
151 address += ".x";
152 return address;
153 }
154 case AF_INET6: {
Sergey Ulanovbeed8282016-01-13 18:14:49 -0800155 std::string result;
156 result.resize(INET6_ADDRSTRLEN);
157 in6_addr addr = ipv6_address();
Niels Mölleraba06332018-10-16 15:14:15 +0200158 size_t len = snprintf(&(result[0]), result.size(), "%x:%x:%x:x:x:x:x:x",
159 (addr.s6_addr[0] << 8) + addr.s6_addr[1],
160 (addr.s6_addr[2] << 8) + addr.s6_addr[3],
161 (addr.s6_addr[4] << 8) + addr.s6_addr[5]);
Sergey Ulanovbeed8282016-01-13 18:14:49 -0800162 result.resize(len);
163 return result;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000164 }
165 }
166 return std::string();
Peter Boströmcdb38e52015-11-26 00:35:49 +0100167#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000168}
169
170IPAddress IPAddress::Normalized() const {
171 if (family_ != AF_INET6) {
172 return *this;
173 }
174 if (!IPIsV4Mapped(*this)) {
175 return *this;
176 }
177 in_addr addr = ExtractMappedAddress(u_.ip6);
178 return IPAddress(addr);
179}
180
181IPAddress IPAddress::AsIPv6Address() const {
182 if (family_ != AF_INET) {
183 return *this;
184 }
185 in6_addr v6addr = kV4MappedPrefix;
186 ::memcpy(&v6addr.s6_addr[12], &u_.ip4.s_addr, sizeof(u_.ip4.s_addr));
187 return IPAddress(v6addr);
188}
189
Yves Gerey665174f2018-06-19 15:03:05 +0200190bool InterfaceAddress::operator==(const InterfaceAddress& other) const {
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000191 return ipv6_flags_ == other.ipv6_flags() &&
Yves Gerey665174f2018-06-19 15:03:05 +0200192 static_cast<const IPAddress&>(*this) == other;
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000193}
194
Yves Gerey665174f2018-06-19 15:03:05 +0200195bool InterfaceAddress::operator!=(const InterfaceAddress& other) const {
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000196 return !((*this) == other);
197}
198
199const InterfaceAddress& InterfaceAddress::operator=(
Yves Gerey665174f2018-06-19 15:03:05 +0200200 const InterfaceAddress& other) {
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000201 ipv6_flags_ = other.ipv6_flags_;
202 static_cast<IPAddress&>(*this) = other;
203 return *this;
204}
205
Jonas Olsson74395342018-04-03 12:22:07 +0200206std::string InterfaceAddress::ToString() const {
207 std::string result = IPAddress::ToString();
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000208
Jonas Olsson74395342018-04-03 12:22:07 +0200209 if (family() == AF_INET6)
210 result += "|flags:0x" + rtc::ToHex(ipv6_flags());
211
212 return result;
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000213}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000214
Daniel Lazarenko2870b0a2018-01-25 10:30:22 +0100215static bool IPIsPrivateNetworkV4(const IPAddress& ip) {
216 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
217 return ((ip_in_host_order >> 24) == 10) ||
Yves Gerey665174f2018-06-19 15:03:05 +0200218 ((ip_in_host_order >> 20) == ((172 << 4) | 1)) ||
219 ((ip_in_host_order >> 16) == ((192 << 8) | 168));
Daniel Lazarenko2870b0a2018-01-25 10:30:22 +0100220}
221
222static bool IPIsPrivateNetworkV6(const IPAddress& ip) {
223 return IPIsHelper(ip, kPrivateNetworkPrefix, 8);
224}
225
226bool IPIsPrivateNetwork(const IPAddress& ip) {
227 switch (ip.family()) {
228 case AF_INET: {
229 return IPIsPrivateNetworkV4(ip);
230 }
231 case AF_INET6: {
232 return IPIsPrivateNetworkV6(ip);
233 }
234 }
235 return false;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000236}
237
Jeroen de Borstaf242c82019-04-24 13:13:48 -0700238static bool IPIsSharedNetworkV4(const IPAddress& ip) {
239 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
240 return (ip_in_host_order >> 22) == ((100 << 2) | 1);
241}
242
243bool IPIsSharedNetwork(const IPAddress& ip) {
244 if (ip.family() == AF_INET) {
245 return IPIsSharedNetworkV4(ip);
246 }
247 return false;
248}
249
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000250in_addr ExtractMappedAddress(const in6_addr& in6) {
251 in_addr ipv4;
252 ::memcpy(&ipv4.s_addr, &in6.s6_addr[12], sizeof(ipv4.s_addr));
253 return ipv4;
254}
255
256bool IPFromAddrInfo(struct addrinfo* info, IPAddress* out) {
257 if (!info || !info->ai_addr) {
258 return false;
259 }
260 if (info->ai_addr->sa_family == AF_INET) {
261 sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(info->ai_addr);
262 *out = IPAddress(addr->sin_addr);
263 return true;
264 } else if (info->ai_addr->sa_family == AF_INET6) {
265 sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(info->ai_addr);
266 *out = IPAddress(addr->sin6_addr);
267 return true;
268 }
269 return false;
270}
271
272bool IPFromString(const std::string& str, IPAddress* out) {
273 if (!out) {
274 return false;
275 }
276 in_addr addr;
277 if (rtc::inet_pton(AF_INET, str.c_str(), &addr) == 0) {
278 in6_addr addr6;
279 if (rtc::inet_pton(AF_INET6, str.c_str(), &addr6) == 0) {
280 *out = IPAddress();
281 return false;
282 }
283 *out = IPAddress(addr6);
284 } else {
285 *out = IPAddress(addr);
286 }
287 return true;
288}
289
Yves Gerey665174f2018-06-19 15:03:05 +0200290bool IPFromString(const std::string& str, int flags, InterfaceAddress* out) {
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000291 IPAddress ip;
292 if (!IPFromString(str, &ip)) {
293 return false;
294 }
295
296 *out = InterfaceAddress(ip, flags);
297 return true;
298}
299
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000300bool IPIsAny(const IPAddress& ip) {
301 switch (ip.family()) {
302 case AF_INET:
303 return ip == IPAddress(INADDR_ANY);
304 case AF_INET6:
guoweis@webrtc.org59ae5ff2015-03-01 23:45:16 +0000305 return ip == IPAddress(in6addr_any) || ip == IPAddress(kV4MappedPrefix);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000306 case AF_UNSPEC:
307 return false;
308 }
309 return false;
310}
311
Daniel Lazarenko2870b0a2018-01-25 10:30:22 +0100312static bool IPIsLoopbackV4(const IPAddress& ip) {
313 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
314 return ((ip_in_host_order >> 24) == 127);
315}
316
317static bool IPIsLoopbackV6(const IPAddress& ip) {
318 return ip == IPAddress(in6addr_loopback);
319}
320
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000321bool IPIsLoopback(const IPAddress& ip) {
322 switch (ip.family()) {
323 case AF_INET: {
Daniel Lazarenko2870b0a2018-01-25 10:30:22 +0100324 return IPIsLoopbackV4(ip);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000325 }
326 case AF_INET6: {
Daniel Lazarenko2870b0a2018-01-25 10:30:22 +0100327 return IPIsLoopbackV6(ip);
Yuwei Huangb181f712018-01-22 17:01:28 -0800328 }
329 }
330 return false;
331}
332
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000333bool IPIsPrivate(const IPAddress& ip) {
Jeroen de Borstaf242c82019-04-24 13:13:48 -0700334 return IPIsLinkLocal(ip) || IPIsLoopback(ip) || IPIsPrivateNetwork(ip) ||
335 IPIsSharedNetwork(ip);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000336}
337
338bool IPIsUnspec(const IPAddress& ip) {
339 return ip.family() == AF_UNSPEC;
340}
341
342size_t HashIP(const IPAddress& ip) {
343 switch (ip.family()) {
344 case AF_INET: {
345 return ip.ipv4_address().s_addr;
346 }
347 case AF_INET6: {
348 in6_addr v6addr = ip.ipv6_address();
Peter Boström0c4e06b2015-10-07 12:23:21 +0200349 const uint32_t* v6_as_ints =
350 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000351 return v6_as_ints[0] ^ v6_as_ints[1] ^ v6_as_ints[2] ^ v6_as_ints[3];
352 }
353 }
354 return 0;
355}
356
357IPAddress TruncateIP(const IPAddress& ip, int length) {
358 if (length < 0) {
359 return IPAddress();
360 }
361 if (ip.family() == AF_INET) {
362 if (length > 31) {
363 return ip;
364 }
365 if (length == 0) {
366 return IPAddress(INADDR_ANY);
367 }
368 int mask = (0xFFFFFFFF << (32 - length));
Peter Boström0c4e06b2015-10-07 12:23:21 +0200369 uint32_t host_order_ip = NetworkToHost32(ip.ipv4_address().s_addr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000370 in_addr masked;
371 masked.s_addr = HostToNetwork32(host_order_ip & mask);
372 return IPAddress(masked);
373 } else if (ip.family() == AF_INET6) {
374 if (length > 127) {
375 return ip;
376 }
377 if (length == 0) {
378 return IPAddress(in6addr_any);
379 }
380 in6_addr v6addr = ip.ipv6_address();
381 int position = length / 32;
382 int inner_length = 32 - (length - (position * 32));
383 // Note: 64bit mask constant needed to allow possible 32-bit left shift.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200384 uint32_t inner_mask = 0xFFFFFFFFLL << inner_length;
385 uint32_t* v6_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000386 for (int i = 0; i < 4; ++i) {
387 if (i == position) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200388 uint32_t host_order_inner = NetworkToHost32(v6_as_ints[i]);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000389 v6_as_ints[i] = HostToNetwork32(host_order_inner & inner_mask);
390 } else if (i > position) {
391 v6_as_ints[i] = 0;
392 }
393 }
394 return IPAddress(v6addr);
395 }
396 return IPAddress();
397}
398
399int CountIPMaskBits(IPAddress mask) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200400 uint32_t word_to_count = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000401 int bits = 0;
402 switch (mask.family()) {
403 case AF_INET: {
404 word_to_count = NetworkToHost32(mask.ipv4_address().s_addr);
405 break;
406 }
407 case AF_INET6: {
408 in6_addr v6addr = mask.ipv6_address();
Peter Boström0c4e06b2015-10-07 12:23:21 +0200409 const uint32_t* v6_as_ints =
410 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000411 int i = 0;
412 for (; i < 4; ++i) {
413 if (v6_as_ints[i] != 0xFFFFFFFF) {
414 break;
415 }
416 }
417 if (i < 4) {
418 word_to_count = NetworkToHost32(v6_as_ints[i]);
419 }
420 bits = (i * 32);
421 break;
422 }
Jeroen de Borstaf242c82019-04-24 13:13:48 -0700423 default: {
424 return 0;
425 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000426 }
427 if (word_to_count == 0) {
428 return bits;
429 }
430
431 // Public domain bit-twiddling hack from:
432 // http://graphics.stanford.edu/~seander/bithacks.html
433 // Counts the trailing 0s in the word.
434 unsigned int zeroes = 32;
tereliusd802b5b2016-03-01 11:07:34 -0800435 // This could also be written word_to_count &= -word_to_count, but
436 // MSVC emits warning C4146 when negating an unsigned number.
437 word_to_count &= ~word_to_count + 1; // Isolate lowest set bit.
Yves Gerey665174f2018-06-19 15:03:05 +0200438 if (word_to_count)
439 zeroes--;
440 if (word_to_count & 0x0000FFFF)
441 zeroes -= 16;
442 if (word_to_count & 0x00FF00FF)
443 zeroes -= 8;
444 if (word_to_count & 0x0F0F0F0F)
445 zeroes -= 4;
446 if (word_to_count & 0x33333333)
447 zeroes -= 2;
448 if (word_to_count & 0x55555555)
449 zeroes -= 1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000450
451 return bits + (32 - zeroes);
452}
453
454bool IPIsHelper(const IPAddress& ip, const in6_addr& tomatch, int length) {
455 // Helper method for checking IP prefix matches (but only on whole byte
456 // lengths). Length is in bits.
457 in6_addr addr = ip.ipv6_address();
458 return ::memcmp(&addr, &tomatch, (length >> 3)) == 0;
459}
460
461bool IPIs6Bone(const IPAddress& ip) {
462 return IPIsHelper(ip, k6BonePrefix, 16);
463}
464
465bool IPIs6To4(const IPAddress& ip) {
466 return IPIsHelper(ip, k6To4Prefix, 16);
467}
468
Daniel Lazarenko2870b0a2018-01-25 10:30:22 +0100469static bool IPIsLinkLocalV4(const IPAddress& ip) {
470 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
471 return ((ip_in_host_order >> 16) == ((169 << 8) | 254));
472}
473
474static bool IPIsLinkLocalV6(const IPAddress& ip) {
475 // Can't use the helper because the prefix is 10 bits.
476 in6_addr addr = ip.ipv6_address();
477 return (addr.s6_addr[0] == 0xFE) && ((addr.s6_addr[1] & 0xC0) == 0x80);
478}
479
480bool IPIsLinkLocal(const IPAddress& ip) {
481 switch (ip.family()) {
482 case AF_INET: {
483 return IPIsLinkLocalV4(ip);
484 }
485 case AF_INET6: {
486 return IPIsLinkLocalV6(ip);
487 }
488 }
489 return false;
490}
491
guoweis@webrtc.orgb91d0f52015-03-17 14:43:20 +0000492// According to http://www.ietf.org/rfc/rfc2373.txt, Appendix A, page 19. An
493// address which contains MAC will have its 11th and 12th bytes as FF:FE as well
494// as the U/L bit as 1.
495bool IPIsMacBased(const IPAddress& ip) {
496 in6_addr addr = ip.ipv6_address();
497 return ((addr.s6_addr[8] & 0x02) && addr.s6_addr[11] == 0xFF &&
498 addr.s6_addr[12] == 0xFE);
guoweis@webrtc.orgbbce5ef2015-03-05 04:38:29 +0000499}
500
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000501bool IPIsSiteLocal(const IPAddress& ip) {
502 // Can't use the helper because the prefix is 10 bits.
503 in6_addr addr = ip.ipv6_address();
504 return addr.s6_addr[0] == 0xFE && (addr.s6_addr[1] & 0xC0) == 0xC0;
505}
506
507bool IPIsULA(const IPAddress& ip) {
508 // Can't use the helper because the prefix is 7 bits.
509 in6_addr addr = ip.ipv6_address();
510 return (addr.s6_addr[0] & 0xFE) == 0xFC;
511}
512
513bool IPIsTeredo(const IPAddress& ip) {
514 return IPIsHelper(ip, kTeredoPrefix, 32);
515}
516
517bool IPIsV4Compatibility(const IPAddress& ip) {
518 return IPIsHelper(ip, kV4CompatibilityPrefix, 96);
519}
520
521bool IPIsV4Mapped(const IPAddress& ip) {
522 return IPIsHelper(ip, kV4MappedPrefix, 96);
523}
524
525int IPAddressPrecedence(const IPAddress& ip) {
526 // Precedence values from RFC 3484-bis. Prefers native v4 over 6to4/Teredo.
527 if (ip.family() == AF_INET) {
528 return 30;
529 } else if (ip.family() == AF_INET6) {
530 if (IPIsLoopback(ip)) {
531 return 60;
532 } else if (IPIsULA(ip)) {
533 return 50;
534 } else if (IPIsV4Mapped(ip)) {
535 return 30;
536 } else if (IPIs6To4(ip)) {
537 return 20;
538 } else if (IPIsTeredo(ip)) {
539 return 10;
540 } else if (IPIsV4Compatibility(ip) || IPIsSiteLocal(ip) || IPIs6Bone(ip)) {
541 return 1;
542 } else {
543 // A 'normal' IPv6 address.
544 return 40;
545 }
546 }
547 return 0;
548}
549
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700550IPAddress GetLoopbackIP(int family) {
551 if (family == AF_INET) {
552 return rtc::IPAddress(INADDR_LOOPBACK);
553 }
554 if (family == AF_INET6) {
555 return rtc::IPAddress(in6addr_loopback);
556 }
557 return rtc::IPAddress();
558}
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800559
560IPAddress GetAnyIP(int family) {
561 if (family == AF_INET) {
562 return rtc::IPAddress(INADDR_ANY);
563 }
564 if (family == AF_INET6) {
565 return rtc::IPAddress(in6addr_any);
566 }
567 return rtc::IPAddress();
568}
569
tereliusd802b5b2016-03-01 11:07:34 -0800570} // namespace rtc