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