Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/base/net_util.h"
      6 
      7 #include <sys/types.h>
      8 
      9 #include "base/files/file_path.h"
     10 #include "base/logging.h"
     11 #include "base/strings/string_number_conversions.h"
     12 #include "base/strings/string_tokenizer.h"
     13 #include "base/strings/string_util.h"
     14 #include "base/threading/thread_restrictions.h"
     15 #include "net/base/escape.h"
     16 #include "net/base/ip_endpoint.h"
     17 #include "net/base/net_errors.h"
     18 #include "url/gurl.h"
     19 
     20 #if !defined(OS_ANDROID)
     21 #include <ifaddrs.h>
     22 #endif
     23 #include <net/if.h>
     24 #include <netinet/in.h>
     25 
     26 #if defined(OS_ANDROID)
     27 #include "net/android/network_library.h"
     28 #endif
     29 
     30 namespace net {
     31 
     32 bool FileURLToFilePath(const GURL& url, base::FilePath* path) {
     33   *path = base::FilePath();
     34   std::string& file_path_str = const_cast<std::string&>(path->value());
     35   file_path_str.clear();
     36 
     37   if (!url.is_valid())
     38     return false;
     39 
     40   // Firefox seems to ignore the "host" of a file url if there is one. That is,
     41   // file://foo/bar.txt maps to /bar.txt.
     42   // TODO(dhg): This should probably take into account UNCs which could
     43   // include a hostname other than localhost or blank
     44   std::string old_path = url.path();
     45 
     46   if (old_path.empty())
     47     return false;
     48 
     49   // GURL stores strings as percent-encoded 8-bit, this will undo if possible.
     50   old_path = UnescapeURLComponent(old_path,
     51       UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
     52 
     53   // Collapse multiple path slashes into a single path slash.
     54   std::string new_path;
     55   do {
     56     new_path = old_path;
     57     ReplaceSubstringsAfterOffset(&new_path, 0, "//", "/");
     58     old_path.swap(new_path);
     59   } while (new_path != old_path);
     60 
     61   file_path_str.assign(old_path);
     62 
     63   return !file_path_str.empty();
     64 }
     65 
     66 bool GetNetworkList(NetworkInterfaceList* networks) {
     67 #if defined(OS_ANDROID)
     68   std::string network_list = android::GetNetworkList();
     69   base::StringTokenizer network_interfaces(network_list, "\n");
     70   while (network_interfaces.GetNext()) {
     71     std::string network_item = network_interfaces.token();
     72     base::StringTokenizer network_tokenizer(network_item, "\t");
     73     CHECK(network_tokenizer.GetNext());
     74     std::string name = network_tokenizer.token();
     75 
     76     CHECK(network_tokenizer.GetNext());
     77     std::string interface_address = network_tokenizer.token();
     78     IPAddressNumber address;
     79     size_t network_prefix = 0;
     80     CHECK(ParseCIDRBlock(network_tokenizer.token(),
     81                          &address,
     82                          &network_prefix));
     83 
     84     CHECK(network_tokenizer.GetNext());
     85     uint32 index = 0;
     86     CHECK(base::StringToUint(network_tokenizer.token(), &index));
     87 
     88     networks->push_back(
     89         NetworkInterface(name, index, address, network_prefix));
     90   }
     91   return true;
     92 #else
     93   // getifaddrs() may require IO operations.
     94   base::ThreadRestrictions::AssertIOAllowed();
     95 
     96   ifaddrs *interfaces;
     97   if (getifaddrs(&interfaces) < 0) {
     98     PLOG(ERROR) << "getifaddrs";
     99     return false;
    100   }
    101 
    102   // Enumerate the addresses assigned to network interfaces which are up.
    103   for (ifaddrs *interface = interfaces;
    104        interface != NULL;
    105        interface = interface->ifa_next) {
    106     // Skip loopback interfaces, and ones which are down.
    107     if (!(IFF_UP & interface->ifa_flags))
    108       continue;
    109     if (IFF_LOOPBACK & interface->ifa_flags)
    110       continue;
    111     // Skip interfaces with no address configured.
    112     struct sockaddr* addr = interface->ifa_addr;
    113     if (!addr)
    114       continue;
    115 
    116     // Skip unspecified addresses (i.e. made of zeroes) and loopback addresses
    117     // configured on non-loopback interfaces.
    118     int addr_size = 0;
    119     if (addr->sa_family == AF_INET6) {
    120       struct sockaddr_in6* addr_in6 =
    121           reinterpret_cast<struct sockaddr_in6*>(addr);
    122       struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
    123       addr_size = sizeof(*addr_in6);
    124       if (IN6_IS_ADDR_LOOPBACK(sin6_addr) ||
    125           IN6_IS_ADDR_UNSPECIFIED(sin6_addr)) {
    126         continue;
    127       }
    128     } else if (addr->sa_family == AF_INET) {
    129       struct sockaddr_in* addr_in =
    130           reinterpret_cast<struct sockaddr_in*>(addr);
    131       addr_size = sizeof(*addr_in);
    132       if (addr_in->sin_addr.s_addr == INADDR_LOOPBACK ||
    133           addr_in->sin_addr.s_addr == 0) {
    134         continue;
    135       }
    136     } else {
    137       // Skip non-IP addresses.
    138       continue;
    139     }
    140 
    141     IPEndPoint address;
    142     std::string name = interface->ifa_name;
    143     if (address.FromSockAddr(addr, addr_size)) {
    144       uint8 net_mask = 0;
    145       if (interface->ifa_netmask) {
    146         IPEndPoint netmask;
    147         if (netmask.FromSockAddr(interface->ifa_netmask, addr_size)) {
    148           net_mask = MaskPrefixLength(netmask.address());
    149         }
    150       }
    151 
    152       networks->push_back(
    153           NetworkInterface(name, if_nametoindex(name.c_str()),
    154                            address.address(), net_mask));
    155     }
    156   }
    157 
    158   freeifaddrs(interfaces);
    159 
    160   return true;
    161 #endif
    162 }
    163 
    164 WifiPHYLayerProtocol GetWifiPHYLayerProtocol() {
    165   return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
    166 }
    167 
    168 }  // namespace net
    169