blob: 9459c2b2b5ac85f5bef15b78e902270cf306aabe [file] [log] [blame]
Wade Guthrie0d438532012-05-18 14:18:50 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Wade Guthriebb9fca22013-04-10 17:21:42 -07005#include "shill/netlink_manager.h"
Wade Guthrie0d438532012-05-18 14:18:50 -07006
Wade Guthrie89e6cb32013-03-07 08:03:45 -08007#include <netlink/netlink.h>
Wade Guthriebee87c22013-03-06 11:00:46 -08008#include <sys/select.h>
9#include <sys/time.h>
Wade Guthrie7347bf22013-04-30 11:21:51 -070010
Wade Guthrie84db7ce2013-06-12 11:40:49 -070011#include <list>
Wade Guthrie0d438532012-05-18 14:18:50 -070012#include <map>
Wade Guthrie0d438532012-05-18 14:18:50 -070013
14#include <base/memory/weak_ptr.h>
Wade Guthried6153612012-08-23 11:36:14 -070015#include <base/stl_util.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070016
Wade Guthriebee87c22013-03-06 11:00:46 -080017#include "shill/attribute_list.h"
repo syncbcaa6942013-01-02 15:38:21 -080018#include "shill/error.h"
Wade Guthrie89e6cb32013-03-07 08:03:45 -080019#include "shill/event_dispatcher.h"
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070020#include "shill/generic_netlink_message.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070021#include "shill/io_handler.h"
22#include "shill/logging.h"
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070023#include "shill/netlink_message.h"
Wade Guthrie92d06362013-04-25 15:41:30 -070024#include "shill/netlink_socket.h"
Wade Guthrie7347bf22013-04-30 11:21:51 -070025#include "shill/nl80211_message.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070026#include "shill/scope_logger.h"
Wade Guthriebee87c22013-03-06 11:00:46 -080027#include "shill/shill_time.h"
Wade Guthriefa2100e2013-05-15 10:11:22 -070028#include "shill/sockets.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070029
30using base::Bind;
31using base::LazyInstance;
Wade Guthrieb1ec8602012-10-18 17:26:14 -070032using std::list;
Wade Guthriec6c81962013-03-06 15:47:13 -080033using std::map;
Wade Guthrie0d438532012-05-18 14:18:50 -070034using std::string;
35
36namespace shill {
37
38namespace {
Wade Guthriebb9fca22013-04-10 17:21:42 -070039LazyInstance<NetlinkManager> g_netlink_manager = LAZY_INSTANCE_INITIALIZER;
Wade Guthrie0d438532012-05-18 14:18:50 -070040} // namespace
41
Wade Guthriebb9fca22013-04-10 17:21:42 -070042const char NetlinkManager::kEventTypeConfig[] = "config";
43const char NetlinkManager::kEventTypeScan[] = "scan";
44const char NetlinkManager::kEventTypeRegulatory[] = "regulatory";
45const char NetlinkManager::kEventTypeMlme[] = "mlme";
Wade Guthrie84db7ce2013-06-12 11:40:49 -070046const long NetlinkManager::kMaximumNewFamilyWaitSeconds = 1; // NOLINT
47const long NetlinkManager::kMaximumNewFamilyWaitMicroSeconds = 0; // NOLINT
48const long NetlinkManager::kResponseTimeoutSeconds = 5; // NOLINT
49const long NetlinkManager::kResponseTimeoutMicroSeconds = 0; // NOLINT
Wade Guthriebee87c22013-03-06 11:00:46 -080050
Wade Guthrie7347bf22013-04-30 11:21:51 -070051NetlinkManager::NetlinkResponseHandler::NetlinkResponseHandler(
52 const NetlinkManager::NetlinkAuxilliaryMessageHandler &error_handler)
53 : error_handler_(error_handler) {}
54
55NetlinkManager::NetlinkResponseHandler::~NetlinkResponseHandler() {}
56
57void NetlinkManager::NetlinkResponseHandler::HandleError(
Wade Guthrie84db7ce2013-06-12 11:40:49 -070058 AuxilliaryMessageType type, const NetlinkMessage *netlink_message) const {
Wade Guthrie7347bf22013-04-30 11:21:51 -070059 if (!error_handler_.is_null())
Wade Guthrie84db7ce2013-06-12 11:40:49 -070060 error_handler_.Run(type, netlink_message);
Wade Guthrie7347bf22013-04-30 11:21:51 -070061}
62
63class ControlResponseHandler : public NetlinkManager::NetlinkResponseHandler {
64 public:
65 ControlResponseHandler(
66 const NetlinkManager::ControlNetlinkMessageHandler &handler,
67 const NetlinkManager::NetlinkAuxilliaryMessageHandler &error_handler)
68 : NetlinkManager::NetlinkResponseHandler(error_handler),
69 handler_(handler) {}
70
71 virtual bool HandleMessage(
72 const NetlinkMessage &netlink_message) const override {
73 if (netlink_message.message_type() !=
74 ControlNetlinkMessage::GetMessageType()) {
75 LOG(ERROR) << "Message is type " << netlink_message.message_type()
76 << ", not " << ControlNetlinkMessage::GetMessageType()
77 << " (Control).";
78 return false;
79 }
80 if (!handler_.is_null()) {
81 const ControlNetlinkMessage *message =
82 dynamic_cast<const ControlNetlinkMessage *>(&netlink_message);
83 handler_.Run(*message);
84 }
85 return true;
86 }
87
88 private:
89 NetlinkManager::ControlNetlinkMessageHandler handler_;
90
91 DISALLOW_COPY_AND_ASSIGN(ControlResponseHandler);
92};
93
94class Nl80211ResponseHandler : public NetlinkManager::NetlinkResponseHandler {
95 public:
96 Nl80211ResponseHandler(
97 const NetlinkManager::Nl80211MessageHandler &handler,
98 const NetlinkManager::NetlinkAuxilliaryMessageHandler &error_handler)
99 : NetlinkManager::NetlinkResponseHandler(error_handler),
100 handler_(handler) {}
101
102 virtual bool HandleMessage(
103 const NetlinkMessage &netlink_message) const override {
104 if (netlink_message.message_type() != Nl80211Message::GetMessageType()) {
105 LOG(ERROR) << "Message is type " << netlink_message.message_type()
106 << ", not " << Nl80211Message::GetMessageType()
107 << " (Nl80211).";
108 return false;
109 }
110 if (!handler_.is_null()) {
111 const Nl80211Message *message =
112 dynamic_cast<const Nl80211Message *>(&netlink_message);
113 handler_.Run(*message);
114 }
115 return true;
116 }
117
118 private:
119 NetlinkManager::Nl80211MessageHandler handler_;
120
121 DISALLOW_COPY_AND_ASSIGN(Nl80211ResponseHandler);
122};
123
124
Wade Guthriebb9fca22013-04-10 17:21:42 -0700125NetlinkManager::MessageType::MessageType() :
Wade Guthriebee87c22013-03-06 11:00:46 -0800126 family_id(NetlinkMessage::kIllegalMessageType) {}
Wade Guthrie0d438532012-05-18 14:18:50 -0700127
Wade Guthriebb9fca22013-04-10 17:21:42 -0700128NetlinkManager::NetlinkManager()
Wade Guthriebee87c22013-03-06 11:00:46 -0800129 : dispatcher_(NULL),
Wade Guthrie0d438532012-05-18 14:18:50 -0700130 weak_ptr_factory_(this),
Wade Guthriebb9fca22013-04-10 17:21:42 -0700131 dispatcher_callback_(Bind(&NetlinkManager::OnRawNlMessageReceived,
repo syncbcaa6942013-01-02 15:38:21 -0800132 weak_ptr_factory_.GetWeakPtr())),
Wade Guthriefa2100e2013-05-15 10:11:22 -0700133 sock_(NULL),
134 time_(Time::GetInstance()) {}
Wade Guthrie0d438532012-05-18 14:18:50 -0700135
Wade Guthriebb9fca22013-04-10 17:21:42 -0700136NetlinkManager *NetlinkManager::GetInstance() {
137 return g_netlink_manager.Pointer();
Wade Guthrie0d438532012-05-18 14:18:50 -0700138}
139
Wade Guthriebb9fca22013-04-10 17:21:42 -0700140void NetlinkManager::Reset(bool full) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800141 ClearBroadcastHandlers();
Wade Guthriefa2100e2013-05-15 10:11:22 -0700142 message_handlers_.clear();
Wade Guthriebee87c22013-03-06 11:00:46 -0800143 message_types_.clear();
Darin Petkovd5818382013-01-28 16:27:07 +0100144 if (full) {
145 dispatcher_ = NULL;
146 delete sock_;
147 sock_ = NULL;
148 }
Wade Guthried6153612012-08-23 11:36:14 -0700149}
150
Wade Guthrie7347bf22013-04-30 11:21:51 -0700151void NetlinkManager::OnNewFamilyMessage(const ControlNetlinkMessage &message) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800152 uint16_t family_id;
153 string family_name;
154
Wade Guthrie7347bf22013-04-30 11:21:51 -0700155 if (!message.const_attributes()->GetU16AttributeValue(CTRL_ATTR_FAMILY_ID,
Wade Guthriebee87c22013-03-06 11:00:46 -0800156 &family_id)) {
157 LOG(ERROR) << __func__ << ": Couldn't get family_id attribute";
158 return;
159 }
160
Wade Guthrie7347bf22013-04-30 11:21:51 -0700161 if (!message.const_attributes()->GetStringAttributeValue(
Wade Guthriebee87c22013-03-06 11:00:46 -0800162 CTRL_ATTR_FAMILY_NAME, &family_name)) {
163 LOG(ERROR) << __func__ << ": Couldn't get family_name attribute";
164 return;
165 }
166
167 SLOG(WiFi, 3) << "Socket family '" << family_name << "' has id=" << family_id;
168
169 // Extract the available multicast groups from the message.
170 AttributeListConstRefPtr multicast_groups;
Wade Guthrie7347bf22013-04-30 11:21:51 -0700171 if (message.const_attributes()->ConstGetNestedAttributeList(
Wade Guthriebee87c22013-03-06 11:00:46 -0800172 CTRL_ATTR_MCAST_GROUPS, &multicast_groups)) {
173 AttributeListConstRefPtr current_group;
174
175 for (int i = 1;
176 multicast_groups->ConstGetNestedAttributeList(i, &current_group);
177 ++i) {
178 string group_name;
179 uint32_t group_id;
180 if (!current_group->GetStringAttributeValue(CTRL_ATTR_MCAST_GRP_NAME,
181 &group_name)) {
182 LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_NAME, found none";
183 continue;
184 }
185 if (!current_group->GetU32AttributeValue(CTRL_ATTR_MCAST_GRP_ID,
186 &group_id)) {
187 LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_ID, found none";
188 continue;
189 }
190 SLOG(WiFi, 3) << " Adding group '" << group_name << "' = " << group_id;
191 message_types_[family_name].groups[group_name] = group_id;
192 }
193 }
194
195 message_types_[family_name].family_id = family_id;
196}
197
Wade Guthrie7347bf22013-04-30 11:21:51 -0700198// static
Wade Guthrie84db7ce2013-06-12 11:40:49 -0700199void NetlinkManager::OnNetlinkMessageError(AuxilliaryMessageType type,
200 const NetlinkMessage *raw_message) {
201 switch (type) {
202 case kErrorFromKernel:
203 if (!raw_message) {
204 LOG(ERROR) << "Unknown error from kernel.";
205 break;
206 }
207 if (raw_message->message_type() == ErrorAckMessage::GetMessageType()) {
208 const ErrorAckMessage *error_ack_message =
209 dynamic_cast<const ErrorAckMessage *>(raw_message);
210 if (error_ack_message->error()) {
211 LOG(ERROR) << __func__ << ": Message (seq: "
212 << error_ack_message->sequence_number() << ") failed: "
213 << error_ack_message->ToString();
214 } else {
215 SLOG(WiFi, 6) << __func__ << ": Message (seq: "
216 << error_ack_message->sequence_number() << ") ACKed";
217 }
218 }
219 break;
220
221 case kUnexpectedResponseType:
222 LOG(ERROR) << "Message not handled by regular message handler:";
223 if (raw_message) {
224 raw_message->Print(0, 0);
225 }
226 break;
227
228 case kTimeoutWaitingForResponse:
229 LOG(WARNING) << "Timeout waiting for response";
230 break;
231
232 default:
233 LOG(ERROR) << "Unexpected auxilliary message type: " << type;
234 break;
Wade Guthrie7347bf22013-04-30 11:21:51 -0700235 }
Wade Guthrie7347bf22013-04-30 11:21:51 -0700236}
237
Wade Guthriebb9fca22013-04-10 17:21:42 -0700238bool NetlinkManager::Init() {
Wade Guthrie12f113a2013-03-12 17:15:46 -0700239 // Install message factory for control class of messages, which has
240 // statically-known message type.
241 message_factory_.AddFactoryMethod(
242 ControlNetlinkMessage::kMessageType,
243 Bind(&ControlNetlinkMessage::CreateMessage));
Wade Guthrie0d438532012-05-18 14:18:50 -0700244 if (!sock_) {
Wade Guthriecc53f232013-03-05 13:22:23 -0800245 sock_ = new NetlinkSocket;
Wade Guthrie0d438532012-05-18 14:18:50 -0700246 if (!sock_) {
247 LOG(ERROR) << "No memory";
248 return false;
249 }
250
251 if (!sock_->Init()) {
252 return false;
253 }
254 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800255 return true;
256}
Wade Guthrie0d438532012-05-18 14:18:50 -0700257
Wade Guthriebb9fca22013-04-10 17:21:42 -0700258void NetlinkManager::Start(EventDispatcher *dispatcher) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800259 dispatcher_ = dispatcher;
260 CHECK(dispatcher_);
261 // Install ourselves in the shill mainloop so we receive messages on the
262 // netlink socket.
263 dispatcher_handler_.reset(dispatcher_->CreateInputHandler(
264 file_descriptor(),
265 dispatcher_callback_,
Wade Guthriebb9fca22013-04-10 17:21:42 -0700266 Bind(&NetlinkManager::OnReadError, weak_ptr_factory_.GetWeakPtr())));
Wade Guthriebee87c22013-03-06 11:00:46 -0800267}
268
Wade Guthriebb9fca22013-04-10 17:21:42 -0700269int NetlinkManager::file_descriptor() const {
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800270 return (sock_ ? sock_->file_descriptor() : -1);
271}
272
Wade Guthriefa2100e2013-05-15 10:11:22 -0700273uint16_t NetlinkManager::GetFamily(const string &name,
Wade Guthrie12f113a2013-03-12 17:15:46 -0700274 const NetlinkMessageFactory::FactoryMethod &message_factory) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800275 MessageType &message_type = message_types_[name];
276 if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
277 return message_type.family_id;
278 }
279 if (!sock_) {
280 LOG(FATAL) << "Must call |Init| before this method.";
281 return false;
Wade Guthrie0d438532012-05-18 14:18:50 -0700282 }
283
Wade Guthriebee87c22013-03-06 11:00:46 -0800284 GetFamilyMessage msg;
Wade Guthriebee87c22013-03-06 11:00:46 -0800285 if (!msg.attributes()->SetStringAttributeValue(CTRL_ATTR_FAMILY_NAME, name)) {
286 LOG(ERROR) << "Couldn't set string attribute";
287 return false;
288 }
Wade Guthrie7347bf22013-04-30 11:21:51 -0700289 SendControlMessage(&msg,
290 Bind(&NetlinkManager::OnNewFamilyMessage,
291 weak_ptr_factory_.GetWeakPtr()),
292 Bind(&NetlinkManager::OnNetlinkMessageError));
Wade Guthriebee87c22013-03-06 11:00:46 -0800293
294 // Wait for a response. The code absolutely needs family_ids for its
295 // message types so we do a synchronous wait. It's OK to do this because
296 // a) libnl does a synchronous wait (so there's prior art), b) waiting
297 // asynchronously would add significant and unnecessary complexity to the
298 // code that deals with pending messages that could, potentially, be waiting
299 // for a message type, and c) it really doesn't take very long for the
300 // GETFAMILY / NEWFAMILY transaction to transpire (this transaction was timed
301 // over 20 times and found a maximum duration of 11.1 microseconds and an
302 // average of 4.0 microseconds).
Wade Guthrief788a0a2013-06-10 09:50:26 -0700303 struct timeval now, end_time;
Wade Guthriebee87c22013-03-06 11:00:46 -0800304 struct timeval maximum_wait_duration = {kMaximumNewFamilyWaitSeconds,
305 kMaximumNewFamilyWaitMicroSeconds};
Wade Guthrief788a0a2013-06-10 09:50:26 -0700306 time_->GetTimeMonotonic(&now);
307 timeradd(&now, &maximum_wait_duration, &end_time);
Wade Guthriebee87c22013-03-06 11:00:46 -0800308
309 do {
310 // Wait with timeout for a message from the netlink socket.
311 fd_set read_fds;
312 FD_ZERO(&read_fds);
313 FD_SET(file_descriptor(), &read_fds);
314 struct timeval wait_duration;
315 timersub(&end_time, &now, &wait_duration);
Wade Guthriefa2100e2013-05-15 10:11:22 -0700316 int result = sock_->sockets()->Select(file_descriptor() + 1,
317 &read_fds,
318 NULL,
319 NULL,
320 &wait_duration);
Wade Guthriebee87c22013-03-06 11:00:46 -0800321 if (result < 0) {
322 PLOG(ERROR) << "Select failed";
323 return NetlinkMessage::kIllegalMessageType;
324 }
325 if (result == 0) {
326 LOG(WARNING) << "Timed out waiting for family_id for family '"
327 << name << "'.";
328 return NetlinkMessage::kIllegalMessageType;
329 }
330
331 // Read and process any messages.
332 ByteString received;
333 sock_->RecvMessage(&received);
334 InputData input_data(received.GetData(), received.GetLength());
335 OnRawNlMessageReceived(&input_data);
336 if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
Wade Guthrie12f113a2013-03-12 17:15:46 -0700337 uint16_t family_id = message_type.family_id;
338 if (family_id != NetlinkMessage::kIllegalMessageType) {
339 message_factory_.AddFactoryMethod(family_id, message_factory);
340 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800341 return message_type.family_id;
342 }
Wade Guthriefa2100e2013-05-15 10:11:22 -0700343 time_->GetTimeMonotonic(&now);
Wade Guthriebee87c22013-03-06 11:00:46 -0800344 } while (timercmp(&now, &end_time, <));
345
346 LOG(ERROR) << "Timed out waiting for family_id for family '" << name << "'.";
347 return NetlinkMessage::kIllegalMessageType;
Wade Guthrie0d438532012-05-18 14:18:50 -0700348}
349
Wade Guthriebb9fca22013-04-10 17:21:42 -0700350bool NetlinkManager::AddBroadcastHandler(const NetlinkMessageHandler &handler) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800351 if (FindBroadcastHandler(handler)) {
352 LOG(WARNING) << "Trying to re-add a handler";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700353 return false; // Should only be one copy in the list.
354 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800355 if (handler.is_null()) {
356 LOG(WARNING) << "Trying to add a NULL handler";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700357 return false;
358 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800359 // And add the handler to the list.
Wade Guthriebb9fca22013-04-10 17:21:42 -0700360 SLOG(WiFi, 3) << "NetlinkManager::" << __func__ << " - adding handler";
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800361 broadcast_handlers_.push_back(handler);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700362 return true;
363}
364
Wade Guthriebb9fca22013-04-10 17:21:42 -0700365bool NetlinkManager::RemoveBroadcastHandler(
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800366 const NetlinkMessageHandler &handler) {
367 list<NetlinkMessageHandler>::iterator i;
368 for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
369 if ((*i).Equals(handler)) {
370 broadcast_handlers_.erase(i);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700371 // Should only be one copy in the list so we don't have to continue
372 // looking for another one.
373 return true;
374 }
375 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800376 LOG(WARNING) << "NetlinkMessageHandler not found.";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700377 return false;
378}
379
Wade Guthriebb9fca22013-04-10 17:21:42 -0700380bool NetlinkManager::FindBroadcastHandler(const NetlinkMessageHandler &handler)
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800381 const {
382 list<NetlinkMessageHandler>::const_iterator i;
383 for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
384 if ((*i).Equals(handler)) {
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700385 return true;
386 }
387 }
388 return false;
389}
390
Wade Guthriebb9fca22013-04-10 17:21:42 -0700391void NetlinkManager::ClearBroadcastHandlers() {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800392 broadcast_handlers_.clear();
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700393}
394
Wade Guthrie7347bf22013-04-30 11:21:51 -0700395bool NetlinkManager::SendControlMessage(
396 ControlNetlinkMessage *message,
397 const ControlNetlinkMessageHandler &message_handler,
398 const NetlinkAuxilliaryMessageHandler &error_handler) {
399 return SendMessageInternal(message,
400 new ControlResponseHandler(message_handler,
401 error_handler));
402}
403
404bool NetlinkManager::SendNl80211Message(
405 Nl80211Message *message,
406 const Nl80211MessageHandler &message_handler,
407 const NetlinkAuxilliaryMessageHandler &error_handler) {
408 return SendMessageInternal(message,
409 new Nl80211ResponseHandler(message_handler,
410 error_handler));
411}
412
413bool NetlinkManager::SendMessageInternal(
414 NetlinkMessage *message,
415 NetlinkManager::NetlinkResponseHandler *response_handler) {
Wade Guthrie5d53d492012-11-07 09:53:31 -0800416 if (!message) {
417 LOG(ERROR) << "Message is NULL.";
418 return false;
419 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800420
Wade Guthrie84db7ce2013-06-12 11:40:49 -0700421 // Clean out timed-out message handlers. The list of outstanding messages
422 // should be small so the time wasted by looking through all of them should
423 // be small.
424 struct timeval now;
425 time_->GetTimeMonotonic(&now);
426 map<uint32_t, NetlinkResponseHandlerRefPtr>::iterator handler_it =
427 message_handlers_.begin();
428 while (handler_it != message_handlers_.end()) {
429 if (timercmp(&now, &handler_it->second->delete_after(), >)) {
430 // A timeout isn't always unexpected so this is not a warning.
431 SLOG(WiFi, 3) << "Removing timed-out handler for sequence number "
432 << handler_it->first;
433 handler_it->second->HandleError(kTimeoutWaitingForResponse, NULL);
434 handler_it = message_handlers_.erase(handler_it);
435 } else {
436 ++handler_it;
437 }
438 }
439
440 // On to the business at hand...
Wade Guthriebee87c22013-03-06 11:00:46 -0800441 ByteString message_string = message->Encode(this->GetSequenceNumber());
Wade Guthriecc53f232013-03-05 13:22:23 -0800442
Wade Guthrie7347bf22013-04-30 11:21:51 -0700443 if (!response_handler) {
Wade Guthriecc53f232013-03-05 13:22:23 -0800444 SLOG(WiFi, 3) << "Handler for message was null.";
445 } else if (ContainsKey(message_handlers_, message->sequence_number())) {
446 LOG(ERROR) << "A handler already existed for sequence: "
Wade Guthriebee87c22013-03-06 11:00:46 -0800447 << message->sequence_number();
448 return false;
Wade Guthriecc53f232013-03-05 13:22:23 -0800449 } else {
Wade Guthrie84db7ce2013-06-12 11:40:49 -0700450 struct timeval response_timeout = {kResponseTimeoutSeconds,
451 kResponseTimeoutMicroSeconds};
452 struct timeval delete_after;
453 timeradd(&now, &response_timeout, &delete_after);
454 response_handler->set_delete_after(delete_after);
455
Wade Guthrie7347bf22013-04-30 11:21:51 -0700456 message_handlers_[message->sequence_number()] =
457 NetlinkResponseHandlerRefPtr(response_handler);
Wade Guthriecc53f232013-03-05 13:22:23 -0800458 }
Wade Guthrie8e278612013-02-26 10:32:34 -0800459
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700460 SLOG(WiFi, 5) << "NL Message " << message->sequence_number()
Wade Guthriecc53f232013-03-05 13:22:23 -0800461 << " Sending (" << message_string.GetLength()
462 << " bytes) ===>";
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700463 message->Print(6, 7);
464 NetlinkMessage::PrintBytes(8, message_string.GetConstData(),
Wade Guthriecc53f232013-03-05 13:22:23 -0800465 message_string.GetLength());
Wade Guthrie8e278612013-02-26 10:32:34 -0800466
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800467 if (!sock_->SendMessage(message_string)) {
Wade Guthrief48a1952013-03-04 17:33:47 -0800468 LOG(ERROR) << "Failed to send Netlink message.";
Wade Guthrie5d53d492012-11-07 09:53:31 -0800469 return false;
470 }
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700471 return true;
472}
473
Wade Guthriebb9fca22013-04-10 17:21:42 -0700474bool NetlinkManager::RemoveMessageHandler(const NetlinkMessage &message) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800475 if (!ContainsKey(message_handlers_, message.sequence_number())) {
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700476 return false;
477 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800478 message_handlers_.erase(message.sequence_number());
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700479 return true;
480}
481
Wade Guthriebb9fca22013-04-10 17:21:42 -0700482uint32_t NetlinkManager::GetSequenceNumber() {
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800483 return sock_ ?
Wade Guthrief48a1952013-03-04 17:33:47 -0800484 sock_->GetSequenceNumber() : NetlinkMessage::kBroadcastSequenceNumber;
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800485}
486
Wade Guthriebb9fca22013-04-10 17:21:42 -0700487bool NetlinkManager::SubscribeToEvents(const string &family_id,
488 const string &group_name) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800489 if (!ContainsKey(message_types_, family_id)) {
490 LOG(ERROR) << "Family '" << family_id << "' doesn't exist";
Wade Guthrie0d438532012-05-18 14:18:50 -0700491 return false;
492 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800493
494 if (!ContainsKey(message_types_[family_id].groups, group_name)) {
495 LOG(ERROR) << "Group '" << group_name << "' doesn't exist in family '"
496 << family_id << "'";
497 return false;
498 }
499
500 uint32_t group_id = message_types_[family_id].groups[group_name];
501 if (!sock_) {
502 LOG(FATAL) << "Need to call |Init| first.";
503 }
504 return sock_->SubscribeToEvents(group_id);
Wade Guthrie0d438532012-05-18 14:18:50 -0700505}
506
Wade Guthriebb9fca22013-04-10 17:21:42 -0700507void NetlinkManager::OnRawNlMessageReceived(InputData *data) {
repo syncbcaa6942013-01-02 15:38:21 -0800508 if (!data) {
509 LOG(ERROR) << __func__ << "() called with null header.";
510 return;
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700511 }
repo syncbcaa6942013-01-02 15:38:21 -0800512 unsigned char *buf = data->buf;
513 unsigned char *end = buf + data->len;
514 while (buf < end) {
515 nlmsghdr *msg = reinterpret_cast<nlmsghdr *>(buf);
516 // Discard the message if there're not enough bytes to a) tell the code how
517 // much space is in the message (i.e., to access nlmsg_len) or b) to hold
518 // the entire message. The odd calculation is there to keep the code from
519 // potentially calculating an illegal address (causes a segfault on some
520 // architectures).
521 size_t bytes_left = end - buf;
522 if (((bytes_left < (offsetof(nlmsghdr, nlmsg_len) +
Liam McLoughlinf4baef22012-08-01 19:08:25 -0700523 sizeof(msg->nlmsg_len))) ||
repo syncbcaa6942013-01-02 15:38:21 -0800524 (bytes_left < msg->nlmsg_len))) {
525 LOG(ERROR) << "Discarding incomplete message.";
526 return;
527 }
528 OnNlMessageReceived(msg);
529 buf += msg->nlmsg_len;
530 }
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700531}
Wade Guthrie0d438532012-05-18 14:18:50 -0700532
Wade Guthriebb9fca22013-04-10 17:21:42 -0700533void NetlinkManager::OnNlMessageReceived(nlmsghdr *msg) {
Christopher Wiley393b93f2012-11-08 17:30:58 -0800534 if (!msg) {
535 LOG(ERROR) << __func__ << "() called with null header.";
repo syncbcaa6942013-01-02 15:38:21 -0800536 return;
Christopher Wiley393b93f2012-11-08 17:30:58 -0800537 }
538 const uint32 sequence_number = msg->nlmsg_seq;
Wade Guthrie84db7ce2013-06-12 11:40:49 -0700539
Wade Guthrie12f113a2013-03-12 17:15:46 -0700540 scoped_ptr<NetlinkMessage> message(message_factory_.CreateMessage(msg));
Wade Guthrie0d438532012-05-18 14:18:50 -0700541 if (message == NULL) {
Wade Guthrie8e278612013-02-26 10:32:34 -0800542 SLOG(WiFi, 3) << "NL Message " << sequence_number << " <===";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700543 SLOG(WiFi, 3) << __func__ << "(msg:NULL)";
repo syncbcaa6942013-01-02 15:38:21 -0800544 return; // Skip current message, continue parsing buffer.
Christopher Wiley393b93f2012-11-08 17:30:58 -0800545 }
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700546 SLOG(WiFi, 5) << "NL Message " << sequence_number
Wade Guthrie8e278612013-02-26 10:32:34 -0800547 << " Received (" << msg->nlmsg_len << " bytes) <===";
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700548 message->Print(6, 7);
Wade Guthrief48a1952013-03-04 17:33:47 -0800549 NetlinkMessage::PrintBytes(8, reinterpret_cast<const unsigned char *>(msg),
Wade Guthrie8e278612013-02-26 10:32:34 -0800550 msg->nlmsg_len);
551
Wade Guthrie7347bf22013-04-30 11:21:51 -0700552 if (message->message_type() == ErrorAckMessage::GetMessageType()) {
553 SLOG(WiFi, 3) << "Error response to message " << sequence_number;
554 const ErrorAckMessage *error_ack_message =
555 dynamic_cast<const ErrorAckMessage *>(message.get());
556 if (error_ack_message->error()) {
557 if (ContainsKey(message_handlers_, sequence_number)) {
558 SLOG(WiFi, 6) << "Found message-specific error handler";
Wade Guthrie84db7ce2013-06-12 11:40:49 -0700559 message_handlers_[sequence_number]->HandleError(kErrorFromKernel,
560 message.get());
Wade Guthriebee87c22013-03-06 11:00:46 -0800561 message_handlers_.erase(sequence_number);
Wade Guthriebee87c22013-03-06 11:00:46 -0800562 }
Wade Guthrie7347bf22013-04-30 11:21:51 -0700563 } else {
564 SLOG(WiFi, 3) << "ACK message -- not removing callback";
565 }
566 return;
567 }
568
569 if (ContainsKey(message_handlers_, sequence_number)) {
570 SLOG(WiFi, 6) << "Found message-specific handler";
571 if (!message_handlers_[sequence_number]->HandleMessage(*message)) {
572 LOG(ERROR) << "Couldn't call message handler for " << sequence_number;
573 // Call the error handler but, since we don't have an |ErrorAckMessage|,
574 // we'll have to pass a NULL pointer.
Wade Guthrie84db7ce2013-06-12 11:40:49 -0700575 message_handlers_[sequence_number]->HandleError(kUnexpectedResponseType,
576 NULL);
Wade Guthrie7347bf22013-04-30 11:21:51 -0700577 }
578 if ((message->flags() & NLM_F_MULTI) &&
Wade Guthriebee87c22013-03-06 11:00:46 -0800579 (message->message_type() != NLMSG_DONE)) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700580 SLOG(WiFi, 6) << "Multi-part message -- not removing callback";
Wade Guthriebee87c22013-03-06 11:00:46 -0800581 } else {
Wade Guthrie7347bf22013-04-30 11:21:51 -0700582 SLOG(WiFi, 6) << "Removing callbacks";
Wade Guthriebee87c22013-03-06 11:00:46 -0800583 message_handlers_.erase(sequence_number);
584 }
Wade Guthrie7347bf22013-04-30 11:21:51 -0700585 return;
586 }
587
588 for (const auto &handler : broadcast_handlers_) {
589 SLOG(WiFi, 6) << "Calling broadcast handler";
590 if (!handler.is_null()) {
591 handler.Run(*message);
Wade Guthrie0d438532012-05-18 14:18:50 -0700592 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700593 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700594}
595
Wade Guthriebb9fca22013-04-10 17:21:42 -0700596void NetlinkManager::OnReadError(const Error &error) {
597 // TODO(wdg): When netlink_manager is used for scan, et al., this should
598 // either be LOG(FATAL) or the code should properly deal with errors,
599 // e.g., dropped messages due to the socket buffer being full.
600 LOG(ERROR) << "NetlinkManager's netlink Socket read returns error: "
repo syncbcaa6942013-01-02 15:38:21 -0800601 << error.message();
602}
603
604
Wade Guthrie0d438532012-05-18 14:18:50 -0700605} // namespace shill.