blob: ec301f5b5a130d1c1b5085866bfcfc2eb6cec1f4 [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 Guthrie0d438532012-05-18 14:18:50 -070011#include <map>
Wade Guthrie0d438532012-05-18 14:18:50 -070012
13#include <base/memory/weak_ptr.h>
Wade Guthried6153612012-08-23 11:36:14 -070014#include <base/stl_util.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070015
Wade Guthriebee87c22013-03-06 11:00:46 -080016#include "shill/attribute_list.h"
repo syncbcaa6942013-01-02 15:38:21 -080017#include "shill/error.h"
Wade Guthrie89e6cb32013-03-07 08:03:45 -080018#include "shill/event_dispatcher.h"
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070019#include "shill/generic_netlink_message.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070020#include "shill/io_handler.h"
21#include "shill/logging.h"
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070022#include "shill/netlink_message.h"
Wade Guthrie92d06362013-04-25 15:41:30 -070023#include "shill/netlink_socket.h"
Wade Guthrie7347bf22013-04-30 11:21:51 -070024#include "shill/nl80211_message.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070025#include "shill/scope_logger.h"
Wade Guthriebee87c22013-03-06 11:00:46 -080026#include "shill/shill_time.h"
Wade Guthriefa2100e2013-05-15 10:11:22 -070027#include "shill/sockets.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070028
29using base::Bind;
30using base::LazyInstance;
Wade Guthrieb1ec8602012-10-18 17:26:14 -070031using std::list;
Wade Guthriec6c81962013-03-06 15:47:13 -080032using std::map;
Wade Guthrie0d438532012-05-18 14:18:50 -070033using std::string;
34
35namespace shill {
36
37namespace {
Wade Guthriebb9fca22013-04-10 17:21:42 -070038LazyInstance<NetlinkManager> g_netlink_manager = LAZY_INSTANCE_INITIALIZER;
Wade Guthrie0d438532012-05-18 14:18:50 -070039} // namespace
40
Wade Guthriebb9fca22013-04-10 17:21:42 -070041const char NetlinkManager::kEventTypeConfig[] = "config";
42const char NetlinkManager::kEventTypeScan[] = "scan";
43const char NetlinkManager::kEventTypeRegulatory[] = "regulatory";
44const char NetlinkManager::kEventTypeMlme[] = "mlme";
45const long NetlinkManager::kMaximumNewFamilyWaitSeconds = 1;
46const long NetlinkManager::kMaximumNewFamilyWaitMicroSeconds = 0;
Wade Guthriebee87c22013-03-06 11:00:46 -080047
Wade Guthrie7347bf22013-04-30 11:21:51 -070048NetlinkManager::NetlinkResponseHandler::NetlinkResponseHandler(
49 const NetlinkManager::NetlinkAuxilliaryMessageHandler &error_handler)
50 : error_handler_(error_handler) {}
51
52NetlinkManager::NetlinkResponseHandler::~NetlinkResponseHandler() {}
53
54void NetlinkManager::NetlinkResponseHandler::HandleError(
55 const NetlinkMessage *netlink_message) const {
56 if (!error_handler_.is_null())
57 error_handler_.Run(netlink_message);
58}
59
60class ControlResponseHandler : public NetlinkManager::NetlinkResponseHandler {
61 public:
62 ControlResponseHandler(
63 const NetlinkManager::ControlNetlinkMessageHandler &handler,
64 const NetlinkManager::NetlinkAuxilliaryMessageHandler &error_handler)
65 : NetlinkManager::NetlinkResponseHandler(error_handler),
66 handler_(handler) {}
67
68 virtual bool HandleMessage(
69 const NetlinkMessage &netlink_message) const override {
70 if (netlink_message.message_type() !=
71 ControlNetlinkMessage::GetMessageType()) {
72 LOG(ERROR) << "Message is type " << netlink_message.message_type()
73 << ", not " << ControlNetlinkMessage::GetMessageType()
74 << " (Control).";
75 return false;
76 }
77 if (!handler_.is_null()) {
78 const ControlNetlinkMessage *message =
79 dynamic_cast<const ControlNetlinkMessage *>(&netlink_message);
80 handler_.Run(*message);
81 }
82 return true;
83 }
84
85 private:
86 NetlinkManager::ControlNetlinkMessageHandler handler_;
87
88 DISALLOW_COPY_AND_ASSIGN(ControlResponseHandler);
89};
90
91class Nl80211ResponseHandler : public NetlinkManager::NetlinkResponseHandler {
92 public:
93 Nl80211ResponseHandler(
94 const NetlinkManager::Nl80211MessageHandler &handler,
95 const NetlinkManager::NetlinkAuxilliaryMessageHandler &error_handler)
96 : NetlinkManager::NetlinkResponseHandler(error_handler),
97 handler_(handler) {}
98
99 virtual bool HandleMessage(
100 const NetlinkMessage &netlink_message) const override {
101 if (netlink_message.message_type() != Nl80211Message::GetMessageType()) {
102 LOG(ERROR) << "Message is type " << netlink_message.message_type()
103 << ", not " << Nl80211Message::GetMessageType()
104 << " (Nl80211).";
105 return false;
106 }
107 if (!handler_.is_null()) {
108 const Nl80211Message *message =
109 dynamic_cast<const Nl80211Message *>(&netlink_message);
110 handler_.Run(*message);
111 }
112 return true;
113 }
114
115 private:
116 NetlinkManager::Nl80211MessageHandler handler_;
117
118 DISALLOW_COPY_AND_ASSIGN(Nl80211ResponseHandler);
119};
120
121
Wade Guthriebb9fca22013-04-10 17:21:42 -0700122NetlinkManager::MessageType::MessageType() :
Wade Guthriebee87c22013-03-06 11:00:46 -0800123 family_id(NetlinkMessage::kIllegalMessageType) {}
Wade Guthrie0d438532012-05-18 14:18:50 -0700124
Wade Guthriebb9fca22013-04-10 17:21:42 -0700125NetlinkManager::NetlinkManager()
Wade Guthriebee87c22013-03-06 11:00:46 -0800126 : dispatcher_(NULL),
Wade Guthrie0d438532012-05-18 14:18:50 -0700127 weak_ptr_factory_(this),
Wade Guthriebb9fca22013-04-10 17:21:42 -0700128 dispatcher_callback_(Bind(&NetlinkManager::OnRawNlMessageReceived,
repo syncbcaa6942013-01-02 15:38:21 -0800129 weak_ptr_factory_.GetWeakPtr())),
Wade Guthriefa2100e2013-05-15 10:11:22 -0700130 sock_(NULL),
131 time_(Time::GetInstance()) {}
Wade Guthrie0d438532012-05-18 14:18:50 -0700132
Wade Guthriebb9fca22013-04-10 17:21:42 -0700133NetlinkManager *NetlinkManager::GetInstance() {
134 return g_netlink_manager.Pointer();
Wade Guthrie0d438532012-05-18 14:18:50 -0700135}
136
Wade Guthriebb9fca22013-04-10 17:21:42 -0700137void NetlinkManager::Reset(bool full) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800138 ClearBroadcastHandlers();
Wade Guthriefa2100e2013-05-15 10:11:22 -0700139 message_handlers_.clear();
Wade Guthriebee87c22013-03-06 11:00:46 -0800140 message_types_.clear();
Darin Petkovd5818382013-01-28 16:27:07 +0100141 if (full) {
142 dispatcher_ = NULL;
143 delete sock_;
144 sock_ = NULL;
145 }
Wade Guthried6153612012-08-23 11:36:14 -0700146}
147
Wade Guthrie7347bf22013-04-30 11:21:51 -0700148void NetlinkManager::OnNewFamilyMessage(const ControlNetlinkMessage &message) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800149 uint16_t family_id;
150 string family_name;
151
Wade Guthrie7347bf22013-04-30 11:21:51 -0700152 if (!message.const_attributes()->GetU16AttributeValue(CTRL_ATTR_FAMILY_ID,
Wade Guthriebee87c22013-03-06 11:00:46 -0800153 &family_id)) {
154 LOG(ERROR) << __func__ << ": Couldn't get family_id attribute";
155 return;
156 }
157
Wade Guthrie7347bf22013-04-30 11:21:51 -0700158 if (!message.const_attributes()->GetStringAttributeValue(
Wade Guthriebee87c22013-03-06 11:00:46 -0800159 CTRL_ATTR_FAMILY_NAME, &family_name)) {
160 LOG(ERROR) << __func__ << ": Couldn't get family_name attribute";
161 return;
162 }
163
164 SLOG(WiFi, 3) << "Socket family '" << family_name << "' has id=" << family_id;
165
166 // Extract the available multicast groups from the message.
167 AttributeListConstRefPtr multicast_groups;
Wade Guthrie7347bf22013-04-30 11:21:51 -0700168 if (message.const_attributes()->ConstGetNestedAttributeList(
Wade Guthriebee87c22013-03-06 11:00:46 -0800169 CTRL_ATTR_MCAST_GROUPS, &multicast_groups)) {
170 AttributeListConstRefPtr current_group;
171
172 for (int i = 1;
173 multicast_groups->ConstGetNestedAttributeList(i, &current_group);
174 ++i) {
175 string group_name;
176 uint32_t group_id;
177 if (!current_group->GetStringAttributeValue(CTRL_ATTR_MCAST_GRP_NAME,
178 &group_name)) {
179 LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_NAME, found none";
180 continue;
181 }
182 if (!current_group->GetU32AttributeValue(CTRL_ATTR_MCAST_GRP_ID,
183 &group_id)) {
184 LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_ID, found none";
185 continue;
186 }
187 SLOG(WiFi, 3) << " Adding group '" << group_name << "' = " << group_id;
188 message_types_[family_name].groups[group_name] = group_id;
189 }
190 }
191
192 message_types_[family_name].family_id = family_id;
193}
194
Wade Guthrie7347bf22013-04-30 11:21:51 -0700195// static
196void NetlinkManager::OnNetlinkMessageError(const NetlinkMessage *raw_message) {
197 if (!raw_message) {
198 LOG(ERROR) << "NetlinkManager error.";
199 return;
200 }
201 if (raw_message->message_type() == ErrorAckMessage::GetMessageType()) {
202 const ErrorAckMessage *error_ack_message =
203 dynamic_cast<const ErrorAckMessage *>(raw_message);
204 if (error_ack_message->error()) {
205 LOG(ERROR) << __func__ << ": Message (seq: "
206 << error_ack_message->sequence_number() << ") failed: "
207 << error_ack_message->ToString();
208 } else {
209 SLOG(WiFi, 6) << __func__ << ": Message (seq: "
210 << error_ack_message->sequence_number() << ") ACKed";
211 }
212 return;
213 }
214 LOG(ERROR) << "Not expecting this message:";
215 raw_message->Print(0, 0);
216}
217
Wade Guthriebb9fca22013-04-10 17:21:42 -0700218bool NetlinkManager::Init() {
Wade Guthrie12f113a2013-03-12 17:15:46 -0700219 // Install message factory for control class of messages, which has
220 // statically-known message type.
221 message_factory_.AddFactoryMethod(
222 ControlNetlinkMessage::kMessageType,
223 Bind(&ControlNetlinkMessage::CreateMessage));
Wade Guthrie0d438532012-05-18 14:18:50 -0700224 if (!sock_) {
Wade Guthriecc53f232013-03-05 13:22:23 -0800225 sock_ = new NetlinkSocket;
Wade Guthrie0d438532012-05-18 14:18:50 -0700226 if (!sock_) {
227 LOG(ERROR) << "No memory";
228 return false;
229 }
230
231 if (!sock_->Init()) {
232 return false;
233 }
234 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800235 return true;
236}
Wade Guthrie0d438532012-05-18 14:18:50 -0700237
Wade Guthriebb9fca22013-04-10 17:21:42 -0700238void NetlinkManager::Start(EventDispatcher *dispatcher) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800239 dispatcher_ = dispatcher;
240 CHECK(dispatcher_);
241 // Install ourselves in the shill mainloop so we receive messages on the
242 // netlink socket.
243 dispatcher_handler_.reset(dispatcher_->CreateInputHandler(
244 file_descriptor(),
245 dispatcher_callback_,
Wade Guthriebb9fca22013-04-10 17:21:42 -0700246 Bind(&NetlinkManager::OnReadError, weak_ptr_factory_.GetWeakPtr())));
Wade Guthriebee87c22013-03-06 11:00:46 -0800247}
248
Wade Guthriebb9fca22013-04-10 17:21:42 -0700249int NetlinkManager::file_descriptor() const {
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800250 return (sock_ ? sock_->file_descriptor() : -1);
251}
252
Wade Guthriefa2100e2013-05-15 10:11:22 -0700253uint16_t NetlinkManager::GetFamily(const string &name,
Wade Guthrie12f113a2013-03-12 17:15:46 -0700254 const NetlinkMessageFactory::FactoryMethod &message_factory) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800255 MessageType &message_type = message_types_[name];
256 if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
257 return message_type.family_id;
258 }
259 if (!sock_) {
260 LOG(FATAL) << "Must call |Init| before this method.";
261 return false;
Wade Guthrie0d438532012-05-18 14:18:50 -0700262 }
263
Wade Guthriebee87c22013-03-06 11:00:46 -0800264 GetFamilyMessage msg;
Wade Guthriebee87c22013-03-06 11:00:46 -0800265 if (!msg.attributes()->SetStringAttributeValue(CTRL_ATTR_FAMILY_NAME, name)) {
266 LOG(ERROR) << "Couldn't set string attribute";
267 return false;
268 }
Wade Guthrie7347bf22013-04-30 11:21:51 -0700269 SendControlMessage(&msg,
270 Bind(&NetlinkManager::OnNewFamilyMessage,
271 weak_ptr_factory_.GetWeakPtr()),
272 Bind(&NetlinkManager::OnNetlinkMessageError));
Wade Guthriebee87c22013-03-06 11:00:46 -0800273
274 // Wait for a response. The code absolutely needs family_ids for its
275 // message types so we do a synchronous wait. It's OK to do this because
276 // a) libnl does a synchronous wait (so there's prior art), b) waiting
277 // asynchronously would add significant and unnecessary complexity to the
278 // code that deals with pending messages that could, potentially, be waiting
279 // for a message type, and c) it really doesn't take very long for the
280 // GETFAMILY / NEWFAMILY transaction to transpire (this transaction was timed
281 // over 20 times and found a maximum duration of 11.1 microseconds and an
282 // average of 4.0 microseconds).
283 struct timeval start_time, now, end_time;
284 struct timeval maximum_wait_duration = {kMaximumNewFamilyWaitSeconds,
285 kMaximumNewFamilyWaitMicroSeconds};
Wade Guthriefa2100e2013-05-15 10:11:22 -0700286 time_->GetTimeMonotonic(&start_time);
Wade Guthriebee87c22013-03-06 11:00:46 -0800287 now = start_time;
288 timeradd(&start_time, &maximum_wait_duration, &end_time);
289
290 do {
291 // Wait with timeout for a message from the netlink socket.
292 fd_set read_fds;
293 FD_ZERO(&read_fds);
294 FD_SET(file_descriptor(), &read_fds);
295 struct timeval wait_duration;
296 timersub(&end_time, &now, &wait_duration);
Wade Guthriefa2100e2013-05-15 10:11:22 -0700297 int result = sock_->sockets()->Select(file_descriptor() + 1,
298 &read_fds,
299 NULL,
300 NULL,
301 &wait_duration);
Wade Guthriebee87c22013-03-06 11:00:46 -0800302 if (result < 0) {
303 PLOG(ERROR) << "Select failed";
304 return NetlinkMessage::kIllegalMessageType;
305 }
306 if (result == 0) {
307 LOG(WARNING) << "Timed out waiting for family_id for family '"
308 << name << "'.";
309 return NetlinkMessage::kIllegalMessageType;
310 }
311
312 // Read and process any messages.
313 ByteString received;
314 sock_->RecvMessage(&received);
315 InputData input_data(received.GetData(), received.GetLength());
316 OnRawNlMessageReceived(&input_data);
317 if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
Wade Guthrie12f113a2013-03-12 17:15:46 -0700318 uint16_t family_id = message_type.family_id;
319 if (family_id != NetlinkMessage::kIllegalMessageType) {
320 message_factory_.AddFactoryMethod(family_id, message_factory);
321 }
Wade Guthriefa2100e2013-05-15 10:11:22 -0700322 time_->GetTimeMonotonic(&now);
Wade Guthriebee87c22013-03-06 11:00:46 -0800323 timersub(&now, &start_time, &wait_duration);
324 SLOG(WiFi, 5) << "Found id " << message_type.family_id
325 << " for name '" << name << "' in "
326 << wait_duration.tv_sec << " sec, "
327 << wait_duration.tv_usec << " usec.";
328 return message_type.family_id;
329 }
Wade Guthriefa2100e2013-05-15 10:11:22 -0700330 time_->GetTimeMonotonic(&now);
Wade Guthriebee87c22013-03-06 11:00:46 -0800331 } while (timercmp(&now, &end_time, <));
332
333 LOG(ERROR) << "Timed out waiting for family_id for family '" << name << "'.";
334 return NetlinkMessage::kIllegalMessageType;
Wade Guthrie0d438532012-05-18 14:18:50 -0700335}
336
Wade Guthriebb9fca22013-04-10 17:21:42 -0700337bool NetlinkManager::AddBroadcastHandler(const NetlinkMessageHandler &handler) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800338 list<NetlinkMessageHandler>::iterator i;
339 if (FindBroadcastHandler(handler)) {
340 LOG(WARNING) << "Trying to re-add a handler";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700341 return false; // Should only be one copy in the list.
342 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800343 if (handler.is_null()) {
344 LOG(WARNING) << "Trying to add a NULL handler";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700345 return false;
346 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800347 // And add the handler to the list.
Wade Guthriebb9fca22013-04-10 17:21:42 -0700348 SLOG(WiFi, 3) << "NetlinkManager::" << __func__ << " - adding handler";
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800349 broadcast_handlers_.push_back(handler);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700350 return true;
351}
352
Wade Guthriebb9fca22013-04-10 17:21:42 -0700353bool NetlinkManager::RemoveBroadcastHandler(
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800354 const NetlinkMessageHandler &handler) {
355 list<NetlinkMessageHandler>::iterator i;
356 for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
357 if ((*i).Equals(handler)) {
358 broadcast_handlers_.erase(i);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700359 // Should only be one copy in the list so we don't have to continue
360 // looking for another one.
361 return true;
362 }
363 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800364 LOG(WARNING) << "NetlinkMessageHandler not found.";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700365 return false;
366}
367
Wade Guthriebb9fca22013-04-10 17:21:42 -0700368bool NetlinkManager::FindBroadcastHandler(const NetlinkMessageHandler &handler)
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800369 const {
370 list<NetlinkMessageHandler>::const_iterator i;
371 for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
372 if ((*i).Equals(handler)) {
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700373 return true;
374 }
375 }
376 return false;
377}
378
Wade Guthriebb9fca22013-04-10 17:21:42 -0700379void NetlinkManager::ClearBroadcastHandlers() {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800380 broadcast_handlers_.clear();
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700381}
382
Wade Guthrie7347bf22013-04-30 11:21:51 -0700383bool NetlinkManager::SendControlMessage(
384 ControlNetlinkMessage *message,
385 const ControlNetlinkMessageHandler &message_handler,
386 const NetlinkAuxilliaryMessageHandler &error_handler) {
387 return SendMessageInternal(message,
388 new ControlResponseHandler(message_handler,
389 error_handler));
390}
391
392bool NetlinkManager::SendNl80211Message(
393 Nl80211Message *message,
394 const Nl80211MessageHandler &message_handler,
395 const NetlinkAuxilliaryMessageHandler &error_handler) {
396 return SendMessageInternal(message,
397 new Nl80211ResponseHandler(message_handler,
398 error_handler));
399}
400
401bool NetlinkManager::SendMessageInternal(
402 NetlinkMessage *message,
403 NetlinkManager::NetlinkResponseHandler *response_handler) {
Wade Guthrie5d53d492012-11-07 09:53:31 -0800404 if (!message) {
405 LOG(ERROR) << "Message is NULL.";
406 return false;
407 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800408
Wade Guthriebee87c22013-03-06 11:00:46 -0800409 ByteString message_string = message->Encode(this->GetSequenceNumber());
Wade Guthriecc53f232013-03-05 13:22:23 -0800410
Wade Guthrie7347bf22013-04-30 11:21:51 -0700411 if (!response_handler) {
Wade Guthriecc53f232013-03-05 13:22:23 -0800412 SLOG(WiFi, 3) << "Handler for message was null.";
413 } else if (ContainsKey(message_handlers_, message->sequence_number())) {
414 LOG(ERROR) << "A handler already existed for sequence: "
Wade Guthriebee87c22013-03-06 11:00:46 -0800415 << message->sequence_number();
416 return false;
Wade Guthriecc53f232013-03-05 13:22:23 -0800417 } else {
Wade Guthrie7347bf22013-04-30 11:21:51 -0700418 message_handlers_[message->sequence_number()] =
419 NetlinkResponseHandlerRefPtr(response_handler);
Wade Guthriecc53f232013-03-05 13:22:23 -0800420 }
Wade Guthrie8e278612013-02-26 10:32:34 -0800421
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700422 SLOG(WiFi, 5) << "NL Message " << message->sequence_number()
Wade Guthriecc53f232013-03-05 13:22:23 -0800423 << " Sending (" << message_string.GetLength()
424 << " bytes) ===>";
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700425 message->Print(6, 7);
426 NetlinkMessage::PrintBytes(8, message_string.GetConstData(),
Wade Guthriecc53f232013-03-05 13:22:23 -0800427 message_string.GetLength());
Wade Guthrie8e278612013-02-26 10:32:34 -0800428
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800429 if (!sock_->SendMessage(message_string)) {
Wade Guthrief48a1952013-03-04 17:33:47 -0800430 LOG(ERROR) << "Failed to send Netlink message.";
Wade Guthrie5d53d492012-11-07 09:53:31 -0800431 return false;
432 }
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700433 return true;
434}
435
Wade Guthriebb9fca22013-04-10 17:21:42 -0700436bool NetlinkManager::RemoveMessageHandler(const NetlinkMessage &message) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800437 if (!ContainsKey(message_handlers_, message.sequence_number())) {
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700438 return false;
439 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800440 message_handlers_.erase(message.sequence_number());
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700441 return true;
442}
443
Wade Guthriebb9fca22013-04-10 17:21:42 -0700444uint32_t NetlinkManager::GetSequenceNumber() {
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800445 return sock_ ?
Wade Guthrief48a1952013-03-04 17:33:47 -0800446 sock_->GetSequenceNumber() : NetlinkMessage::kBroadcastSequenceNumber;
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800447}
448
Wade Guthriebb9fca22013-04-10 17:21:42 -0700449bool NetlinkManager::SubscribeToEvents(const string &family_id,
450 const string &group_name) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800451 if (!ContainsKey(message_types_, family_id)) {
452 LOG(ERROR) << "Family '" << family_id << "' doesn't exist";
Wade Guthrie0d438532012-05-18 14:18:50 -0700453 return false;
454 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800455
456 if (!ContainsKey(message_types_[family_id].groups, group_name)) {
457 LOG(ERROR) << "Group '" << group_name << "' doesn't exist in family '"
458 << family_id << "'";
459 return false;
460 }
461
462 uint32_t group_id = message_types_[family_id].groups[group_name];
463 if (!sock_) {
464 LOG(FATAL) << "Need to call |Init| first.";
465 }
466 return sock_->SubscribeToEvents(group_id);
Wade Guthrie0d438532012-05-18 14:18:50 -0700467}
468
Wade Guthriebb9fca22013-04-10 17:21:42 -0700469void NetlinkManager::OnRawNlMessageReceived(InputData *data) {
repo syncbcaa6942013-01-02 15:38:21 -0800470 if (!data) {
471 LOG(ERROR) << __func__ << "() called with null header.";
472 return;
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700473 }
repo syncbcaa6942013-01-02 15:38:21 -0800474 unsigned char *buf = data->buf;
475 unsigned char *end = buf + data->len;
476 while (buf < end) {
477 nlmsghdr *msg = reinterpret_cast<nlmsghdr *>(buf);
478 // Discard the message if there're not enough bytes to a) tell the code how
479 // much space is in the message (i.e., to access nlmsg_len) or b) to hold
480 // the entire message. The odd calculation is there to keep the code from
481 // potentially calculating an illegal address (causes a segfault on some
482 // architectures).
483 size_t bytes_left = end - buf;
484 if (((bytes_left < (offsetof(nlmsghdr, nlmsg_len) +
Liam McLoughlinf4baef22012-08-01 19:08:25 -0700485 sizeof(msg->nlmsg_len))) ||
repo syncbcaa6942013-01-02 15:38:21 -0800486 (bytes_left < msg->nlmsg_len))) {
487 LOG(ERROR) << "Discarding incomplete message.";
488 return;
489 }
490 OnNlMessageReceived(msg);
491 buf += msg->nlmsg_len;
492 }
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700493}
Wade Guthrie0d438532012-05-18 14:18:50 -0700494
Wade Guthriebb9fca22013-04-10 17:21:42 -0700495void NetlinkManager::OnNlMessageReceived(nlmsghdr *msg) {
Christopher Wiley393b93f2012-11-08 17:30:58 -0800496 if (!msg) {
497 LOG(ERROR) << __func__ << "() called with null header.";
repo syncbcaa6942013-01-02 15:38:21 -0800498 return;
Christopher Wiley393b93f2012-11-08 17:30:58 -0800499 }
500 const uint32 sequence_number = msg->nlmsg_seq;
Wade Guthrie12f113a2013-03-12 17:15:46 -0700501 scoped_ptr<NetlinkMessage> message(message_factory_.CreateMessage(msg));
Wade Guthrie0d438532012-05-18 14:18:50 -0700502 if (message == NULL) {
Wade Guthrie8e278612013-02-26 10:32:34 -0800503 SLOG(WiFi, 3) << "NL Message " << sequence_number << " <===";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700504 SLOG(WiFi, 3) << __func__ << "(msg:NULL)";
repo syncbcaa6942013-01-02 15:38:21 -0800505 return; // Skip current message, continue parsing buffer.
Christopher Wiley393b93f2012-11-08 17:30:58 -0800506 }
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700507 SLOG(WiFi, 5) << "NL Message " << sequence_number
Wade Guthrie8e278612013-02-26 10:32:34 -0800508 << " Received (" << msg->nlmsg_len << " bytes) <===";
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700509 message->Print(6, 7);
Wade Guthrief48a1952013-03-04 17:33:47 -0800510 NetlinkMessage::PrintBytes(8, reinterpret_cast<const unsigned char *>(msg),
Wade Guthrie8e278612013-02-26 10:32:34 -0800511 msg->nlmsg_len);
512
Wade Guthrie7347bf22013-04-30 11:21:51 -0700513 if (message->message_type() == ErrorAckMessage::GetMessageType()) {
514 SLOG(WiFi, 3) << "Error response to message " << sequence_number;
515 const ErrorAckMessage *error_ack_message =
516 dynamic_cast<const ErrorAckMessage *>(message.get());
517 if (error_ack_message->error()) {
518 if (ContainsKey(message_handlers_, sequence_number)) {
519 SLOG(WiFi, 6) << "Found message-specific error handler";
520 message_handlers_[sequence_number]->HandleError(message.get());
Wade Guthriebee87c22013-03-06 11:00:46 -0800521 message_handlers_.erase(sequence_number);
Wade Guthriebee87c22013-03-06 11:00:46 -0800522 }
Wade Guthrie7347bf22013-04-30 11:21:51 -0700523 } else {
524 SLOG(WiFi, 3) << "ACK message -- not removing callback";
525 }
526 return;
527 }
528
529 if (ContainsKey(message_handlers_, sequence_number)) {
530 SLOG(WiFi, 6) << "Found message-specific handler";
531 if (!message_handlers_[sequence_number]->HandleMessage(*message)) {
532 LOG(ERROR) << "Couldn't call message handler for " << sequence_number;
533 // Call the error handler but, since we don't have an |ErrorAckMessage|,
534 // we'll have to pass a NULL pointer.
535 message_handlers_[sequence_number]->HandleError(NULL);
536 }
537 if ((message->flags() & NLM_F_MULTI) &&
Wade Guthriebee87c22013-03-06 11:00:46 -0800538 (message->message_type() != NLMSG_DONE)) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700539 SLOG(WiFi, 6) << "Multi-part message -- not removing callback";
Wade Guthriebee87c22013-03-06 11:00:46 -0800540 } else {
Wade Guthrie7347bf22013-04-30 11:21:51 -0700541 SLOG(WiFi, 6) << "Removing callbacks";
Wade Guthriebee87c22013-03-06 11:00:46 -0800542 message_handlers_.erase(sequence_number);
543 }
Wade Guthrie7347bf22013-04-30 11:21:51 -0700544 return;
545 }
546
547 for (const auto &handler : broadcast_handlers_) {
548 SLOG(WiFi, 6) << "Calling broadcast handler";
549 if (!handler.is_null()) {
550 handler.Run(*message);
Wade Guthrie0d438532012-05-18 14:18:50 -0700551 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700552 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700553}
554
Wade Guthriebb9fca22013-04-10 17:21:42 -0700555void NetlinkManager::OnReadError(const Error &error) {
556 // TODO(wdg): When netlink_manager is used for scan, et al., this should
557 // either be LOG(FATAL) or the code should properly deal with errors,
558 // e.g., dropped messages due to the socket buffer being full.
559 LOG(ERROR) << "NetlinkManager's netlink Socket read returns error: "
repo syncbcaa6942013-01-02 15:38:21 -0800560 << error.message();
561}
562
563
Wade Guthrie0d438532012-05-18 14:18:50 -0700564} // namespace shill.