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