• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/net/netlink_manager.h"
18 
19 #include <errno.h>
20 #include <sys/select.h>
21 #include <sys/time.h>
22 
23 #include <list>
24 #include <map>
25 #include <queue>
26 
27 #include <base/location.h>
28 #include <base/logging.h>
29 #include <base/memory/weak_ptr.h>
30 #include <base/message_loop/message_loop.h>
31 #include <base/stl_util.h>
32 
33 #include "shill/net/attribute_list.h"
34 #include "shill/net/generic_netlink_message.h"
35 #include "shill/net/io_handler.h"
36 #include "shill/net/netlink_message.h"
37 #include "shill/net/netlink_packet.h"
38 #include "shill/net/nl80211_message.h"
39 #include "shill/net/shill_time.h"
40 #include "shill/net/sockets.h"
41 
42 using base::Bind;
43 using base::LazyInstance;
44 using base::MessageLoop;
45 using std::list;
46 using std::map;
47 using std::string;
48 
49 namespace shill {
50 
51 namespace {
52 LazyInstance<NetlinkManager> g_netlink_manager = LAZY_INSTANCE_INITIALIZER;
53 }  // namespace
54 
55 const char NetlinkManager::kEventTypeConfig[] = "config";
56 const char NetlinkManager::kEventTypeScan[] = "scan";
57 const char NetlinkManager::kEventTypeRegulatory[] = "regulatory";
58 const char NetlinkManager::kEventTypeMlme[] = "mlme";
59 const long NetlinkManager::kMaximumNewFamilyWaitSeconds = 1;  // NOLINT
60 const long NetlinkManager::kMaximumNewFamilyWaitMicroSeconds = 0;  // NOLINT
61 const long NetlinkManager::kResponseTimeoutSeconds = 5;  // NOLINT
62 const long NetlinkManager::kResponseTimeoutMicroSeconds = 0;  // NOLINT
63 const long NetlinkManager::kPendingDumpTimeoutMilliseconds = 500;  // NOLINT
64 const long NetlinkManager::kNlMessageRetryDelayMilliseconds = 300;  // NOLINT
65 const int NetlinkManager::kMaxNlMessageRetries = 1;  // NOLINT
66 
NetlinkResponseHandler(const NetlinkManager::NetlinkAckHandler & ack_handler,const NetlinkManager::NetlinkAuxilliaryMessageHandler & error_handler)67 NetlinkManager::NetlinkResponseHandler::NetlinkResponseHandler(
68     const NetlinkManager::NetlinkAckHandler& ack_handler,
69     const NetlinkManager::NetlinkAuxilliaryMessageHandler& error_handler)
70     : ack_handler_(ack_handler),
71       error_handler_(error_handler) {}
72 
~NetlinkResponseHandler()73 NetlinkManager::NetlinkResponseHandler::~NetlinkResponseHandler() {}
74 
HandleError(AuxilliaryMessageType type,const NetlinkMessage * netlink_message) const75 void NetlinkManager::NetlinkResponseHandler::HandleError(
76     AuxilliaryMessageType type, const NetlinkMessage* netlink_message) const {
77   if (!error_handler_.is_null())
78     error_handler_.Run(type, netlink_message);
79 }
80 
HandleAck() const81 bool NetlinkManager::NetlinkResponseHandler::HandleAck() const {
82   if (!ack_handler_.is_null()) {
83     // Default behavior is not to remove callbacks. In the case where the
84     // callback is not successfully invoked, this is safe as it does not
85     // prevent any further responses from behind handled.
86     bool remove_callbacks = false;
87     ack_handler_.Run(&remove_callbacks);
88     // If there are no other handlers other than the Ack handler, then force
89     // the callback to be removed after handling the Ack.
90     return remove_callbacks || error_handler_.is_null();
91   } else {
92     // If there is no Ack handler, do not delete registered callbacks
93     // for this function because we are not explicitly told to do so.
94     return false;
95   }
96 }
97 
98 class ControlResponseHandler : public NetlinkManager::NetlinkResponseHandler {
99  public:
ControlResponseHandler(const NetlinkManager::NetlinkAckHandler & ack_handler,const NetlinkManager::NetlinkAuxilliaryMessageHandler & error_handler,const NetlinkManager::ControlNetlinkMessageHandler & handler)100   ControlResponseHandler(
101       const NetlinkManager::NetlinkAckHandler& ack_handler,
102       const NetlinkManager::NetlinkAuxilliaryMessageHandler& error_handler,
103       const NetlinkManager::ControlNetlinkMessageHandler& handler)
104     : NetlinkManager::NetlinkResponseHandler(ack_handler, error_handler),
105       handler_(handler) {}
106 
HandleMessage(const NetlinkMessage & netlink_message) const107   bool HandleMessage(const NetlinkMessage& netlink_message) const override {
108     if (netlink_message.message_type() !=
109         ControlNetlinkMessage::GetMessageType()) {
110       LOG(ERROR) << "Message is type " << netlink_message.message_type()
111                  << ", not " << ControlNetlinkMessage::GetMessageType()
112                  << " (Control).";
113       return false;
114     }
115     if (!handler_.is_null()) {
116       const ControlNetlinkMessage* message =
117           static_cast<const ControlNetlinkMessage*>(&netlink_message);
118       handler_.Run(*message);
119     }
120     return true;
121   }
122 
HandleAck() const123   bool HandleAck() const override {
124     if (handler_.is_null()) {
125       return NetlinkManager::NetlinkResponseHandler::HandleAck();
126     } else {
127       bool remove_callbacks = false;
128       NetlinkManager::NetlinkResponseHandler::ack_handler_.Run(
129           &remove_callbacks);
130       return remove_callbacks;
131     }
132   }
133 
134  private:
135   NetlinkManager::ControlNetlinkMessageHandler handler_;
136 
137   DISALLOW_COPY_AND_ASSIGN(ControlResponseHandler);
138 };
139 
140 class Nl80211ResponseHandler : public NetlinkManager::NetlinkResponseHandler {
141  public:
Nl80211ResponseHandler(const NetlinkManager::NetlinkAckHandler & ack_handler,const NetlinkManager::NetlinkAuxilliaryMessageHandler & error_handler,const NetlinkManager::Nl80211MessageHandler & handler)142   Nl80211ResponseHandler(
143       const NetlinkManager::NetlinkAckHandler& ack_handler,
144       const NetlinkManager::NetlinkAuxilliaryMessageHandler& error_handler,
145       const NetlinkManager::Nl80211MessageHandler& handler)
146     : NetlinkManager::NetlinkResponseHandler(ack_handler, error_handler),
147       handler_(handler) {}
148 
HandleMessage(const NetlinkMessage & netlink_message) const149   bool HandleMessage(const NetlinkMessage& netlink_message) const override {
150     if (netlink_message.message_type() != Nl80211Message::GetMessageType()) {
151       LOG(ERROR) << "Message is type " << netlink_message.message_type()
152                  << ", not " << Nl80211Message::GetMessageType()
153                  << " (Nl80211).";
154       return false;
155     }
156     if (!handler_.is_null()) {
157       const Nl80211Message* message =
158           static_cast<const Nl80211Message*>(&netlink_message);
159       handler_.Run(*message);
160     }
161     return true;
162   }
163 
HandleAck() const164   bool HandleAck() const override {
165     if (handler_.is_null()) {
166       return NetlinkManager::NetlinkResponseHandler::HandleAck();
167     } else {
168       bool remove_callbacks = false;
169       NetlinkManager::NetlinkResponseHandler::ack_handler_.Run(
170           &remove_callbacks);
171       return remove_callbacks;
172     }
173   }
174 
175  private:
176   NetlinkManager::Nl80211MessageHandler handler_;
177 
178   DISALLOW_COPY_AND_ASSIGN(Nl80211ResponseHandler);
179 };
180 
181 
MessageType()182 NetlinkManager::MessageType::MessageType() :
183   family_id(NetlinkMessage::kIllegalMessageType) {}
184 
NetlinkManager()185 NetlinkManager::NetlinkManager()
186     : weak_ptr_factory_(this),
187       dispatcher_callback_(Bind(&NetlinkManager::OnRawNlMessageReceived,
188                                 weak_ptr_factory_.GetWeakPtr())),
189       time_(Time::GetInstance()),
190       io_handler_factory_(
191           IOHandlerFactoryContainer::GetInstance()->GetIOHandlerFactory()),
192           dump_pending_(false) {}
193 
~NetlinkManager()194 NetlinkManager::~NetlinkManager() {}
195 
GetInstance()196 NetlinkManager* NetlinkManager::GetInstance() {
197   return g_netlink_manager.Pointer();
198 }
199 
Reset(bool full)200 void NetlinkManager::Reset(bool full) {
201   ClearBroadcastHandlers();
202   message_handlers_.clear();
203   message_types_.clear();
204   while (!pending_messages_.empty()) {
205     pending_messages_.pop();
206   }
207   pending_dump_timeout_callback_.Cancel();
208   resend_dump_message_callback_.Cancel();
209   dump_pending_ = false;
210   if (full) {
211     sock_.reset();
212   }
213 }
214 
OnNewFamilyMessage(const ControlNetlinkMessage & message)215 void NetlinkManager::OnNewFamilyMessage(const ControlNetlinkMessage& message) {
216   uint16_t family_id;
217   string family_name;
218 
219   if (!message.const_attributes()->GetU16AttributeValue(CTRL_ATTR_FAMILY_ID,
220                                                          &family_id)) {
221     LOG(ERROR) << __func__ << ": Couldn't get family_id attribute";
222     return;
223   }
224 
225   if (!message.const_attributes()->GetStringAttributeValue(
226       CTRL_ATTR_FAMILY_NAME, &family_name)) {
227     LOG(ERROR) << __func__ << ": Couldn't get family_name attribute";
228     return;
229   }
230 
231   VLOG(3) << "Socket family '" << family_name << "' has id=" << family_id;
232 
233   // Extract the available multicast groups from the message.
234   AttributeListConstRefPtr multicast_groups;
235   if (message.const_attributes()->ConstGetNestedAttributeList(
236       CTRL_ATTR_MCAST_GROUPS, &multicast_groups)) {
237     AttributeListConstRefPtr current_group;
238 
239     for (int i = 1;
240          multicast_groups->ConstGetNestedAttributeList(i, &current_group);
241          ++i) {
242       string group_name;
243       uint32_t group_id;
244       if (!current_group->GetStringAttributeValue(CTRL_ATTR_MCAST_GRP_NAME,
245                                                   &group_name)) {
246         LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_NAME, found none";
247         continue;
248       }
249       if (!current_group->GetU32AttributeValue(CTRL_ATTR_MCAST_GRP_ID,
250                                                &group_id)) {
251         LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_ID, found none";
252         continue;
253       }
254       VLOG(3) << "  Adding group '" << group_name << "' = " << group_id;
255       message_types_[family_name].groups[group_name] = group_id;
256     }
257   }
258 
259   message_types_[family_name].family_id = family_id;
260 }
261 
262 // static
OnNetlinkMessageError(AuxilliaryMessageType type,const NetlinkMessage * raw_message)263 void NetlinkManager::OnNetlinkMessageError(AuxilliaryMessageType type,
264                                            const NetlinkMessage* raw_message) {
265   switch (type) {
266     case kErrorFromKernel:
267       if (!raw_message) {
268         LOG(ERROR) << "Unknown error from kernel.";
269         break;
270       }
271       if (raw_message->message_type() == ErrorAckMessage::GetMessageType()) {
272         const ErrorAckMessage* error_ack_message =
273             static_cast<const ErrorAckMessage*>(raw_message);
274         // error_ack_message->error() should be non-zero (i.e. not an ACK),
275         // since ACKs would be routed to a NetlinkAckHandler in
276         // NetlinkManager::OnNlMessageReceived.
277         LOG(ERROR) << __func__
278                    << ": Message (seq: " << error_ack_message->sequence_number()
279                    << ") failed: " << error_ack_message->ToString();
280       }
281       break;
282 
283     case kUnexpectedResponseType:
284       LOG(ERROR) << "Message not handled by regular message handler:";
285       if (raw_message) {
286         raw_message->Print(0, 0);
287       }
288       break;
289 
290     case kTimeoutWaitingForResponse:
291       LOG(WARNING) << "Timeout waiting for response";
292       break;
293 
294     default:
295       LOG(ERROR) << "Unexpected auxilliary message type: " << type;
296       break;
297   }
298 }
299 
Init()300 bool NetlinkManager::Init() {
301   // Install message factory for control class of messages, which has
302   // statically-known message type.
303   message_factory_.AddFactoryMethod(
304       ControlNetlinkMessage::kMessageType,
305       Bind(&ControlNetlinkMessage::CreateMessage));
306   if (!sock_) {
307     sock_.reset(new NetlinkSocket);
308     if (!sock_) {
309       LOG(ERROR) << "No memory";
310       return false;
311     }
312 
313     if (!sock_->Init()) {
314       return false;
315     }
316   }
317   return true;
318 }
319 
Start()320 void NetlinkManager::Start() {
321   // Create an IO handler for receiving messages on the netlink socket.
322   // IO handler will be installed to the current message loop.
323   dispatcher_handler_.reset(io_handler_factory_->CreateIOInputHandler(
324       file_descriptor(),
325       dispatcher_callback_,
326       Bind(&NetlinkManager::OnReadError, weak_ptr_factory_.GetWeakPtr())));
327 }
328 
file_descriptor() const329 int NetlinkManager::file_descriptor() const {
330   return (sock_ ? sock_->file_descriptor() : Sockets::kInvalidFileDescriptor);
331 }
332 
GetFamily(const string & name,const NetlinkMessageFactory::FactoryMethod & message_factory)333 uint16_t NetlinkManager::GetFamily(const string& name,
334     const NetlinkMessageFactory::FactoryMethod& message_factory) {
335   MessageType& message_type = message_types_[name];
336   if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
337     return message_type.family_id;
338   }
339   if (!sock_) {
340     LOG(FATAL) << "Must call |Init| before this method.";
341     return false;
342   }
343 
344   GetFamilyMessage msg;
345   if (!msg.attributes()->SetStringAttributeValue(CTRL_ATTR_FAMILY_NAME, name)) {
346     LOG(ERROR) << "Couldn't set string attribute";
347     return false;
348   }
349   SendControlMessage(&msg,
350                      Bind(&NetlinkManager::OnNewFamilyMessage,
351                           weak_ptr_factory_.GetWeakPtr()),
352                      Bind(&NetlinkManager::OnAckDoNothing),
353                      Bind(&NetlinkManager::OnNetlinkMessageError));
354 
355   // Wait for a response.  The code absolutely needs family_ids for its
356   // message types so we do a synchronous wait.  It's OK to do this because
357   // a) libnl does a synchronous wait (so there's prior art), b) waiting
358   // asynchronously would add significant and unnecessary complexity to the
359   // code that deals with pending messages that could, potentially, be waiting
360   // for a message type, and c) it really doesn't take very long for the
361   // GETFAMILY / NEWFAMILY transaction to transpire (this transaction was timed
362   // over 20 times and found a maximum duration of 11.1 microseconds and an
363   // average of 4.0 microseconds).
364   struct timeval now, end_time;
365   struct timeval maximum_wait_duration = {kMaximumNewFamilyWaitSeconds,
366                                           kMaximumNewFamilyWaitMicroSeconds};
367   time_->GetTimeMonotonic(&now);
368   timeradd(&now, &maximum_wait_duration, &end_time);
369 
370   do {
371     // Wait with timeout for a message from the netlink socket.
372     fd_set read_fds;
373     FD_ZERO(&read_fds);
374 
375     int socket = file_descriptor();
376     if (socket >= FD_SETSIZE)
377        LOG(FATAL) << "Invalid file_descriptor.";
378     FD_SET(socket, &read_fds);
379 
380     struct timeval wait_duration;
381     timersub(&end_time, &now, &wait_duration);
382     int result = sock_->sockets()->Select(file_descriptor() + 1,
383                                           &read_fds,
384                                           nullptr,
385                                           nullptr,
386                                           &wait_duration);
387     if (result < 0) {
388       PLOG(ERROR) << "Select failed";
389       return NetlinkMessage::kIllegalMessageType;
390     }
391     if (result == 0) {
392       LOG(WARNING) << "Timed out waiting for family_id for family '"
393                    << name << "'.";
394       return NetlinkMessage::kIllegalMessageType;
395     }
396 
397     // Read and process any messages.
398     ByteString received;
399     sock_->RecvMessage(&received);
400     InputData input_data(received.GetData(), received.GetLength());
401     OnRawNlMessageReceived(&input_data);
402     if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
403       uint16_t family_id = message_type.family_id;
404       if (family_id != NetlinkMessage::kIllegalMessageType) {
405         message_factory_.AddFactoryMethod(family_id, message_factory);
406       }
407       return message_type.family_id;
408     }
409     time_->GetTimeMonotonic(&now);
410   } while (timercmp(&now, &end_time, <));
411 
412   LOG(ERROR) << "Timed out waiting for family_id for family '" << name << "'.";
413   return NetlinkMessage::kIllegalMessageType;
414 }
415 
AddBroadcastHandler(const NetlinkMessageHandler & handler)416 bool NetlinkManager::AddBroadcastHandler(const NetlinkMessageHandler& handler) {
417   if (FindBroadcastHandler(handler)) {
418     LOG(WARNING) << "Trying to re-add a handler";
419     return false;  // Should only be one copy in the list.
420   }
421   if (handler.is_null()) {
422     LOG(WARNING) << "Trying to add a NULL handler";
423     return false;
424   }
425   // And add the handler to the list.
426   VLOG(3) << "NetlinkManager::" << __func__ << " - adding handler";
427   broadcast_handlers_.push_back(handler);
428   return true;
429 }
430 
RemoveBroadcastHandler(const NetlinkMessageHandler & handler)431 bool NetlinkManager::RemoveBroadcastHandler(
432     const NetlinkMessageHandler& handler) {
433   list<NetlinkMessageHandler>::iterator i;
434   for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
435     if ((*i).Equals(handler)) {
436       broadcast_handlers_.erase(i);
437       // Should only be one copy in the list so we don't have to continue
438       // looking for another one.
439       return true;
440     }
441   }
442   LOG(WARNING) << "NetlinkMessageHandler not found.";
443   return false;
444 }
445 
FindBroadcastHandler(const NetlinkMessageHandler & handler) const446 bool NetlinkManager::FindBroadcastHandler(const NetlinkMessageHandler& handler)
447     const {
448   for (const auto& broadcast_handler : broadcast_handlers_) {
449     if (broadcast_handler.Equals(handler)) {
450       return true;
451     }
452   }
453   return false;
454 }
455 
ClearBroadcastHandlers()456 void NetlinkManager::ClearBroadcastHandlers() {
457   broadcast_handlers_.clear();
458 }
459 
SendControlMessage(ControlNetlinkMessage * message,const ControlNetlinkMessageHandler & message_handler,const NetlinkAckHandler & ack_handler,const NetlinkAuxilliaryMessageHandler & error_handler)460 bool NetlinkManager::SendControlMessage(
461     ControlNetlinkMessage* message,
462     const ControlNetlinkMessageHandler& message_handler,
463     const NetlinkAckHandler& ack_handler,
464     const NetlinkAuxilliaryMessageHandler& error_handler) {
465   return SendOrPostMessage(message,
466                            new ControlResponseHandler(ack_handler,
467                                                       error_handler,
468                                                       message_handler));
469 }
470 
SendNl80211Message(Nl80211Message * message,const Nl80211MessageHandler & message_handler,const NetlinkAckHandler & ack_handler,const NetlinkAuxilliaryMessageHandler & error_handler)471 bool NetlinkManager::SendNl80211Message(
472     Nl80211Message* message,
473     const Nl80211MessageHandler& message_handler,
474     const NetlinkAckHandler& ack_handler,
475     const NetlinkAuxilliaryMessageHandler& error_handler) {
476   return SendOrPostMessage(message,
477                            new Nl80211ResponseHandler(ack_handler,
478                                                       error_handler,
479                                                       message_handler));
480 }
481 
SendOrPostMessage(NetlinkMessage * message,NetlinkManager::NetlinkResponseHandler * response_handler)482 bool NetlinkManager::SendOrPostMessage(
483     NetlinkMessage* message,
484     NetlinkManager::NetlinkResponseHandler* response_handler) {
485   if (!message) {
486     LOG(ERROR) << "Message is NULL.";
487     return false;
488   }
489 
490   const uint32_t sequence_number = this->GetSequenceNumber();
491   const bool is_dump_msg = message->flags() & NLM_F_DUMP;
492   NetlinkPendingMessage pending_message(
493       sequence_number, is_dump_msg, message->Encode(sequence_number),
494       NetlinkResponseHandlerRefPtr(response_handler));
495 
496   // TODO(samueltan): print this debug message above the actual call to
497   // NetlinkSocket::SendMessage in NetlinkManager::SendMessageInternal.
498   VLOG(5) << "NL Message " << pending_message.sequence_number << " to send ("
499           << pending_message.message_string.GetLength() << " bytes) ===>";
500   message->Print(6, 7);
501   NetlinkMessage::PrintBytes(8, pending_message.message_string.GetConstData(),
502                              pending_message.message_string.GetLength());
503 
504   if (is_dump_msg) {
505     pending_messages_.push(pending_message);
506     if (IsDumpPending()) {
507       VLOG(5) << "Dump pending -- will send message after dump is complete";
508       return true;
509     }
510   }
511   return RegisterHandlersAndSendMessage(pending_message);
512 }
513 
RegisterHandlersAndSendMessage(const NetlinkPendingMessage & pending_message)514 bool NetlinkManager::RegisterHandlersAndSendMessage(
515     const NetlinkPendingMessage& pending_message) {
516   // Clean out timed-out message handlers.  The list of outstanding messages
517   // should be small so the time wasted by looking through all of them should
518   // be small.
519   struct timeval now;
520   time_->GetTimeMonotonic(&now);
521   map<uint32_t, NetlinkResponseHandlerRefPtr>::iterator handler_it =
522       message_handlers_.begin();
523   while (handler_it != message_handlers_.end()) {
524     if (timercmp(&now, &handler_it->second->delete_after(), >)) {
525       // A timeout isn't always unexpected so this is not a warning.
526       VLOG(3) << "Removing timed-out handler for sequence number "
527               << handler_it->first;
528       handler_it->second->HandleError(kTimeoutWaitingForResponse, nullptr);
529       handler_it = message_handlers_.erase(handler_it);
530     } else {
531       ++handler_it;
532     }
533   }
534 
535   // Register handlers for replies to this message.
536   if (!pending_message.handler) {
537     VLOG(3) << "Handler for message was null.";
538   } else if (ContainsKey(message_handlers_, pending_message.sequence_number)) {
539     LOG(ERROR) << "A handler already existed for sequence: "
540                << pending_message.sequence_number;
541     return false;
542   } else {
543     struct timeval response_timeout = {kResponseTimeoutSeconds,
544                                        kResponseTimeoutMicroSeconds};
545     struct timeval delete_after;
546     timeradd(&now, &response_timeout, &delete_after);
547     pending_message.handler->set_delete_after(delete_after);
548 
549     message_handlers_[pending_message.sequence_number] =
550         pending_message.handler;
551   }
552   return SendMessageInternal(pending_message);
553 }
554 
SendMessageInternal(const NetlinkPendingMessage & pending_message)555 bool NetlinkManager::SendMessageInternal(
556     const NetlinkPendingMessage& pending_message) {
557   VLOG(5) << "Sending NL message " << pending_message.sequence_number;
558 
559   if (!sock_->SendMessage(pending_message.message_string)) {
560     LOG(ERROR) << "Failed to send Netlink message.";
561     return false;
562   }
563   if (pending_message.is_dump_request) {
564     VLOG(5) << "Waiting for replies to NL dump message "
565             << pending_message.sequence_number;
566     dump_pending_ = true;
567     pending_dump_timeout_callback_.Reset(Bind(
568         &NetlinkManager::OnPendingDumpTimeout, weak_ptr_factory_.GetWeakPtr()));
569     MessageLoop::current()->PostDelayedTask(
570         FROM_HERE, pending_dump_timeout_callback_.callback(),
571         base::TimeDelta::FromMilliseconds(kPendingDumpTimeoutMilliseconds));
572   }
573   return true;
574 }
575 
InferMessageContext(const NetlinkPacket & packet)576 NetlinkMessage::MessageContext NetlinkManager::InferMessageContext(
577     const NetlinkPacket& packet) {
578   NetlinkMessage::MessageContext context;
579 
580   const uint32_t sequence_number = packet.GetMessageSequence();
581   if (!ContainsKey(message_handlers_, sequence_number) &&
582       packet.GetMessageType() != ErrorAckMessage::kMessageType) {
583     context.is_broadcast = true;
584   }
585 
586   genlmsghdr genl_header;
587   if (packet.GetMessageType() == Nl80211Message::GetMessageType() &&
588       packet.GetGenlMsgHdr(&genl_header)) {
589     context.nl80211_cmd = genl_header.cmd;
590   }
591 
592   return context;
593 }
594 
OnPendingDumpTimeout()595 void NetlinkManager::OnPendingDumpTimeout() {
596   VLOG(3) << "Timed out waiting for replies to NL dump message "
597           << PendingDumpSequenceNumber();
598   CallErrorHandler(PendingDumpSequenceNumber(), kTimeoutWaitingForResponse,
599                    nullptr);
600   OnPendingDumpComplete();
601 }
602 
OnPendingDumpComplete()603 void NetlinkManager::OnPendingDumpComplete() {
604   VLOG(3) << __func__;
605   dump_pending_ = false;
606   pending_dump_timeout_callback_.Cancel();
607   resend_dump_message_callback_.Cancel();
608   pending_messages_.pop();
609   if (!pending_messages_.empty()) {
610     VLOG(3) << "Sending next pending message";
611     NetlinkPendingMessage to_send = pending_messages_.front();
612     RegisterHandlersAndSendMessage(to_send);
613   }
614 }
615 
IsDumpPending()616 bool NetlinkManager::IsDumpPending() {
617   return dump_pending_ && !pending_messages_.empty();
618 }
619 
PendingDumpSequenceNumber()620 uint32_t NetlinkManager::PendingDumpSequenceNumber() {
621   if (!IsDumpPending()) {
622     LOG(ERROR) << __func__ << ": no pending dump";
623     return 0;
624   }
625   return pending_messages_.front().sequence_number;
626 }
627 
RemoveMessageHandler(const NetlinkMessage & message)628 bool NetlinkManager::RemoveMessageHandler(const NetlinkMessage& message) {
629   if (!ContainsKey(message_handlers_, message.sequence_number())) {
630     return false;
631   }
632   message_handlers_.erase(message.sequence_number());
633   return true;
634 }
635 
GetSequenceNumber()636 uint32_t NetlinkManager::GetSequenceNumber() {
637   return sock_ ?
638       sock_->GetSequenceNumber() : NetlinkMessage::kBroadcastSequenceNumber;
639 }
640 
SubscribeToEvents(const string & family_id,const string & group_name)641 bool NetlinkManager::SubscribeToEvents(const string& family_id,
642                                        const string& group_name) {
643   if (!ContainsKey(message_types_, family_id)) {
644     LOG(ERROR) << "Family '" << family_id << "' doesn't exist";
645     return false;
646   }
647 
648   if (!ContainsKey(message_types_[family_id].groups, group_name)) {
649     LOG(ERROR) << "Group '" << group_name << "' doesn't exist in family '"
650                << family_id << "'";
651     return false;
652   }
653 
654   uint32_t group_id = message_types_[family_id].groups[group_name];
655   if (!sock_) {
656     LOG(FATAL) << "Need to call |Init| first.";
657   }
658   return sock_->SubscribeToEvents(group_id);
659 }
660 
OnRawNlMessageReceived(InputData * data)661 void NetlinkManager::OnRawNlMessageReceived(InputData* data) {
662   if (!data) {
663     LOG(ERROR) << __func__ << "() called with null header.";
664     return;
665   }
666   unsigned char* buf = data->buf;
667   unsigned char* end = buf + data->len;
668   while (buf < end) {
669     NetlinkPacket packet(buf, end - buf);
670     if (!packet.IsValid()) {
671       break;
672     }
673     buf += packet.GetLength();
674     OnNlMessageReceived(&packet);
675   }
676 }
677 
OnNlMessageReceived(NetlinkPacket * packet)678 void NetlinkManager::OnNlMessageReceived(NetlinkPacket* packet) {
679   if (!packet) {
680     LOG(ERROR) << __func__ << "() called with null packet.";
681     return;
682   }
683   const uint32_t sequence_number = packet->GetMessageSequence();
684 
685   std::unique_ptr<NetlinkMessage> message(
686       message_factory_.CreateMessage(packet, InferMessageContext(*packet)));
687   if (message == nullptr) {
688     VLOG(3) << "NL Message " << sequence_number << " <===";
689     VLOG(3) << __func__ << "(msg:NULL)";
690     return;  // Skip current message, continue parsing buffer.
691   }
692   VLOG(5) << "NL Message " << sequence_number << " Received ("
693           << packet->GetLength() << " bytes) <===";
694   message->Print(6, 7);
695   NetlinkMessage::PrintPacket(8, *packet);
696 
697   bool is_error_ack_message = false;
698   uint32_t error_code = 0;
699   if (message->message_type() == ErrorAckMessage::GetMessageType()) {
700     is_error_ack_message = true;
701     const ErrorAckMessage* error_ack_message =
702         static_cast<const ErrorAckMessage*>(message.get());
703     error_code = error_ack_message->error();
704   }
705 
706   // Note: assumes we only receive one reply to a dump request: an error
707   // message, an ACK, or a single multi-part reply. If we receive two replies,
708   // then we will stop waiting for replies after the first reply is processed
709   // here. This assumption should hold unless the NLM_F_ACK or NLM_F_ECHO
710   // flags are explicitly added to the dump request.
711   if (IsDumpPending() &&
712       (message->sequence_number() == PendingDumpSequenceNumber()) &&
713       !((message->flags() & NLM_F_MULTI) &&
714         (message->message_type() != NLMSG_DONE))) {
715     // Dump currently in progress, this message's sequence number matches that
716     // of the pending dump request, and we are not in the middle of receiving a
717     // multi-part reply.
718     if (is_error_ack_message && (error_code == static_cast<uint32_t>(-EBUSY))) {
719       VLOG(3) << "EBUSY reply received for NL dump message "
720               << PendingDumpSequenceNumber();
721       if (pending_messages_.front().retries_left) {
722         pending_messages_.front().last_received_error = error_code;
723         pending_dump_timeout_callback_.Cancel();
724         ResendPendingDumpMessageAfterDelay();
725         // Since we will resend the message, do not invoke error handler.
726         return;
727       } else {
728         VLOG(3) << "No more resend attempts left for NL dump message "
729                 << PendingDumpSequenceNumber() << " -- stop waiting "
730                                                   "for replies";
731         OnPendingDumpComplete();
732       }
733     } else {
734       VLOG(3) << "Reply received for NL dump message "
735               << PendingDumpSequenceNumber() << " -- stop waiting for replies";
736       OnPendingDumpComplete();
737     }
738   }
739 
740   if (is_error_ack_message) {
741     VLOG(3) << "Error/ACK response to message " << sequence_number;
742     if (error_code) {
743       CallErrorHandler(sequence_number, kErrorFromKernel, message.get());
744     } else {
745       if (ContainsKey(message_handlers_, sequence_number)) {
746         VLOG(6) << "Found message-specific ACK handler";
747         if (message_handlers_[sequence_number]->HandleAck()) {
748           VLOG(6) << "ACK handler invoked -- removing callback";
749           message_handlers_.erase(sequence_number);
750         } else {
751           VLOG(6) << "ACK handler invoked -- not removing callback";
752         }
753       }
754     }
755     return;
756   }
757 
758   if (ContainsKey(message_handlers_, sequence_number)) {
759     VLOG(6) << "Found message-specific handler";
760     if ((message->flags() & NLM_F_MULTI) &&
761         (message->message_type() == NLMSG_DONE)) {
762       message_handlers_[sequence_number]->HandleError(kDone, message.get());
763     } else if (!message_handlers_[sequence_number]->HandleMessage(*message)) {
764       LOG(ERROR) << "Couldn't call message handler for " << sequence_number;
765       // Call the error handler but, since we don't have an |ErrorAckMessage|,
766       // we'll have to pass a nullptr.
767       message_handlers_[sequence_number]->HandleError(kUnexpectedResponseType,
768                                                       nullptr);
769     }
770     if ((message->flags() & NLM_F_MULTI) &&
771         (message->message_type() != NLMSG_DONE)) {
772       VLOG(6) << "Multi-part message -- not removing callback";
773     } else {
774       VLOG(6) << "Removing callbacks";
775       message_handlers_.erase(sequence_number);
776     }
777     return;
778   }
779 
780   for (const auto& handler : broadcast_handlers_) {
781     VLOG(6) << "Calling broadcast handler";
782     if (!handler.is_null()) {
783       handler.Run(*message);
784     }
785   }
786 }
787 
ResendPendingDumpMessage()788 void NetlinkManager::ResendPendingDumpMessage() {
789   if (!IsDumpPending()) {
790     VLOG(3) << "No pending dump, so do not resend dump message";
791     return;
792   }
793   --pending_messages_.front().retries_left;
794   if (SendMessageInternal(pending_messages_.front())) {
795     VLOG(3) << "NL message " << PendingDumpSequenceNumber()
796             << " sent again successfully";
797     return;
798   }
799   VLOG(3) << "Failed to resend NL message " << PendingDumpSequenceNumber();
800   if (pending_messages_.front().retries_left) {
801     ResendPendingDumpMessageAfterDelay();
802   } else {
803     VLOG(3) << "No more resend attempts left for NL dump message "
804             << PendingDumpSequenceNumber() << " -- stop waiting "
805                                               "for replies";
806     ErrorAckMessage err_message(pending_messages_.front().last_received_error);
807     CallErrorHandler(PendingDumpSequenceNumber(), kErrorFromKernel,
808                      &err_message);
809     OnPendingDumpComplete();
810   }
811 }
812 
CallErrorHandler(uint32_t sequence_number,AuxilliaryMessageType type,const NetlinkMessage * netlink_message)813 void NetlinkManager::CallErrorHandler(uint32_t sequence_number,
814                                       AuxilliaryMessageType type,
815                                       const NetlinkMessage* netlink_message) {
816   if (ContainsKey(message_handlers_, sequence_number)) {
817     VLOG(6) << "Found message-specific error handler";
818     message_handlers_[sequence_number]->HandleError(type, netlink_message);
819     message_handlers_.erase(sequence_number);
820   }
821 }
822 
OnReadError(const string & error_msg)823 void NetlinkManager::OnReadError(const string& error_msg) {
824   // TODO(wdg): When netlink_manager is used for scan, et al., this should
825   // either be LOG(FATAL) or the code should properly deal with errors,
826   // e.g., dropped messages due to the socket buffer being full.
827   LOG(ERROR) << "NetlinkManager's netlink Socket read returns error: "
828              << error_msg;
829 }
830 
ResendPendingDumpMessageAfterDelay()831 void NetlinkManager::ResendPendingDumpMessageAfterDelay() {
832   VLOG(3) << "Resending NL dump message " << PendingDumpSequenceNumber()
833           << " after " << kNlMessageRetryDelayMilliseconds << " ms";
834   resend_dump_message_callback_.Reset(
835       Bind(&NetlinkManager::ResendPendingDumpMessage,
836            weak_ptr_factory_.GetWeakPtr()));
837   MessageLoop::current()->PostDelayedTask(
838       FROM_HERE, resend_dump_message_callback_.callback(),
839       base::TimeDelta::FromMilliseconds(kNlMessageRetryDelayMilliseconds));
840 }
841 
842 }  // namespace shill.
843