Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Unified Diff: net/base/address_tracker_linux.cc

Issue 739983005: Determine connection type in NetworkChangeNotifierLinux. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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(

Powered by Google App Engine
This is Rietveld 408576698