Chromium Code Reviews| 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( |