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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 PLOG(ERROR) << "Could not create NETLINK socket"; | 122 PLOG(ERROR) << "Could not create NETLINK socket"; |
123 AbortAndForceOnline(); | 123 AbortAndForceOnline(); |
124 return; | 124 return; |
125 } | 125 } |
126 | 126 |
127 // Request notifications. | 127 // Request notifications. |
128 struct sockaddr_nl addr = {}; | 128 struct sockaddr_nl addr = {}; |
129 addr.nl_family = AF_NETLINK; | 129 addr.nl_family = AF_NETLINK; |
130 addr.nl_pid = getpid(); | 130 addr.nl_pid = getpid(); |
131 // TODO(szym): Track RTMGRP_LINK as well for ifi_type, http://crbug.com/113993 | 131 // TODO(szym): Track RTMGRP_LINK as well for ifi_type, http://crbug.com/113993 |
132 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | | 132 addr.nl_groups = |
133 RTMGRP_LINK; | 133 RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | RTMGRP_LINK; |
134 int rv = bind(netlink_fd_, | 134 int rv = bind( |
135 reinterpret_cast<struct sockaddr*>(&addr), | 135 netlink_fd_, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)); |
136 sizeof(addr)); | |
137 if (rv < 0) { | 136 if (rv < 0) { |
138 PLOG(ERROR) << "Could not bind NETLINK socket"; | 137 PLOG(ERROR) << "Could not bind NETLINK socket"; |
139 AbortAndForceOnline(); | 138 AbortAndForceOnline(); |
140 return; | 139 return; |
141 } | 140 } |
142 | 141 |
143 // Request dump of addresses. | 142 // Request dump of addresses. |
144 struct sockaddr_nl peer = {}; | 143 struct sockaddr_nl peer = {}; |
145 peer.nl_family = AF_NETLINK; | 144 peer.nl_family = AF_NETLINK; |
146 | 145 |
147 struct { | 146 struct { |
148 struct nlmsghdr header; | 147 struct nlmsghdr header; |
149 struct rtgenmsg msg; | 148 struct rtgenmsg msg; |
150 } request = {}; | 149 } request = {}; |
151 | 150 |
152 request.header.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg)); | 151 request.header.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg)); |
153 request.header.nlmsg_type = RTM_GETADDR; | 152 request.header.nlmsg_type = RTM_GETADDR; |
154 request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; | 153 request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; |
155 request.header.nlmsg_pid = getpid(); | 154 request.header.nlmsg_pid = getpid(); |
156 request.msg.rtgen_family = AF_UNSPEC; | 155 request.msg.rtgen_family = AF_UNSPEC; |
157 | 156 |
158 rv = HANDLE_EINTR(sendto(netlink_fd_, &request, request.header.nlmsg_len, | 157 rv = HANDLE_EINTR(sendto(netlink_fd_, |
159 0, reinterpret_cast<struct sockaddr*>(&peer), | 158 &request, |
| 159 request.header.nlmsg_len, |
| 160 0, |
| 161 reinterpret_cast<struct sockaddr*>(&peer), |
160 sizeof(peer))); | 162 sizeof(peer))); |
161 if (rv < 0) { | 163 if (rv < 0) { |
162 PLOG(ERROR) << "Could not send NETLINK request"; | 164 PLOG(ERROR) << "Could not send NETLINK request"; |
163 AbortAndForceOnline(); | 165 AbortAndForceOnline(); |
164 return; | 166 return; |
165 } | 167 } |
166 | 168 |
167 // Consume pending message to populate the AddressMap, but don't notify. | 169 // Consume pending message to populate the AddressMap, but don't notify. |
168 // Sending another request without first reading responses results in EBUSY. | 170 // Sending another request without first reading responses results in EBUSY. |
169 bool address_changed; | 171 bool address_changed; |
170 bool link_changed; | 172 bool link_changed; |
171 bool tunnel_changed; | 173 bool tunnel_changed; |
172 ReadMessages(&address_changed, &link_changed, &tunnel_changed); | 174 ReadMessages(&address_changed, &link_changed, &tunnel_changed); |
173 | 175 |
174 // Request dump of link state | 176 // Request dump of link state |
175 request.header.nlmsg_type = RTM_GETLINK; | 177 request.header.nlmsg_type = RTM_GETLINK; |
176 | 178 |
177 rv = HANDLE_EINTR(sendto(netlink_fd_, &request, request.header.nlmsg_len, 0, | 179 rv = HANDLE_EINTR(sendto(netlink_fd_, |
| 180 &request, |
| 181 request.header.nlmsg_len, |
| 182 0, |
178 reinterpret_cast<struct sockaddr*>(&peer), | 183 reinterpret_cast<struct sockaddr*>(&peer), |
179 sizeof(peer))); | 184 sizeof(peer))); |
180 if (rv < 0) { | 185 if (rv < 0) { |
181 PLOG(ERROR) << "Could not send NETLINK request"; | 186 PLOG(ERROR) << "Could not send NETLINK request"; |
182 AbortAndForceOnline(); | 187 AbortAndForceOnline(); |
183 return; | 188 return; |
184 } | 189 } |
185 | 190 |
186 // Consume pending message to populate links_online_, but don't notify. | 191 // Consume pending message to populate links_online_, but don't notify. |
187 ReadMessages(&address_changed, &link_changed, &tunnel_changed); | 192 ReadMessages(&address_changed, &link_changed, &tunnel_changed); |
(...skipping 29 matching lines...) Expand all Loading... |
217 AddressTrackerLinux::GetCurrentConnectionType() { | 222 AddressTrackerLinux::GetCurrentConnectionType() { |
218 // http://crbug.com/125097 | 223 // http://crbug.com/125097 |
219 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 224 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
220 base::AutoLock lock(is_offline_lock_); | 225 base::AutoLock lock(is_offline_lock_); |
221 // Make sure the initial offline state is set before returning. | 226 // Make sure the initial offline state is set before returning. |
222 while (!is_offline_initialized_) { | 227 while (!is_offline_initialized_) { |
223 is_offline_initialized_cv_.Wait(); | 228 is_offline_initialized_cv_.Wait(); |
224 } | 229 } |
225 // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN. | 230 // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN. |
226 // http://crbug.com/160537 | 231 // http://crbug.com/160537 |
227 return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE : | 232 return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE |
228 NetworkChangeNotifier::CONNECTION_UNKNOWN; | 233 : NetworkChangeNotifier::CONNECTION_UNKNOWN; |
229 } | 234 } |
230 | 235 |
231 void AddressTrackerLinux::ReadMessages(bool* address_changed, | 236 void AddressTrackerLinux::ReadMessages(bool* address_changed, |
232 bool* link_changed, | 237 bool* link_changed, |
233 bool* tunnel_changed) { | 238 bool* tunnel_changed) { |
234 *address_changed = false; | 239 *address_changed = false; |
235 *link_changed = false; | 240 *link_changed = false; |
236 *tunnel_changed = false; | 241 *tunnel_changed = false; |
237 char buffer[4096]; | 242 char buffer[4096]; |
238 bool first_loop = true; | 243 bool first_loop = true; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 for (struct nlmsghdr* header = reinterpret_cast<struct nlmsghdr*>(buffer); | 275 for (struct nlmsghdr* header = reinterpret_cast<struct nlmsghdr*>(buffer); |
271 NLMSG_OK(header, length); | 276 NLMSG_OK(header, length); |
272 header = NLMSG_NEXT(header, length)) { | 277 header = NLMSG_NEXT(header, length)) { |
273 switch (header->nlmsg_type) { | 278 switch (header->nlmsg_type) { |
274 case NLMSG_DONE: | 279 case NLMSG_DONE: |
275 return; | 280 return; |
276 case NLMSG_ERROR: { | 281 case NLMSG_ERROR: { |
277 const struct nlmsgerr* msg = | 282 const struct nlmsgerr* msg = |
278 reinterpret_cast<struct nlmsgerr*>(NLMSG_DATA(header)); | 283 reinterpret_cast<struct nlmsgerr*>(NLMSG_DATA(header)); |
279 LOG(ERROR) << "Unexpected netlink error " << msg->error << "."; | 284 LOG(ERROR) << "Unexpected netlink error " << msg->error << "."; |
280 } return; | 285 } |
| 286 return; |
281 case RTM_NEWADDR: { | 287 case RTM_NEWADDR: { |
282 IPAddressNumber address; | 288 IPAddressNumber address; |
283 bool really_deprecated; | 289 bool really_deprecated; |
284 if (GetAddress(header, &address, &really_deprecated)) { | 290 if (GetAddress(header, &address, &really_deprecated)) { |
285 base::AutoLock lock(address_map_lock_); | 291 base::AutoLock lock(address_map_lock_); |
286 struct ifaddrmsg* msg = | 292 struct ifaddrmsg* msg = |
287 reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); | 293 reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); |
288 // Routers may frequently (every few seconds) output the IPv6 ULA | 294 // Routers may frequently (every few seconds) output the IPv6 ULA |
289 // prefix which can cause the linux kernel to frequently output two | 295 // prefix which can cause the linux kernel to frequently output two |
290 // back-to-back messages, one without the deprecated flag and one with | 296 // back-to-back messages, one without the deprecated flag and one with |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 bool tunnel_changed; | 360 bool tunnel_changed; |
355 ReadMessages(&address_changed, &link_changed, &tunnel_changed); | 361 ReadMessages(&address_changed, &link_changed, &tunnel_changed); |
356 if (address_changed) | 362 if (address_changed) |
357 address_callback_.Run(); | 363 address_callback_.Run(); |
358 if (link_changed) | 364 if (link_changed) |
359 link_callback_.Run(); | 365 link_callback_.Run(); |
360 if (tunnel_changed) | 366 if (tunnel_changed) |
361 tunnel_callback_.Run(); | 367 tunnel_callback_.Run(); |
362 } | 368 } |
363 | 369 |
364 void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {} | 370 void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) { |
| 371 } |
365 | 372 |
366 void AddressTrackerLinux::CloseSocket() { | 373 void AddressTrackerLinux::CloseSocket() { |
367 if (netlink_fd_ >= 0 && IGNORE_EINTR(close(netlink_fd_)) < 0) | 374 if (netlink_fd_ >= 0 && IGNORE_EINTR(close(netlink_fd_)) < 0) |
368 PLOG(ERROR) << "Could not close NETLINK socket."; | 375 PLOG(ERROR) << "Could not close NETLINK socket."; |
369 netlink_fd_ = -1; | 376 netlink_fd_ = -1; |
370 } | 377 } |
371 | 378 |
372 bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const { | 379 bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const { |
373 // Linux kernel drivers/net/tun.c uses "tun" name prefix. | 380 // Linux kernel drivers/net/tun.c uses "tun" name prefix. |
374 return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0; | 381 return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0; |
375 } | 382 } |
376 | 383 |
377 } // namespace internal | 384 } // namespace internal |
378 } // namespace net | 385 } // namespace net |
OLD | NEW |