Index: net/base/net_util_linux.cc |
diff --git a/net/base/net_util_linux.cc b/net/base/net_util_linux.cc |
index e4e0f7f3277e9110cb944ea0714ea9136f36ea18..36c9eb706ecfdaaa4d5cff4abdc73aac357795fd 100644 |
--- a/net/base/net_util_linux.cc |
+++ b/net/base/net_util_linux.cc |
@@ -4,12 +4,18 @@ |
#include "net/base/net_util_linux.h" |
-#include <net/if.h> |
-#include <netinet/in.h> |
+#if !defined(OS_ANDROID) |
+#include <linux/ethtool.h> |
+#endif // !defined(OS_ANDROID) |
+#include <linux/if.h> |
+#include <linux/sockios.h> |
+#include <linux/wireless.h> |
#include <set> |
+#include <sys/ioctl.h> |
#include <sys/types.h> |
#include "base/files/file_path.h" |
+#include "base/files/scoped_file.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/strings/string_number_conversions.h" |
@@ -69,6 +75,34 @@ inline const unsigned char* GetIPAddressData(const IPAddressNumber& ip) { |
#endif |
} |
+// Gets the connection type for interface |ifname| by checking for wireless |
+// or ethtool extensions. |
+NetworkChangeNotifier::ConnectionType GetInterfaceConnectionType( |
+ const std::string& ifname) { |
+ base::ScopedFD s(socket(AF_INET, SOCK_STREAM, 0)); |
+ if (!s.is_valid()) |
+ return NetworkChangeNotifier::CONNECTION_UNKNOWN; |
+ |
+ // Test wireless extensions for CONNECTION_WIFI |
+ struct iwreq pwrq = {}; |
+ strncpy(pwrq.ifr_name, ifname.c_str(), IFNAMSIZ - 1); |
+ if (ioctl(s.get(), SIOCGIWNAME, &pwrq) != -1) |
+ return NetworkChangeNotifier::CONNECTION_WIFI; |
+ |
+#if !defined(OS_ANDROID) |
+ // Test ethtool for CONNECTION_ETHERNET |
+ struct ethtool_cmd ecmd = {}; |
+ ecmd.cmd = ETHTOOL_GSET; |
+ struct ifreq ifr = {}; |
+ ifr.ifr_data = &ecmd; |
+ strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1); |
+ if (ioctl(s.get(), SIOCETHTOOL, &ifr) != -1) |
+ return NetworkChangeNotifier::CONNECTION_ETHERNET; |
+#endif // !defined(OS_ANDROID) |
+ |
+ return NetworkChangeNotifier::CONNECTION_UNKNOWN; |
+} |
+ |
bool GetNetworkListImpl( |
NetworkInterfaceList* networks, |
int policy, |
@@ -112,13 +146,12 @@ bool GetNetworkListImpl( |
ifnames.find(it->second.ifa_index); |
std::string ifname; |
if (itname == ifnames.end()) { |
- char buffer[IF_NAMESIZE] = {0}; |
- if (get_interface_name(it->second.ifa_index, buffer)) { |
- ifname = ifnames[it->second.ifa_index] = buffer; |
- } else { |
- // Ignore addresses whose interface name can't be retrieved. |
+ char buffer[IFNAMSIZ] = {0}; |
+ ifname.assign(get_interface_name(it->second.ifa_index, buffer)); |
+ // Ignore addresses whose interface name can't be retrieved. |
+ if (ifname.empty()) |
continue; |
- } |
+ ifnames[it->second.ifa_index] = ifname; |
} else { |
ifname = itname->second; |
} |
@@ -128,9 +161,11 @@ bool GetNetworkListImpl( |
if (ShouldIgnoreInterface(ifname, policy)) |
continue; |
+ NetworkChangeNotifier::ConnectionType type = |
+ GetInterfaceConnectionType(ifname); |
+ |
networks->push_back( |
- NetworkInterface(ifname, ifname, it->second.ifa_index, |
- NetworkChangeNotifier::CONNECTION_UNKNOWN, it->first, |
+ NetworkInterface(ifname, ifname, it->second.ifa_index, type, it->first, |
it->second.ifa_prefixlen, ip_attributes)); |
} |
@@ -146,9 +181,9 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { |
internal::AddressTrackerLinux tracker; |
tracker.Init(); |
- return internal::GetNetworkListImpl(networks, policy, |
- tracker.GetOnlineLinks(), |
- tracker.GetAddressMap(), &if_indextoname); |
+ return internal::GetNetworkListImpl( |
+ networks, policy, tracker.GetOnlineLinks(), tracker.GetAddressMap(), |
+ &internal::AddressTrackerLinux::GetInterfaceName); |
} |
} // namespace net |