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
FileURLToFilePath(const GURL & url,base::FilePath * path)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
GetNetworkList(NetworkInterfaceList * networks)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
GetWifiPHYLayerProtocol()164 WifiPHYLayerProtocol GetWifiPHYLayerProtocol() {
165 return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
166 }
167
168 } // namespace net
169