• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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