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

Side by Side Diff: net/base/address_tracker_linux.cc

Issue 571743002: Adding non-tracking mode support to AddressTracker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add one more comment on the usage of ThreadChecker. Created 6 years, 3 months 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 <sys/ioctl.h> 9 #include <sys/ioctl.h>
10 10
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 ifr.ifr_ifindex = interface_index; 90 ifr.ifr_ifindex = interface_index;
91 int rv = ioctl(ioctl_socket, SIOCGIFNAME, &ifr); 91 int rv = ioctl(ioctl_socket, SIOCGIFNAME, &ifr);
92 close(ioctl_socket); 92 close(ioctl_socket);
93 if (rv != 0) 93 if (rv != 0)
94 return ""; 94 return "";
95 return ifr.ifr_name; 95 return ifr.ifr_name;
96 } 96 }
97 97
98 } // namespace 98 } // namespace
99 99
100 AddressTrackerLinux::AddressTrackerLinux()
101 : get_interface_name_(GetInterfaceName),
102 address_callback_(base::Bind(&base::DoNothing)),
103 link_callback_(base::Bind(&base::DoNothing)),
104 tunnel_callback_(base::Bind(&base::DoNothing)),
105 netlink_fd_(-1),
106 is_offline_(true),
107 is_offline_initialized_(false),
108 is_offline_initialized_cv_(&is_offline_lock_),
109 tracking_(false) {
110 }
111
100 AddressTrackerLinux::AddressTrackerLinux(const base::Closure& address_callback, 112 AddressTrackerLinux::AddressTrackerLinux(const base::Closure& address_callback,
101 const base::Closure& link_callback, 113 const base::Closure& link_callback,
102 const base::Closure& tunnel_callback) 114 const base::Closure& tunnel_callback)
103 : get_interface_name_(GetInterfaceName), 115 : get_interface_name_(GetInterfaceName),
104 address_callback_(address_callback), 116 address_callback_(address_callback),
105 link_callback_(link_callback), 117 link_callback_(link_callback),
106 tunnel_callback_(tunnel_callback), 118 tunnel_callback_(tunnel_callback),
107 netlink_fd_(-1), 119 netlink_fd_(-1),
108 is_offline_(true), 120 is_offline_(true),
109 is_offline_initialized_(false), 121 is_offline_initialized_(false),
110 is_offline_initialized_cv_(&is_offline_lock_) { 122 is_offline_initialized_cv_(&is_offline_lock_),
123 tracking_(true) {
111 DCHECK(!address_callback.is_null()); 124 DCHECK(!address_callback.is_null());
112 DCHECK(!link_callback.is_null()); 125 DCHECK(!link_callback.is_null());
113 } 126 }
114 127
115 AddressTrackerLinux::~AddressTrackerLinux() { 128 AddressTrackerLinux::~AddressTrackerLinux() {
116 CloseSocket(); 129 CloseSocket();
117 } 130 }
118 131
119 void AddressTrackerLinux::Init() { 132 void AddressTrackerLinux::Init() {
120 netlink_fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 133 netlink_fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
121 if (netlink_fd_ < 0) { 134 if (netlink_fd_ < 0) {
122 PLOG(ERROR) << "Could not create NETLINK socket"; 135 PLOG(ERROR) << "Could not create NETLINK socket";
123 AbortAndForceOnline(); 136 AbortAndForceOnline();
124 return; 137 return;
125 } 138 }
126 139
127 // Request notifications. 140 int rv;
128 struct sockaddr_nl addr = {}; 141
129 addr.nl_family = AF_NETLINK; 142 if (tracking_) {
130 addr.nl_pid = getpid(); 143 // Request notifications.
131 // TODO(szym): Track RTMGRP_LINK as well for ifi_type, http://crbug.com/113993 144 struct sockaddr_nl addr = {};
132 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | 145 addr.nl_family = AF_NETLINK;
133 RTMGRP_LINK; 146 addr.nl_pid = getpid();
134 int rv = bind(netlink_fd_, 147 // TODO(szym): Track RTMGRP_LINK as well for ifi_type,
135 reinterpret_cast<struct sockaddr*>(&addr), 148 // http://crbug.com/113993
136 sizeof(addr)); 149 addr.nl_groups =
137 if (rv < 0) { 150 RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | RTMGRP_LINK;
138 PLOG(ERROR) << "Could not bind NETLINK socket"; 151 rv = bind(
139 AbortAndForceOnline(); 152 netlink_fd_, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
140 return; 153 if (rv < 0) {
154 PLOG(ERROR) << "Could not bind NETLINK socket";
155 AbortAndForceOnline();
156 return;
157 }
141 } 158 }
142 159
143 // Request dump of addresses. 160 // Request dump of addresses.
144 struct sockaddr_nl peer = {}; 161 struct sockaddr_nl peer = {};
145 peer.nl_family = AF_NETLINK; 162 peer.nl_family = AF_NETLINK;
146 163
147 struct { 164 struct {
148 struct nlmsghdr header; 165 struct nlmsghdr header;
149 struct rtgenmsg msg; 166 struct rtgenmsg msg;
150 } request = {}; 167 } request = {};
(...skipping 28 matching lines...) Expand all
179 sizeof(peer))); 196 sizeof(peer)));
180 if (rv < 0) { 197 if (rv < 0) {
181 PLOG(ERROR) << "Could not send NETLINK request"; 198 PLOG(ERROR) << "Could not send NETLINK request";
182 AbortAndForceOnline(); 199 AbortAndForceOnline();
183 return; 200 return;
184 } 201 }
185 202
186 // Consume pending message to populate links_online_, but don't notify. 203 // Consume pending message to populate links_online_, but don't notify.
187 ReadMessages(&address_changed, &link_changed, &tunnel_changed); 204 ReadMessages(&address_changed, &link_changed, &tunnel_changed);
188 { 205 {
189 base::AutoLock lock(is_offline_lock_); 206 AddressTrackerAutoLock lock(*this, is_offline_lock_);
190 is_offline_initialized_ = true; 207 is_offline_initialized_ = true;
191 is_offline_initialized_cv_.Signal(); 208 is_offline_initialized_cv_.Signal();
192 } 209 }
193 210
194 rv = base::MessageLoopForIO::current()->WatchFileDescriptor( 211 if (tracking_) {
195 netlink_fd_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this); 212 rv = base::MessageLoopForIO::current()->WatchFileDescriptor(
196 if (rv < 0) { 213 netlink_fd_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this);
197 PLOG(ERROR) << "Could not watch NETLINK socket"; 214 if (rv < 0) {
198 AbortAndForceOnline(); 215 PLOG(ERROR) << "Could not watch NETLINK socket";
199 return; 216 AbortAndForceOnline();
217 return;
218 }
200 } 219 }
201 } 220 }
202 221
203 void AddressTrackerLinux::AbortAndForceOnline() { 222 void AddressTrackerLinux::AbortAndForceOnline() {
204 CloseSocket(); 223 CloseSocket();
205 base::AutoLock lock(is_offline_lock_); 224 AddressTrackerAutoLock lock(*this, is_offline_lock_);
206 is_offline_ = false; 225 is_offline_ = false;
207 is_offline_initialized_ = true; 226 is_offline_initialized_ = true;
208 is_offline_initialized_cv_.Signal(); 227 is_offline_initialized_cv_.Signal();
209 } 228 }
210 229
211 AddressTrackerLinux::AddressMap AddressTrackerLinux::GetAddressMap() const { 230 AddressTrackerLinux::AddressMap AddressTrackerLinux::GetAddressMap() const {
212 base::AutoLock lock(address_map_lock_); 231 AddressTrackerAutoLock lock(*this, address_map_lock_);
213 return address_map_; 232 return address_map_;
214 } 233 }
215 234
235 base::hash_set<int> AddressTrackerLinux::GetOnlineLinks() const {
236 AddressTrackerAutoLock lock(*this, online_links_lock_);
237 return online_links_;
238 }
239
216 NetworkChangeNotifier::ConnectionType 240 NetworkChangeNotifier::ConnectionType
217 AddressTrackerLinux::GetCurrentConnectionType() { 241 AddressTrackerLinux::GetCurrentConnectionType() {
218 // http://crbug.com/125097 242 // http://crbug.com/125097
219 base::ThreadRestrictions::ScopedAllowWait allow_wait; 243 base::ThreadRestrictions::ScopedAllowWait allow_wait;
220 base::AutoLock lock(is_offline_lock_); 244 AddressTrackerAutoLock lock(*this, is_offline_lock_);
221 // Make sure the initial offline state is set before returning. 245 // Make sure the initial offline state is set before returning.
222 while (!is_offline_initialized_) { 246 while (!is_offline_initialized_) {
223 is_offline_initialized_cv_.Wait(); 247 is_offline_initialized_cv_.Wait();
224 } 248 }
225 // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN. 249 // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN.
226 // http://crbug.com/160537 250 // http://crbug.com/160537
227 return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE : 251 return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE :
228 NetworkChangeNotifier::CONNECTION_UNKNOWN; 252 NetworkChangeNotifier::CONNECTION_UNKNOWN;
229 } 253 }
230 254
(...skipping 16 matching lines...) Expand all
247 LOG(ERROR) << "Unexpected shutdown of NETLINK socket."; 271 LOG(ERROR) << "Unexpected shutdown of NETLINK socket.";
248 return; 272 return;
249 } 273 }
250 if (rv < 0) { 274 if (rv < 0) {
251 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) 275 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
252 break; 276 break;
253 PLOG(ERROR) << "Failed to recv from netlink socket"; 277 PLOG(ERROR) << "Failed to recv from netlink socket";
254 return; 278 return;
255 } 279 }
256 HandleMessage(buffer, rv, address_changed, link_changed, tunnel_changed); 280 HandleMessage(buffer, rv, address_changed, link_changed, tunnel_changed);
257 }; 281 }
258 if (*link_changed) { 282 if (*link_changed) {
259 base::AutoLock lock(is_offline_lock_); 283 bool is_offline;
260 is_offline_ = online_links_.empty(); 284 {
285 AddressTrackerAutoLock lock(*this, online_links_lock_);
286 is_offline = online_links_.empty();
287 }
288 AddressTrackerAutoLock lock(*this, is_offline_lock_);
289 is_offline_ = is_offline;
261 } 290 }
262 } 291 }
263 292
264 void AddressTrackerLinux::HandleMessage(char* buffer, 293 void AddressTrackerLinux::HandleMessage(char* buffer,
265 size_t length, 294 size_t length,
266 bool* address_changed, 295 bool* address_changed,
267 bool* link_changed, 296 bool* link_changed,
268 bool* tunnel_changed) { 297 bool* tunnel_changed) {
269 DCHECK(buffer); 298 DCHECK(buffer);
270 for (struct nlmsghdr* header = reinterpret_cast<struct nlmsghdr*>(buffer); 299 for (struct nlmsghdr* header = reinterpret_cast<struct nlmsghdr*>(buffer);
271 NLMSG_OK(header, length); 300 NLMSG_OK(header, length);
272 header = NLMSG_NEXT(header, length)) { 301 header = NLMSG_NEXT(header, length)) {
273 switch (header->nlmsg_type) { 302 switch (header->nlmsg_type) {
274 case NLMSG_DONE: 303 case NLMSG_DONE:
275 return; 304 return;
276 case NLMSG_ERROR: { 305 case NLMSG_ERROR: {
277 const struct nlmsgerr* msg = 306 const struct nlmsgerr* msg =
278 reinterpret_cast<struct nlmsgerr*>(NLMSG_DATA(header)); 307 reinterpret_cast<struct nlmsgerr*>(NLMSG_DATA(header));
279 LOG(ERROR) << "Unexpected netlink error " << msg->error << "."; 308 LOG(ERROR) << "Unexpected netlink error " << msg->error << ".";
280 } return; 309 } return;
281 case RTM_NEWADDR: { 310 case RTM_NEWADDR: {
282 IPAddressNumber address; 311 IPAddressNumber address;
283 bool really_deprecated; 312 bool really_deprecated;
284 if (GetAddress(header, &address, &really_deprecated)) { 313 if (GetAddress(header, &address, &really_deprecated)) {
285 base::AutoLock lock(address_map_lock_); 314 AddressTrackerAutoLock lock(*this, address_map_lock_);
286 struct ifaddrmsg* msg = 315 struct ifaddrmsg* msg =
287 reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); 316 reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header));
288 // Routers may frequently (every few seconds) output the IPv6 ULA 317 // Routers may frequently (every few seconds) output the IPv6 ULA
289 // prefix which can cause the linux kernel to frequently output two 318 // prefix which can cause the linux kernel to frequently output two
290 // back-to-back messages, one without the deprecated flag and one with 319 // back-to-back messages, one without the deprecated flag and one with
291 // the deprecated flag but both with preferred lifetimes of 0. Avoid 320 // the deprecated flag but both with preferred lifetimes of 0. Avoid
292 // interpretting this as an actual change by canonicalizing the two 321 // interpretting this as an actual change by canonicalizing the two
293 // messages by setting the deprecated flag based on the preferred 322 // messages by setting the deprecated flag based on the preferred
294 // lifetime also. http://crbug.com/268042 323 // lifetime also. http://crbug.com/268042
295 if (really_deprecated) 324 if (really_deprecated)
296 msg->ifa_flags |= IFA_F_DEPRECATED; 325 msg->ifa_flags |= IFA_F_DEPRECATED;
297 // Only indicate change if the address is new or ifaddrmsg info has 326 // Only indicate change if the address is new or ifaddrmsg info has
298 // changed. 327 // changed.
299 AddressMap::iterator it = address_map_.find(address); 328 AddressMap::iterator it = address_map_.find(address);
300 if (it == address_map_.end()) { 329 if (it == address_map_.end()) {
301 address_map_.insert(it, std::make_pair(address, *msg)); 330 address_map_.insert(it, std::make_pair(address, *msg));
302 *address_changed = true; 331 *address_changed = true;
303 } else if (memcmp(&it->second, msg, sizeof(*msg))) { 332 } else if (memcmp(&it->second, msg, sizeof(*msg))) {
304 it->second = *msg; 333 it->second = *msg;
305 *address_changed = true; 334 *address_changed = true;
306 } 335 }
307 } 336 }
308 } break; 337 } break;
309 case RTM_DELADDR: { 338 case RTM_DELADDR: {
310 IPAddressNumber address; 339 IPAddressNumber address;
311 if (GetAddress(header, &address, NULL)) { 340 if (GetAddress(header, &address, NULL)) {
312 base::AutoLock lock(address_map_lock_); 341 AddressTrackerAutoLock lock(*this, address_map_lock_);
313 if (address_map_.erase(address)) 342 if (address_map_.erase(address))
314 *address_changed = true; 343 *address_changed = true;
315 } 344 }
316 } break; 345 } break;
317 case RTM_NEWLINK: { 346 case RTM_NEWLINK: {
318 const struct ifinfomsg* msg = 347 const struct ifinfomsg* msg =
319 reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); 348 reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header));
320 if (!(msg->ifi_flags & IFF_LOOPBACK) && (msg->ifi_flags & IFF_UP) && 349 if (!(msg->ifi_flags & IFF_LOOPBACK) && (msg->ifi_flags & IFF_UP) &&
321 (msg->ifi_flags & IFF_LOWER_UP) && (msg->ifi_flags & IFF_RUNNING)) { 350 (msg->ifi_flags & IFF_LOWER_UP) && (msg->ifi_flags & IFF_RUNNING)) {
351 AddressTrackerAutoLock lock(*this, online_links_lock_);
322 if (online_links_.insert(msg->ifi_index).second) { 352 if (online_links_.insert(msg->ifi_index).second) {
323 *link_changed = true; 353 *link_changed = true;
324 if (IsTunnelInterface(msg)) 354 if (IsTunnelInterface(msg))
325 *tunnel_changed = true; 355 *tunnel_changed = true;
326 } 356 }
327 } else { 357 } else {
358 AddressTrackerAutoLock lock(*this, online_links_lock_);
328 if (online_links_.erase(msg->ifi_index)) { 359 if (online_links_.erase(msg->ifi_index)) {
329 *link_changed = true; 360 *link_changed = true;
330 if (IsTunnelInterface(msg)) 361 if (IsTunnelInterface(msg))
331 *tunnel_changed = true; 362 *tunnel_changed = true;
332 } 363 }
333 } 364 }
334 } break; 365 } break;
335 case RTM_DELLINK: { 366 case RTM_DELLINK: {
336 const struct ifinfomsg* msg = 367 const struct ifinfomsg* msg =
337 reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); 368 reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header));
369 AddressTrackerAutoLock lock(*this, online_links_lock_);
338 if (online_links_.erase(msg->ifi_index)) { 370 if (online_links_.erase(msg->ifi_index)) {
339 *link_changed = true; 371 *link_changed = true;
340 if (IsTunnelInterface(msg)) 372 if (IsTunnelInterface(msg))
341 *tunnel_changed = true; 373 *tunnel_changed = true;
342 } 374 }
343 } break; 375 } break;
344 default: 376 default:
345 break; 377 break;
346 } 378 }
347 } 379 }
(...skipping 21 matching lines...) Expand all
369 netlink_fd_ = -1; 401 netlink_fd_ = -1;
370 } 402 }
371 403
372 bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const { 404 bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const {
373 // Linux kernel drivers/net/tun.c uses "tun" name prefix. 405 // Linux kernel drivers/net/tun.c uses "tun" name prefix.
374 return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0; 406 return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0;
375 } 407 }
376 408
377 } // namespace internal 409 } // namespace internal
378 } // namespace net 410 } // namespace net
OLDNEW
« net/base/address_tracker_linux.h ('K') | « net/base/address_tracker_linux.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698