Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 switch (attr->rta_type) { | 52 switch (attr->rta_type) { |
| 53 case IFA_ADDRESS: | 53 case IFA_ADDRESS: |
| 54 DCHECK_GE(RTA_PAYLOAD(attr), address_length); | 54 DCHECK_GE(RTA_PAYLOAD(attr), address_length); |
| 55 address = reinterpret_cast<unsigned char*>(RTA_DATA(attr)); | 55 address = reinterpret_cast<unsigned char*>(RTA_DATA(attr)); |
| 56 break; | 56 break; |
| 57 case IFA_LOCAL: | 57 case IFA_LOCAL: |
| 58 DCHECK_GE(RTA_PAYLOAD(attr), address_length); | 58 DCHECK_GE(RTA_PAYLOAD(attr), address_length); |
| 59 local = reinterpret_cast<unsigned char*>(RTA_DATA(attr)); | 59 local = reinterpret_cast<unsigned char*>(RTA_DATA(attr)); |
| 60 break; | 60 break; |
| 61 case IFA_CACHEINFO: { | 61 case IFA_CACHEINFO: { |
| 62 const struct ifa_cacheinfo *cache_info = | 62 const struct ifa_cacheinfo* cache_info = |
| 63 reinterpret_cast<const struct ifa_cacheinfo*>(RTA_DATA(attr)); | 63 reinterpret_cast<const struct ifa_cacheinfo*>(RTA_DATA(attr)); |
| 64 if (really_deprecated) | 64 if (really_deprecated) |
| 65 *really_deprecated = (cache_info->ifa_prefered == 0); | 65 *really_deprecated = (cache_info->ifa_prefered == 0); |
| 66 } break; | 66 } break; |
| 67 default: | 67 default: |
| 68 break; | 68 break; |
| 69 } | 69 } |
| 70 } | 70 } |
| 71 if (local) | 71 if (local) |
| 72 address = local; | 72 address = local; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 struct nlmsghdr header; | 165 struct nlmsghdr header; |
| 166 struct rtgenmsg msg; | 166 struct rtgenmsg msg; |
| 167 } request = {}; | 167 } request = {}; |
| 168 | 168 |
| 169 request.header.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg)); | 169 request.header.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg)); |
| 170 request.header.nlmsg_type = RTM_GETADDR; | 170 request.header.nlmsg_type = RTM_GETADDR; |
| 171 request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; | 171 request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; |
| 172 request.header.nlmsg_pid = getpid(); | 172 request.header.nlmsg_pid = getpid(); |
| 173 request.msg.rtgen_family = AF_UNSPEC; | 173 request.msg.rtgen_family = AF_UNSPEC; |
| 174 | 174 |
| 175 rv = HANDLE_EINTR(sendto(netlink_fd_, &request, request.header.nlmsg_len, | 175 rv = HANDLE_EINTR(sendto(netlink_fd_, |
| 176 0, reinterpret_cast<struct sockaddr*>(&peer), | 176 &request, |
| 177 request.header.nlmsg_len, | |
| 178 0, | |
| 179 reinterpret_cast<struct sockaddr*>(&peer), | |
| 177 sizeof(peer))); | 180 sizeof(peer))); |
| 178 if (rv < 0) { | 181 if (rv < 0) { |
| 179 PLOG(ERROR) << "Could not send NETLINK request"; | 182 PLOG(ERROR) << "Could not send NETLINK request"; |
| 180 AbortAndForceOnline(); | 183 AbortAndForceOnline(); |
| 181 return; | 184 return; |
| 182 } | 185 } |
| 183 | 186 |
| 184 // Consume pending message to populate the AddressMap, but don't notify. | 187 // Consume pending message to populate the AddressMap, but don't notify. |
| 185 // Sending another request without first reading responses results in EBUSY. | 188 // Sending another request without first reading responses results in EBUSY. |
| 186 bool address_changed; | 189 bool address_changed; |
| 187 bool link_changed; | 190 bool link_changed; |
| 188 bool tunnel_changed; | 191 bool tunnel_changed; |
| 189 ReadMessages(&address_changed, &link_changed, &tunnel_changed); | 192 ReadMessages(&address_changed, &link_changed, &tunnel_changed); |
| 190 | 193 |
| 191 // Request dump of link state | 194 // Request dump of link state |
| 192 request.header.nlmsg_type = RTM_GETLINK; | 195 request.header.nlmsg_type = RTM_GETLINK; |
| 193 | 196 |
| 194 rv = HANDLE_EINTR(sendto(netlink_fd_, &request, request.header.nlmsg_len, 0, | 197 rv = HANDLE_EINTR(sendto(netlink_fd_, |
| 198 &request, | |
| 199 request.header.nlmsg_len, | |
| 200 0, | |
| 195 reinterpret_cast<struct sockaddr*>(&peer), | 201 reinterpret_cast<struct sockaddr*>(&peer), |
| 196 sizeof(peer))); | 202 sizeof(peer))); |
| 197 if (rv < 0) { | 203 if (rv < 0) { |
| 198 PLOG(ERROR) << "Could not send NETLINK request"; | 204 PLOG(ERROR) << "Could not send NETLINK request"; |
| 199 AbortAndForceOnline(); | 205 AbortAndForceOnline(); |
| 200 return; | 206 return; |
| 201 } | 207 } |
| 202 | 208 |
| 203 // Consume pending message to populate links_online_, but don't notify. | 209 // Consume pending message to populate links_online_, but don't notify. |
| 204 ReadMessages(&address_changed, &link_changed, &tunnel_changed); | 210 ReadMessages(&address_changed, &link_changed, &tunnel_changed); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 241 AddressTrackerLinux::GetCurrentConnectionType() { | 247 AddressTrackerLinux::GetCurrentConnectionType() { |
| 242 // http://crbug.com/125097 | 248 // http://crbug.com/125097 |
| 243 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 249 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
| 244 AddressTrackerAutoLock lock(*this, is_offline_lock_); | 250 AddressTrackerAutoLock lock(*this, is_offline_lock_); |
| 245 // Make sure the initial offline state is set before returning. | 251 // Make sure the initial offline state is set before returning. |
| 246 while (!is_offline_initialized_) { | 252 while (!is_offline_initialized_) { |
| 247 is_offline_initialized_cv_.Wait(); | 253 is_offline_initialized_cv_.Wait(); |
| 248 } | 254 } |
| 249 // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN. | 255 // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN. |
| 250 // http://crbug.com/160537 | 256 // http://crbug.com/160537 |
| 251 return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE : | 257 return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE |
| 252 NetworkChangeNotifier::CONNECTION_UNKNOWN; | 258 : NetworkChangeNotifier::CONNECTION_UNKNOWN; |
| 253 } | 259 } |
| 254 | 260 |
| 255 void AddressTrackerLinux::ReadMessages(bool* address_changed, | 261 void AddressTrackerLinux::ReadMessages(bool* address_changed, |
| 256 bool* link_changed, | 262 bool* link_changed, |
| 257 bool* tunnel_changed) { | 263 bool* tunnel_changed) { |
| 258 *address_changed = false; | 264 *address_changed = false; |
| 259 *link_changed = false; | 265 *link_changed = false; |
| 260 *tunnel_changed = false; | 266 *tunnel_changed = false; |
| 261 char buffer[4096]; | 267 char buffer[4096]; |
| 262 bool first_loop = true; | 268 bool first_loop = true; |
| 263 for (;;) { | 269 for (;;) { |
| 264 int rv = HANDLE_EINTR(recv(netlink_fd_, | 270 int rv = HANDLE_EINTR(recv(netlink_fd_, |
| 265 buffer, | 271 buffer, |
| 266 sizeof(buffer), | 272 sizeof(buffer), |
| 267 // Block the first time through loop. | 273 // Block the first time through loop. |
| 268 first_loop ? 0 : MSG_DONTWAIT)); | 274 first_loop |
| 275 ? 0 | |
| 276 : MSG_DONTWAIT)); | |
|
davidben
2014/10/10 20:24:15
This looks like a clang-format bug.
| |
| 269 first_loop = false; | 277 first_loop = false; |
| 270 if (rv == 0) { | 278 if (rv == 0) { |
| 271 LOG(ERROR) << "Unexpected shutdown of NETLINK socket."; | 279 LOG(ERROR) << "Unexpected shutdown of NETLINK socket."; |
| 272 return; | 280 return; |
| 273 } | 281 } |
| 274 if (rv < 0) { | 282 if (rv < 0) { |
| 275 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) | 283 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) |
| 276 break; | 284 break; |
| 277 PLOG(ERROR) << "Failed to recv from netlink socket"; | 285 PLOG(ERROR) << "Failed to recv from netlink socket"; |
| 278 return; | 286 return; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 299 for (struct nlmsghdr* header = reinterpret_cast<struct nlmsghdr*>(buffer); | 307 for (struct nlmsghdr* header = reinterpret_cast<struct nlmsghdr*>(buffer); |
| 300 NLMSG_OK(header, length); | 308 NLMSG_OK(header, length); |
| 301 header = NLMSG_NEXT(header, length)) { | 309 header = NLMSG_NEXT(header, length)) { |
| 302 switch (header->nlmsg_type) { | 310 switch (header->nlmsg_type) { |
| 303 case NLMSG_DONE: | 311 case NLMSG_DONE: |
| 304 return; | 312 return; |
| 305 case NLMSG_ERROR: { | 313 case NLMSG_ERROR: { |
| 306 const struct nlmsgerr* msg = | 314 const struct nlmsgerr* msg = |
| 307 reinterpret_cast<struct nlmsgerr*>(NLMSG_DATA(header)); | 315 reinterpret_cast<struct nlmsgerr*>(NLMSG_DATA(header)); |
| 308 LOG(ERROR) << "Unexpected netlink error " << msg->error << "."; | 316 LOG(ERROR) << "Unexpected netlink error " << msg->error << "."; |
| 309 } return; | 317 } |
| 318 return; | |
|
davidben
2014/10/10 20:24:15
Both of these seem pretty off. Move the return ins
| |
| 310 case RTM_NEWADDR: { | 319 case RTM_NEWADDR: { |
| 311 IPAddressNumber address; | 320 IPAddressNumber address; |
| 312 bool really_deprecated; | 321 bool really_deprecated; |
| 313 if (GetAddress(header, &address, &really_deprecated)) { | 322 if (GetAddress(header, &address, &really_deprecated)) { |
| 314 AddressTrackerAutoLock lock(*this, address_map_lock_); | 323 AddressTrackerAutoLock lock(*this, address_map_lock_); |
| 315 struct ifaddrmsg* msg = | 324 struct ifaddrmsg* msg = |
| 316 reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); | 325 reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); |
| 317 // Routers may frequently (every few seconds) output the IPv6 ULA | 326 // Routers may frequently (every few seconds) output the IPv6 ULA |
| 318 // prefix which can cause the linux kernel to frequently output two | 327 // prefix which can cause the linux kernel to frequently output two |
| 319 // back-to-back messages, one without the deprecated flag and one with | 328 // back-to-back messages, one without the deprecated flag and one with |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 bool tunnel_changed; | 395 bool tunnel_changed; |
| 387 ReadMessages(&address_changed, &link_changed, &tunnel_changed); | 396 ReadMessages(&address_changed, &link_changed, &tunnel_changed); |
| 388 if (address_changed) | 397 if (address_changed) |
| 389 address_callback_.Run(); | 398 address_callback_.Run(); |
| 390 if (link_changed) | 399 if (link_changed) |
| 391 link_callback_.Run(); | 400 link_callback_.Run(); |
| 392 if (tunnel_changed) | 401 if (tunnel_changed) |
| 393 tunnel_callback_.Run(); | 402 tunnel_callback_.Run(); |
| 394 } | 403 } |
| 395 | 404 |
| 396 void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {} | 405 void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) { |
| 406 } | |
| 397 | 407 |
| 398 void AddressTrackerLinux::CloseSocket() { | 408 void AddressTrackerLinux::CloseSocket() { |
| 399 if (netlink_fd_ >= 0 && IGNORE_EINTR(close(netlink_fd_)) < 0) | 409 if (netlink_fd_ >= 0 && IGNORE_EINTR(close(netlink_fd_)) < 0) |
| 400 PLOG(ERROR) << "Could not close NETLINK socket."; | 410 PLOG(ERROR) << "Could not close NETLINK socket."; |
| 401 netlink_fd_ = -1; | 411 netlink_fd_ = -1; |
| 402 } | 412 } |
| 403 | 413 |
| 404 bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const { | 414 bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const { |
| 405 // Linux kernel drivers/net/tun.c uses "tun" name prefix. | 415 // Linux kernel drivers/net/tun.c uses "tun" name prefix. |
| 406 return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0; | 416 return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 419 | 429 |
| 420 AddressTrackerLinux::AddressTrackerAutoLock::~AddressTrackerAutoLock() { | 430 AddressTrackerLinux::AddressTrackerAutoLock::~AddressTrackerAutoLock() { |
| 421 if (tracker_.tracking_) { | 431 if (tracker_.tracking_) { |
| 422 lock_.AssertAcquired(); | 432 lock_.AssertAcquired(); |
| 423 lock_.Release(); | 433 lock_.Release(); |
| 424 } | 434 } |
| 425 } | 435 } |
| 426 | 436 |
| 427 } // namespace internal | 437 } // namespace internal |
| 428 } // namespace net | 438 } // namespace net |
| OLD | NEW |