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/posix/eintr_wrapper.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
30namespace net {
31
32bool 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
66bool GetNetworkList(NetworkInterfaceList* networks) {
67#if defined(OS_ANDROID)
68  std::string network_list = android::GetNetworkList();
69  base::StringTokenizer network_interfaces(network_list, ";");
70  while (network_interfaces.GetNext()) {
71    std::string network_item = network_interfaces.token();
72    base::StringTokenizer network_tokenizer(network_item, ",");
73    std::string name;
74    if (!network_tokenizer.GetNext())
75      continue;
76    name = network_tokenizer.token();
77
78    std::string literal_address;
79    if (!network_tokenizer.GetNext())
80      continue;
81    literal_address = network_tokenizer.token();
82
83    IPAddressNumber address;
84    if (!ParseIPLiteralToNumber(literal_address, &address))
85      continue;
86    networks->push_back(NetworkInterface(name, address));
87  }
88  return true;
89#else
90  // getifaddrs() may require IO operations.
91  base::ThreadRestrictions::AssertIOAllowed();
92
93  ifaddrs *interfaces;
94  if (getifaddrs(&interfaces) < 0) {
95    PLOG(ERROR) << "getifaddrs";
96    return false;
97  }
98
99  // Enumerate the addresses assigned to network interfaces which are up.
100  for (ifaddrs *interface = interfaces;
101       interface != NULL;
102       interface = interface->ifa_next) {
103    // Skip loopback interfaces, and ones which are down.
104    if (!(IFF_UP & interface->ifa_flags))
105      continue;
106    if (IFF_LOOPBACK & interface->ifa_flags)
107      continue;
108    // Skip interfaces with no address configured.
109    struct sockaddr* addr = interface->ifa_addr;
110    if (!addr)
111      continue;
112    // Skip unspecified addresses (i.e. made of zeroes) and loopback addresses
113    // configured on non-loopback interfaces.
114    int addr_size = 0;
115    if (addr->sa_family == AF_INET6) {
116      struct sockaddr_in6* addr_in6 =
117          reinterpret_cast<struct sockaddr_in6*>(addr);
118      struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
119      addr_size = sizeof(*addr_in6);
120      if (IN6_IS_ADDR_LOOPBACK(sin6_addr) ||
121          IN6_IS_ADDR_UNSPECIFIED(sin6_addr)) {
122        continue;
123      }
124    } else if (addr->sa_family == AF_INET) {
125      struct sockaddr_in* addr_in =
126          reinterpret_cast<struct sockaddr_in*>(addr);
127      addr_size = sizeof(*addr_in);
128      if (addr_in->sin_addr.s_addr == INADDR_LOOPBACK ||
129          addr_in->sin_addr.s_addr == 0) {
130        continue;
131      }
132    } else {
133      // Skip non-IP addresses.
134      continue;
135    }
136    IPEndPoint address;
137    std::string name = interface->ifa_name;
138    if (address.FromSockAddr(addr, addr_size)) {
139      networks->push_back(NetworkInterface(name, address.address()));
140    }
141  }
142
143  freeifaddrs(interfaces);
144
145  return true;
146#endif
147}
148
149WifiPHYLayerProtocol GetWifiPHYLayerProtocol() {
150  return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
151}
152
153}  // namespace net
154