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 #if defined(WEBRTC_BSD)
15 #include <sys/types.h>
16 #endif
17 #ifdef OPENBSD
18 #include <netinet/in_systm.h>
19 #endif
20 #ifndef __native_client__
21 #include <netinet/ip.h>
22 #endif
23 #include <netdb.h>
24 #endif
25
26 #include "rtc_base/byte_order.h"
27 #include "rtc_base/ip_address.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 #if !defined(NDEBUG)
155 // Return non-stripped in debug.
156 return ToString();
157 #else
158 switch (family_) {
159 case AF_INET: {
160 std::string address = ToString();
161 size_t find_pos = address.rfind('.');
162 if (find_pos == std::string::npos)
163 return std::string();
164 address.resize(find_pos);
165 address += ".x";
166 return address;
167 }
168 case AF_INET6: {
169 std::string result;
170 result.resize(INET6_ADDRSTRLEN);
171 in6_addr addr = ipv6_address();
172 size_t len = snprintf(&(result[0]), result.size(), "%x:%x:%x:x:x:x:x:x",
173 (addr.s6_addr[0] << 8) + addr.s6_addr[1],
174 (addr.s6_addr[2] << 8) + addr.s6_addr[3],
175 (addr.s6_addr[4] << 8) + addr.s6_addr[5]);
176 result.resize(len);
177 return result;
178 }
179 }
180 return std::string();
181 #endif
182 }
183
Normalized() const184 IPAddress IPAddress::Normalized() const {
185 if (family_ != AF_INET6) {
186 return *this;
187 }
188 if (!IPIsV4Mapped(*this)) {
189 return *this;
190 }
191 in_addr addr = ExtractMappedAddress(u_.ip6);
192 return IPAddress(addr);
193 }
194
AsIPv6Address() const195 IPAddress IPAddress::AsIPv6Address() const {
196 if (family_ != AF_INET) {
197 return *this;
198 }
199 in6_addr v6addr = kV4MappedPrefix;
200 ::memcpy(&v6addr.s6_addr[12], &u_.ip4.s_addr, sizeof(u_.ip4.s_addr));
201 return IPAddress(v6addr);
202 }
203
operator ==(const InterfaceAddress & other) const204 bool InterfaceAddress::operator==(const InterfaceAddress& other) const {
205 return ipv6_flags_ == other.ipv6_flags() &&
206 static_cast<const IPAddress&>(*this) == other;
207 }
208
operator !=(const InterfaceAddress & other) const209 bool InterfaceAddress::operator!=(const InterfaceAddress& other) const {
210 return !((*this) == other);
211 }
212
operator =(const InterfaceAddress & other)213 const InterfaceAddress& InterfaceAddress::operator=(
214 const InterfaceAddress& other) {
215 ipv6_flags_ = other.ipv6_flags_;
216 static_cast<IPAddress&>(*this) = other;
217 return *this;
218 }
219
ToString() const220 std::string InterfaceAddress::ToString() const {
221 std::string result = IPAddress::ToString();
222
223 if (family() == AF_INET6)
224 result += "|flags:0x" + rtc::ToHex(ipv6_flags());
225
226 return result;
227 }
228
IPIsPrivateNetworkV4(const IPAddress & ip)229 static bool IPIsPrivateNetworkV4(const IPAddress& ip) {
230 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
231 return ((ip_in_host_order >> 24) == 10) ||
232 ((ip_in_host_order >> 20) == ((172 << 4) | 1)) ||
233 ((ip_in_host_order >> 16) == ((192 << 8) | 168));
234 }
235
IPIsPrivateNetworkV6(const IPAddress & ip)236 static bool IPIsPrivateNetworkV6(const IPAddress& ip) {
237 return IPIsHelper(ip, kPrivateNetworkPrefix, 8);
238 }
239
IPIsPrivateNetwork(const IPAddress & ip)240 bool IPIsPrivateNetwork(const IPAddress& ip) {
241 switch (ip.family()) {
242 case AF_INET: {
243 return IPIsPrivateNetworkV4(ip);
244 }
245 case AF_INET6: {
246 return IPIsPrivateNetworkV6(ip);
247 }
248 }
249 return false;
250 }
251
IPIsSharedNetworkV4(const IPAddress & ip)252 static bool IPIsSharedNetworkV4(const IPAddress& ip) {
253 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
254 return (ip_in_host_order >> 22) == ((100 << 2) | 1);
255 }
256
IPIsSharedNetwork(const IPAddress & ip)257 bool IPIsSharedNetwork(const IPAddress& ip) {
258 if (ip.family() == AF_INET) {
259 return IPIsSharedNetworkV4(ip);
260 }
261 return false;
262 }
263
ExtractMappedAddress(const in6_addr & in6)264 in_addr ExtractMappedAddress(const in6_addr& in6) {
265 in_addr ipv4;
266 ::memcpy(&ipv4.s_addr, &in6.s6_addr[12], sizeof(ipv4.s_addr));
267 return ipv4;
268 }
269
IPFromAddrInfo(struct addrinfo * info,IPAddress * out)270 bool IPFromAddrInfo(struct addrinfo* info, IPAddress* out) {
271 if (!info || !info->ai_addr) {
272 return false;
273 }
274 if (info->ai_addr->sa_family == AF_INET) {
275 sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(info->ai_addr);
276 *out = IPAddress(addr->sin_addr);
277 return true;
278 } else if (info->ai_addr->sa_family == AF_INET6) {
279 sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(info->ai_addr);
280 *out = IPAddress(addr->sin6_addr);
281 return true;
282 }
283 return false;
284 }
285
IPFromString(const std::string & str,IPAddress * out)286 bool IPFromString(const std::string& str, IPAddress* out) {
287 if (!out) {
288 return false;
289 }
290 in_addr addr;
291 if (rtc::inet_pton(AF_INET, str.c_str(), &addr) == 0) {
292 in6_addr addr6;
293 if (rtc::inet_pton(AF_INET6, str.c_str(), &addr6) == 0) {
294 *out = IPAddress();
295 return false;
296 }
297 *out = IPAddress(addr6);
298 } else {
299 *out = IPAddress(addr);
300 }
301 return true;
302 }
303
IPFromString(const std::string & str,int flags,InterfaceAddress * out)304 bool IPFromString(const std::string& str, int flags, InterfaceAddress* out) {
305 IPAddress ip;
306 if (!IPFromString(str, &ip)) {
307 return false;
308 }
309
310 *out = InterfaceAddress(ip, flags);
311 return true;
312 }
313
IPIsAny(const IPAddress & ip)314 bool IPIsAny(const IPAddress& ip) {
315 switch (ip.family()) {
316 case AF_INET:
317 return ip == IPAddress(INADDR_ANY);
318 case AF_INET6:
319 return ip == IPAddress(in6addr_any) || ip == IPAddress(kV4MappedPrefix);
320 case AF_UNSPEC:
321 return false;
322 }
323 return false;
324 }
325
IPIsLoopbackV4(const IPAddress & ip)326 static bool IPIsLoopbackV4(const IPAddress& ip) {
327 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
328 return ((ip_in_host_order >> 24) == 127);
329 }
330
IPIsLoopbackV6(const IPAddress & ip)331 static bool IPIsLoopbackV6(const IPAddress& ip) {
332 return ip == IPAddress(in6addr_loopback);
333 }
334
IPIsLoopback(const IPAddress & ip)335 bool IPIsLoopback(const IPAddress& ip) {
336 switch (ip.family()) {
337 case AF_INET: {
338 return IPIsLoopbackV4(ip);
339 }
340 case AF_INET6: {
341 return IPIsLoopbackV6(ip);
342 }
343 }
344 return false;
345 }
346
IPIsPrivate(const IPAddress & ip)347 bool IPIsPrivate(const IPAddress& ip) {
348 return IPIsLinkLocal(ip) || IPIsLoopback(ip) || IPIsPrivateNetwork(ip) ||
349 IPIsSharedNetwork(ip);
350 }
351
IPIsUnspec(const IPAddress & ip)352 bool IPIsUnspec(const IPAddress& ip) {
353 return ip.family() == AF_UNSPEC;
354 }
355
HashIP(const IPAddress & ip)356 size_t HashIP(const IPAddress& ip) {
357 switch (ip.family()) {
358 case AF_INET: {
359 return ip.ipv4_address().s_addr;
360 }
361 case AF_INET6: {
362 in6_addr v6addr = ip.ipv6_address();
363 const uint32_t* v6_as_ints =
364 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr);
365 return v6_as_ints[0] ^ v6_as_ints[1] ^ v6_as_ints[2] ^ v6_as_ints[3];
366 }
367 }
368 return 0;
369 }
370
TruncateIP(const IPAddress & ip,int length)371 IPAddress TruncateIP(const IPAddress& ip, int length) {
372 if (length < 0) {
373 return IPAddress();
374 }
375 if (ip.family() == AF_INET) {
376 if (length > 31) {
377 return ip;
378 }
379 if (length == 0) {
380 return IPAddress(INADDR_ANY);
381 }
382 int mask = (0xFFFFFFFF << (32 - length));
383 uint32_t host_order_ip = NetworkToHost32(ip.ipv4_address().s_addr);
384 in_addr masked;
385 masked.s_addr = HostToNetwork32(host_order_ip & mask);
386 return IPAddress(masked);
387 } else if (ip.family() == AF_INET6) {
388 if (length > 127) {
389 return ip;
390 }
391 if (length == 0) {
392 return IPAddress(in6addr_any);
393 }
394 in6_addr v6addr = ip.ipv6_address();
395 int position = length / 32;
396 int inner_length = 32 - (length - (position * 32));
397 // Note: 64bit mask constant needed to allow possible 32-bit left shift.
398 uint32_t inner_mask = 0xFFFFFFFFLL << inner_length;
399 uint32_t* v6_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr);
400 for (int i = 0; i < 4; ++i) {
401 if (i == position) {
402 uint32_t host_order_inner = NetworkToHost32(v6_as_ints[i]);
403 v6_as_ints[i] = HostToNetwork32(host_order_inner & inner_mask);
404 } else if (i > position) {
405 v6_as_ints[i] = 0;
406 }
407 }
408 return IPAddress(v6addr);
409 }
410 return IPAddress();
411 }
412
CountIPMaskBits(const IPAddress & mask)413 int CountIPMaskBits(const IPAddress& mask) {
414 uint32_t word_to_count = 0;
415 int bits = 0;
416 switch (mask.family()) {
417 case AF_INET: {
418 word_to_count = NetworkToHost32(mask.ipv4_address().s_addr);
419 break;
420 }
421 case AF_INET6: {
422 in6_addr v6addr = mask.ipv6_address();
423 const uint32_t* v6_as_ints =
424 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr);
425 int i = 0;
426 for (; i < 4; ++i) {
427 if (v6_as_ints[i] != 0xFFFFFFFF) {
428 break;
429 }
430 }
431 if (i < 4) {
432 word_to_count = NetworkToHost32(v6_as_ints[i]);
433 }
434 bits = (i * 32);
435 break;
436 }
437 default: {
438 return 0;
439 }
440 }
441 if (word_to_count == 0) {
442 return bits;
443 }
444
445 // Public domain bit-twiddling hack from:
446 // http://graphics.stanford.edu/~seander/bithacks.html
447 // Counts the trailing 0s in the word.
448 unsigned int zeroes = 32;
449 // This could also be written word_to_count &= -word_to_count, but
450 // MSVC emits warning C4146 when negating an unsigned number.
451 word_to_count &= ~word_to_count + 1; // Isolate lowest set bit.
452 if (word_to_count)
453 zeroes--;
454 if (word_to_count & 0x0000FFFF)
455 zeroes -= 16;
456 if (word_to_count & 0x00FF00FF)
457 zeroes -= 8;
458 if (word_to_count & 0x0F0F0F0F)
459 zeroes -= 4;
460 if (word_to_count & 0x33333333)
461 zeroes -= 2;
462 if (word_to_count & 0x55555555)
463 zeroes -= 1;
464
465 return bits + (32 - zeroes);
466 }
467
IPIsHelper(const IPAddress & ip,const in6_addr & tomatch,int length)468 bool IPIsHelper(const IPAddress& ip, const in6_addr& tomatch, int length) {
469 // Helper method for checking IP prefix matches (but only on whole byte
470 // lengths). Length is in bits.
471 in6_addr addr = ip.ipv6_address();
472 return ::memcmp(&addr, &tomatch, (length >> 3)) == 0;
473 }
474
IPIs6Bone(const IPAddress & ip)475 bool IPIs6Bone(const IPAddress& ip) {
476 return IPIsHelper(ip, k6BonePrefix, 16);
477 }
478
IPIs6To4(const IPAddress & ip)479 bool IPIs6To4(const IPAddress& ip) {
480 return IPIsHelper(ip, k6To4Prefix, 16);
481 }
482
IPIsLinkLocalV4(const IPAddress & ip)483 static bool IPIsLinkLocalV4(const IPAddress& ip) {
484 uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
485 return ((ip_in_host_order >> 16) == ((169 << 8) | 254));
486 }
487
IPIsLinkLocalV6(const IPAddress & ip)488 static bool IPIsLinkLocalV6(const IPAddress& ip) {
489 // Can't use the helper because the prefix is 10 bits.
490 in6_addr addr = ip.ipv6_address();
491 return (addr.s6_addr[0] == 0xFE) && ((addr.s6_addr[1] & 0xC0) == 0x80);
492 }
493
IPIsLinkLocal(const IPAddress & ip)494 bool IPIsLinkLocal(const IPAddress& ip) {
495 switch (ip.family()) {
496 case AF_INET: {
497 return IPIsLinkLocalV4(ip);
498 }
499 case AF_INET6: {
500 return IPIsLinkLocalV6(ip);
501 }
502 }
503 return false;
504 }
505
506 // According to http://www.ietf.org/rfc/rfc2373.txt, Appendix A, page 19. An
507 // address which contains MAC will have its 11th and 12th bytes as FF:FE as well
508 // as the U/L bit as 1.
IPIsMacBased(const IPAddress & ip)509 bool IPIsMacBased(const IPAddress& ip) {
510 in6_addr addr = ip.ipv6_address();
511 return ((addr.s6_addr[8] & 0x02) && addr.s6_addr[11] == 0xFF &&
512 addr.s6_addr[12] == 0xFE);
513 }
514
IPIsSiteLocal(const IPAddress & ip)515 bool IPIsSiteLocal(const IPAddress& ip) {
516 // Can't use the helper because the prefix is 10 bits.
517 in6_addr addr = ip.ipv6_address();
518 return addr.s6_addr[0] == 0xFE && (addr.s6_addr[1] & 0xC0) == 0xC0;
519 }
520
IPIsULA(const IPAddress & ip)521 bool IPIsULA(const IPAddress& ip) {
522 // Can't use the helper because the prefix is 7 bits.
523 in6_addr addr = ip.ipv6_address();
524 return (addr.s6_addr[0] & 0xFE) == 0xFC;
525 }
526
IPIsTeredo(const IPAddress & ip)527 bool IPIsTeredo(const IPAddress& ip) {
528 return IPIsHelper(ip, kTeredoPrefix, 32);
529 }
530
IPIsV4Compatibility(const IPAddress & ip)531 bool IPIsV4Compatibility(const IPAddress& ip) {
532 return IPIsHelper(ip, kV4CompatibilityPrefix, 96);
533 }
534
IPIsV4Mapped(const IPAddress & ip)535 bool IPIsV4Mapped(const IPAddress& ip) {
536 return IPIsHelper(ip, kV4MappedPrefix, 96);
537 }
538
IPAddressPrecedence(const IPAddress & ip)539 int IPAddressPrecedence(const IPAddress& ip) {
540 // Precedence values from RFC 3484-bis. Prefers native v4 over 6to4/Teredo.
541 if (ip.family() == AF_INET) {
542 return 30;
543 } else if (ip.family() == AF_INET6) {
544 if (IPIsLoopback(ip)) {
545 return 60;
546 } else if (IPIsULA(ip)) {
547 return 50;
548 } else if (IPIsV4Mapped(ip)) {
549 return 30;
550 } else if (IPIs6To4(ip)) {
551 return 20;
552 } else if (IPIsTeredo(ip)) {
553 return 10;
554 } else if (IPIsV4Compatibility(ip) || IPIsSiteLocal(ip) || IPIs6Bone(ip)) {
555 return 1;
556 } else {
557 // A 'normal' IPv6 address.
558 return 40;
559 }
560 }
561 return 0;
562 }
563
GetLoopbackIP(int family)564 IPAddress GetLoopbackIP(int family) {
565 if (family == AF_INET) {
566 return rtc::IPAddress(INADDR_LOOPBACK);
567 }
568 if (family == AF_INET6) {
569 return rtc::IPAddress(in6addr_loopback);
570 }
571 return rtc::IPAddress();
572 }
573
GetAnyIP(int family)574 IPAddress GetAnyIP(int family) {
575 if (family == AF_INET) {
576 return rtc::IPAddress(INADDR_ANY);
577 }
578 if (family == AF_INET6) {
579 return rtc::IPAddress(in6addr_any);
580 }
581 return rtc::IPAddress();
582 }
583
584 } // namespace rtc
585