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

Side by Side 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 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/address_tracker_linux.h" 5 #include "net/base/address_tracker_linux.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <linux/if.h> 8 #include <linux/if.h>
9 #include <linux/wireless.h>
9 #include <sys/ioctl.h> 10 #include <sys/ioctl.h>
10 11
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/posix/eintr_wrapper.h" 13 #include "base/posix/eintr_wrapper.h"
13 #include "base/threading/thread_restrictions.h" 14 #include "base/threading/thread_restrictions.h"
15 #include "net/base/ip_endpoint.h"
16 #include "net/base/net_util_linux.h"
17 #include "net/base/net_util_posix.h"
14 18
15 namespace net { 19 namespace net {
16 namespace internal { 20 namespace internal {
17 21
18 namespace { 22 namespace {
19 23
24 // Gets the connection type for interface |ifname| by checking for wireless
25 // extensions. It is assumed for linux that if there are no extensions that
26 // the device is ethernet.
27 NetworkChangeNotifier::ConnectionType
28 GetInterfaceConnectionType(std::string ifname) {
29 NetworkChangeNotifier::ConnectionType type =
30 NetworkChangeNotifier::CONNECTION_UNKNOWN;
31
32 int s = socket(AF_INET, SOCK_STREAM, 0);
33 if (s == -1) {
34 return type;
35 }
36
37 struct iwreq pwrq;
38 memset(&pwrq, 0, sizeof(pwrq));
39 strncpy(pwrq.ifr_name, ifname.c_str(), IFNAMSIZ);
40
41 if (ioctl(s, SIOCGIWNAME, &pwrq) != -1) {
42 type = NetworkChangeNotifier::CONNECTION_WIFI;
43 }
pauljensen 2014/11/21 18:55:36 extra line break
derekjchow1 2014/11/21 23:13:58 Done.
44 else {
45 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
46 }
47 close(s);
48 return type;
49 }
50
20 // Retrieves address from NETLINK address message. 51 // Retrieves address from NETLINK address message.
21 // Sets |really_deprecated| for IPv6 addresses with preferred lifetimes of 0. 52 // Sets |really_deprecated| for IPv6 addresses with preferred lifetimes of 0.
22 bool GetAddress(const struct nlmsghdr* header, 53 bool GetAddress(const struct nlmsghdr* header,
23 IPAddressNumber* out, 54 IPAddressNumber* out,
24 bool* really_deprecated) { 55 bool* really_deprecated) {
25 if (really_deprecated) 56 if (really_deprecated)
26 *really_deprecated = false; 57 *really_deprecated = false;
27 const struct ifaddrmsg* msg = 58 const struct ifaddrmsg* msg =
28 reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); 59 reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header));
29 size_t address_length = 0; 60 size_t address_length = 0;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 } 101 }
71 if (local) 102 if (local)
72 address = local; 103 address = local;
73 if (!address) 104 if (!address)
74 return false; 105 return false;
75 out->assign(address, address + address_length); 106 out->assign(address, address + address_length);
76 return true; 107 return true;
77 } 108 }
78 109
79 // Returns the name for the interface with interface index |interface_index|. 110 // Returns the name for the interface with interface index |interface_index|.
80 // The return value points to a function-scoped static so it may be changed by 111 // |buf| should be a pointer to an array of size IFNAMSIZ. This function acts
81 // subsequent calls. This function could be replaced with if_indextoname() but 112 // behaves as if_indextoname which cannot be used as net/if.h cannot be mixed
82 // net/if.h cannot be mixed with linux/if.h so we'll stick with exclusively 113 // with linux/if.h. We'll stick with exclusively talking to the kernel and
83 // talking to the kernel and not the C library. 114 // not the C library.
84 const char* GetInterfaceName(int interface_index) { 115 char* GetInterfaceName(unsigned int interface_index, char* buf) {
85 int ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0); 116 int ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0);
86 if (ioctl_socket < 0) 117 if (ioctl_socket < 0) {
87 return ""; 118 strncpy(buf, "", IFNAMSIZ);
119 return buf;
120 }
88 static struct ifreq ifr; 121 static struct ifreq ifr;
89 memset(&ifr, 0, sizeof(ifr)); 122 memset(&ifr, 0, sizeof(ifr));
90 ifr.ifr_ifindex = interface_index; 123 ifr.ifr_ifindex = interface_index;
91 int rv = ioctl(ioctl_socket, SIOCGIFNAME, &ifr); 124 int rv = ioctl(ioctl_socket, SIOCGIFNAME, &ifr);
92 close(ioctl_socket); 125 close(ioctl_socket);
93 if (rv != 0) 126 if (rv != 0) {
94 return ""; 127 strncpy(buf, "", IFNAMSIZ);
95 return ifr.ifr_name; 128 return buf;
129 }
130 strncpy(buf, ifr.ifr_name, IFNAMSIZ);
131 return buf;
96 } 132 }
97 133
98 } // namespace 134 } // namespace
99 135
100 AddressTrackerLinux::AddressTrackerLinux() 136 AddressTrackerLinux::AddressTrackerLinux()
101 : get_interface_name_(GetInterfaceName), 137 : get_interface_name_(GetInterfaceName),
102 address_callback_(base::Bind(&base::DoNothing)), 138 address_callback_(base::Bind(&base::DoNothing)),
103 link_callback_(base::Bind(&base::DoNothing)), 139 link_callback_(base::Bind(&base::DoNothing)),
104 tunnel_callback_(base::Bind(&base::DoNothing)), 140 tunnel_callback_(base::Bind(&base::DoNothing)),
105 netlink_fd_(-1), 141 netlink_fd_(-1),
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 AddressTrackerLinux::GetCurrentConnectionType() { 277 AddressTrackerLinux::GetCurrentConnectionType() {
242 // http://crbug.com/125097 278 // http://crbug.com/125097
243 base::ThreadRestrictions::ScopedAllowWait allow_wait; 279 base::ThreadRestrictions::ScopedAllowWait allow_wait;
244 AddressTrackerAutoLock lock(*this, is_offline_lock_); 280 AddressTrackerAutoLock lock(*this, is_offline_lock_);
245 // Make sure the initial offline state is set before returning. 281 // Make sure the initial offline state is set before returning.
246 while (!is_offline_initialized_) { 282 while (!is_offline_initialized_) {
247 is_offline_initialized_cv_.Wait(); 283 is_offline_initialized_cv_.Wait();
248 } 284 }
249 // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN. 285 // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN.
250 // http://crbug.com/160537 286 // http://crbug.com/160537
251 return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE : 287 if (is_offline_)
252 NetworkChangeNotifier::CONNECTION_UNKNOWN; 288 return NetworkChangeNotifier::CONNECTION_NONE;
289
290 std::string primary_if = GetPrimaryNetif();
291 if (primary_if.empty())
292 return NetworkChangeNotifier::CONNECTION_NONE;
293
294 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.
253 } 295 }
254 296
255 void AddressTrackerLinux::ReadMessages(bool* address_changed, 297 void AddressTrackerLinux::ReadMessages(bool* address_changed,
256 bool* link_changed, 298 bool* link_changed,
257 bool* tunnel_changed) { 299 bool* tunnel_changed) {
258 *address_changed = false; 300 *address_changed = false;
259 *link_changed = false; 301 *link_changed = false;
260 *tunnel_changed = false; 302 *tunnel_changed = false;
261 char buffer[4096]; 303 char buffer[4096];
262 bool first_loop = true; 304 bool first_loop = true;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {} 438 void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {}
397 439
398 void AddressTrackerLinux::CloseSocket() { 440 void AddressTrackerLinux::CloseSocket() {
399 if (netlink_fd_ >= 0 && IGNORE_EINTR(close(netlink_fd_)) < 0) 441 if (netlink_fd_ >= 0 && IGNORE_EINTR(close(netlink_fd_)) < 0)
400 PLOG(ERROR) << "Could not close NETLINK socket."; 442 PLOG(ERROR) << "Could not close NETLINK socket.";
401 netlink_fd_ = -1; 443 netlink_fd_ = -1;
402 } 444 }
403 445
404 bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const { 446 bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const {
405 // Linux kernel drivers/net/tun.c uses "tun" name prefix. 447 // Linux kernel drivers/net/tun.c uses "tun" name prefix.
406 return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0; 448 char buf[IFNAMSIZ] = {0};
449 return strncmp(get_interface_name_(msg->ifi_index, buf), "tun", 3) == 0;
450 }
451
452 bool AddressTrackerLinux::GetNetworkList(NetworkInterfaceList* networks,
453 int policy) const {
454 const base::hash_set<int> online_links = GetOnlineLinks();
455 const internal::AddressTrackerLinux::AddressMap address_map
456 = GetAddressMap();
457
458 bool success = GetNetworkListImpl(networks, policy, online_links, address_map,
459 get_interface_name_);
460 if (success) {
461 for (size_t i = 0; i < (*networks).size(); ++i)
462 (*networks)[i].type = GetInterfaceConnectionType((*networks)[i].name);
463 }
464
465 return success;
466 }
467
468 std::string AddressTrackerLinux::GetPrimaryNetif() const {
469 NetworkInterfaceList networks;
470 if (!GetNetworkList(&networks, 0)) {
471 LOG(ERROR) << "GetNetworkList failed";
472 return "";
473 }
474
475 for (size_t i = 0; i < networks.size(); ++i) {
476 net::AddressFamily family = net::GetAddressFamily(networks[i].address);
477
478 // Skip ignored interfaces.
479 if (netifs_to_ignore_.find(networks[i].name) != netifs_to_ignore_.end())
480 continue;
481
482 // 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.
483 // 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.
484 // not be true if static IP is used.
485 if (family != net::ADDRESS_FAMILY_IPV4)
486 continue;
487
488 return networks[i].name;
489 }
490
491 return "";
492 }
493
494 bool AddressTrackerLinux::AddNetifToIgnore(const std::string& netif_name) {
495 return netifs_to_ignore_.insert(netif_name).second;
496 }
497
498 bool AddressTrackerLinux::RemoveNetifToIgnore(const std::string& netif_name) {
499 return netifs_to_ignore_.erase(netif_name) > 0;
407 } 500 }
408 501
409 AddressTrackerLinux::AddressTrackerAutoLock::AddressTrackerAutoLock( 502 AddressTrackerLinux::AddressTrackerAutoLock::AddressTrackerAutoLock(
410 const AddressTrackerLinux& tracker, 503 const AddressTrackerLinux& tracker,
411 base::Lock& lock) 504 base::Lock& lock)
412 : tracker_(tracker), lock_(lock) { 505 : tracker_(tracker), lock_(lock) {
413 if (tracker_.tracking_) { 506 if (tracker_.tracking_) {
414 lock_.Acquire(); 507 lock_.Acquire();
415 } else { 508 } else {
416 DCHECK(tracker_.thread_checker_.CalledOnValidThread()); 509 DCHECK(tracker_.thread_checker_.CalledOnValidThread());
417 } 510 }
418 } 511 }
419 512
420 AddressTrackerLinux::AddressTrackerAutoLock::~AddressTrackerAutoLock() { 513 AddressTrackerLinux::AddressTrackerAutoLock::~AddressTrackerAutoLock() {
421 if (tracker_.tracking_) { 514 if (tracker_.tracking_) {
422 lock_.AssertAcquired(); 515 lock_.AssertAcquired();
423 lock_.Release(); 516 lock_.Release();
424 } 517 }
425 } 518 }
426 519
427 } // namespace internal 520 } // namespace internal
428 } // namespace net 521 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698