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