Index: net/base/address_tracker_linux.cc |
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc |
index 27dd2019ab0dffd6392dee105b7ae11ba7b6e138..e4d472d9efbba9ad7df95d16543f045564b01088 100644 |
--- a/net/base/address_tracker_linux.cc |
+++ b/net/base/address_tracker_linux.cc |
@@ -6,17 +6,48 @@ |
#include <errno.h> |
#include <linux/if.h> |
+#include <linux/wireless.h> |
#include <sys/ioctl.h> |
#include "base/logging.h" |
#include "base/posix/eintr_wrapper.h" |
#include "base/threading/thread_restrictions.h" |
+#include "net/base/ip_endpoint.h" |
+#include "net/base/net_util_linux.h" |
+#include "net/base/net_util_posix.h" |
namespace net { |
namespace internal { |
namespace { |
+// Gets the connection type for interface |ifname| by checking for wireless |
+// extensions. It is assumed for linux that if there are no extensions that |
+// the device is ethernet. |
+NetworkChangeNotifier::ConnectionType |
+GetInterfaceConnectionType(std::string ifname) { |
+ NetworkChangeNotifier::ConnectionType type = |
+ NetworkChangeNotifier::CONNECTION_UNKNOWN; |
+ |
+ int s = socket(AF_INET, SOCK_STREAM, 0); |
+ if (s == -1) { |
+ return type; |
+ } |
+ |
+ struct iwreq pwrq; |
+ memset(&pwrq, 0, sizeof(pwrq)); |
+ strncpy(pwrq.ifr_name, ifname.c_str(), IFNAMSIZ); |
+ |
+ if (ioctl(s, SIOCGIWNAME, &pwrq) != -1) { |
+ type = NetworkChangeNotifier::CONNECTION_WIFI; |
+ } |
pauljensen
2014/11/21 18:55:36
extra line break
derekjchow1
2014/11/21 23:13:58
Done.
|
+ else { |
+ type = NetworkChangeNotifier::CONNECTION_ETHERNET; |
pauljensen
2014/11/21 18:55:36
We should be defaulting to UNKNOWN not ETHERNET.
derekjchow1
2014/11/21 23:13:58
I'm looking to use NetworkChangeNotifierLinux in a
pauljensen
2014/11/24 12:33:18
I don't think this works. I believe on Chromebook
|
+ } |
+ close(s); |
+ return type; |
+} |
+ |
// Retrieves address from NETLINK address message. |
// Sets |really_deprecated| for IPv6 addresses with preferred lifetimes of 0. |
bool GetAddress(const struct nlmsghdr* header, |
@@ -77,22 +108,27 @@ bool GetAddress(const struct nlmsghdr* header, |
} |
// Returns the name for the interface with interface index |interface_index|. |
-// The return value points to a function-scoped static so it may be changed by |
-// subsequent calls. This function could be replaced with if_indextoname() but |
-// net/if.h cannot be mixed with linux/if.h so we'll stick with exclusively |
-// talking to the kernel and not the C library. |
-const char* GetInterfaceName(int interface_index) { |
+// |buf| should be a pointer to an array of size IFNAMSIZ. This function acts |
+// behaves as if_indextoname which cannot be used as net/if.h cannot be mixed |
+// with linux/if.h. We'll stick with exclusively talking to the kernel and |
+// not the C library. |
+char* GetInterfaceName(unsigned int interface_index, char* buf) { |
int ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0); |
- if (ioctl_socket < 0) |
- return ""; |
+ if (ioctl_socket < 0) { |
+ strncpy(buf, "", IFNAMSIZ); |
+ return buf; |
+ } |
static struct ifreq ifr; |
memset(&ifr, 0, sizeof(ifr)); |
ifr.ifr_ifindex = interface_index; |
int rv = ioctl(ioctl_socket, SIOCGIFNAME, &ifr); |
close(ioctl_socket); |
- if (rv != 0) |
- return ""; |
- return ifr.ifr_name; |
+ if (rv != 0) { |
+ strncpy(buf, "", IFNAMSIZ); |
+ return buf; |
+ } |
+ strncpy(buf, ifr.ifr_name, IFNAMSIZ); |
+ return buf; |
} |
} // namespace |
@@ -248,8 +284,14 @@ AddressTrackerLinux::GetCurrentConnectionType() { |
} |
// TODO(droger): Return something more detailed than CONNECTION_UNKNOWN. |
// http://crbug.com/160537 |
- return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE : |
- NetworkChangeNotifier::CONNECTION_UNKNOWN; |
+ if (is_offline_) |
+ return NetworkChangeNotifier::CONNECTION_NONE; |
+ |
+ std::string primary_if = GetPrimaryNetif(); |
+ if (primary_if.empty()) |
+ return NetworkChangeNotifier::CONNECTION_NONE; |
+ |
+ return GetInterfaceConnectionType(primary_if); |
pauljensen
2014/11/21 18:55:36
You've added lots of code executed while the lock
derekjchow1
2014/11/21 23:13:58
Done.
|
} |
void AddressTrackerLinux::ReadMessages(bool* address_changed, |
@@ -403,7 +445,58 @@ void AddressTrackerLinux::CloseSocket() { |
bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const { |
// Linux kernel drivers/net/tun.c uses "tun" name prefix. |
- return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0; |
+ char buf[IFNAMSIZ] = {0}; |
+ return strncmp(get_interface_name_(msg->ifi_index, buf), "tun", 3) == 0; |
+} |
+ |
+bool AddressTrackerLinux::GetNetworkList(NetworkInterfaceList* networks, |
+ int policy) const { |
+ const base::hash_set<int> online_links = GetOnlineLinks(); |
+ const internal::AddressTrackerLinux::AddressMap address_map |
+ = GetAddressMap(); |
+ |
+ bool success = GetNetworkListImpl(networks, policy, online_links, address_map, |
+ get_interface_name_); |
+ if (success) { |
+ for (size_t i = 0; i < (*networks).size(); ++i) |
+ (*networks)[i].type = GetInterfaceConnectionType((*networks)[i].name); |
+ } |
+ |
+ return success; |
+} |
+ |
+std::string AddressTrackerLinux::GetPrimaryNetif() const { |
+ NetworkInterfaceList networks; |
+ if (!GetNetworkList(&networks, 0)) { |
+ LOG(ERROR) << "GetNetworkList failed"; |
+ return ""; |
+ } |
+ |
+ for (size_t i = 0; i < networks.size(); ++i) { |
+ net::AddressFamily family = net::GetAddressFamily(networks[i].address); |
+ |
+ // Skip ignored interfaces. |
+ if (netifs_to_ignore_.find(networks[i].name) != netifs_to_ignore_.end()) |
+ continue; |
+ |
+ // IPv4 address means interface is configured. |
pauljensen
2014/11/21 18:55:36
I don't think an IPv4 address means an interface i
derekjchow1
2014/11/21 23:13:58
Done.
|
+ // IP address is cleared by DHCP when Ethernet cable is unplugged. It may |
pauljensen
2014/11/21 18:55:36
I don't think DHCP clears IP addresses on local in
derekjchow1
2014/11/21 23:13:58
Done.
|
+ // not be true if static IP is used. |
+ if (family != net::ADDRESS_FAMILY_IPV4) |
+ continue; |
+ |
+ return networks[i].name; |
+ } |
+ |
+ return ""; |
+} |
+ |
+bool AddressTrackerLinux::AddNetifToIgnore(const std::string& netif_name) { |
+ return netifs_to_ignore_.insert(netif_name).second; |
+} |
+ |
+bool AddressTrackerLinux::RemoveNetifToIgnore(const std::string& netif_name) { |
+ return netifs_to_ignore_.erase(netif_name) > 0; |
} |
AddressTrackerLinux::AddressTrackerAutoLock::AddressTrackerAutoLock( |