blob: cef93e37c1f74df0d43c05b79d1aecce6464310a [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 Guthrie0d438532012-05-18 14:18:50 -070010#include <map>
Wade Guthrie0d438532012-05-18 14:18:50 -070011
12#include <base/memory/weak_ptr.h>
Wade Guthried6153612012-08-23 11:36:14 -070013#include <base/stl_util.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070014
Wade Guthriebee87c22013-03-06 11:00:46 -080015#include "shill/attribute_list.h"
repo syncbcaa6942013-01-02 15:38:21 -080016#include "shill/error.h"
Wade Guthrie89e6cb32013-03-07 08:03:45 -080017#include "shill/event_dispatcher.h"
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070018#include "shill/generic_netlink_message.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070019#include "shill/io_handler.h"
20#include "shill/logging.h"
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070021#include "shill/netlink_message.h"
Wade Guthrie92d06362013-04-25 15:41:30 -070022#include "shill/netlink_socket.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070023#include "shill/scope_logger.h"
Wade Guthriebee87c22013-03-06 11:00:46 -080024#include "shill/shill_time.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070025
26using base::Bind;
27using base::LazyInstance;
Wade Guthrieb1ec8602012-10-18 17:26:14 -070028using std::list;
Wade Guthriec6c81962013-03-06 15:47:13 -080029using std::map;
Wade Guthrie0d438532012-05-18 14:18:50 -070030using std::string;
31
32namespace shill {
33
34namespace {
Wade Guthriebb9fca22013-04-10 17:21:42 -070035LazyInstance<NetlinkManager> g_netlink_manager = LAZY_INSTANCE_INITIALIZER;
Wade Guthrie0d438532012-05-18 14:18:50 -070036} // namespace
37
Wade Guthriebb9fca22013-04-10 17:21:42 -070038const char NetlinkManager::kEventTypeConfig[] = "config";
39const char NetlinkManager::kEventTypeScan[] = "scan";
40const char NetlinkManager::kEventTypeRegulatory[] = "regulatory";
41const char NetlinkManager::kEventTypeMlme[] = "mlme";
42const long NetlinkManager::kMaximumNewFamilyWaitSeconds = 1;
43const long NetlinkManager::kMaximumNewFamilyWaitMicroSeconds = 0;
Wade Guthriebee87c22013-03-06 11:00:46 -080044
Wade Guthriebb9fca22013-04-10 17:21:42 -070045NetlinkManager::MessageType::MessageType() :
Wade Guthriebee87c22013-03-06 11:00:46 -080046 family_id(NetlinkMessage::kIllegalMessageType) {}
Wade Guthrie0d438532012-05-18 14:18:50 -070047
Wade Guthriebb9fca22013-04-10 17:21:42 -070048NetlinkManager::NetlinkManager()
Wade Guthriebee87c22013-03-06 11:00:46 -080049 : dispatcher_(NULL),
Wade Guthrie0d438532012-05-18 14:18:50 -070050 weak_ptr_factory_(this),
Wade Guthriebb9fca22013-04-10 17:21:42 -070051 dispatcher_callback_(Bind(&NetlinkManager::OnRawNlMessageReceived,
repo syncbcaa6942013-01-02 15:38:21 -080052 weak_ptr_factory_.GetWeakPtr())),
Wade Guthriebee87c22013-03-06 11:00:46 -080053 sock_(NULL) {}
Wade Guthrie0d438532012-05-18 14:18:50 -070054
Wade Guthriebb9fca22013-04-10 17:21:42 -070055NetlinkManager *NetlinkManager::GetInstance() {
56 return g_netlink_manager.Pointer();
Wade Guthrie0d438532012-05-18 14:18:50 -070057}
58
Wade Guthriebb9fca22013-04-10 17:21:42 -070059void NetlinkManager::Reset(bool full) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -080060 ClearBroadcastHandlers();
Wade Guthriebee87c22013-03-06 11:00:46 -080061 message_types_.clear();
Darin Petkovd5818382013-01-28 16:27:07 +010062 if (full) {
63 dispatcher_ = NULL;
64 delete sock_;
65 sock_ = NULL;
66 }
Wade Guthried6153612012-08-23 11:36:14 -070067}
68
Wade Guthriebb9fca22013-04-10 17:21:42 -070069void NetlinkManager::OnNewFamilyMessage(const NetlinkMessage &raw_message) {
Wade Guthriebee87c22013-03-06 11:00:46 -080070 uint16_t family_id;
71 string family_name;
72
73 if (raw_message.message_type() == ErrorAckMessage::kMessageType) {
74 const ErrorAckMessage *error_ack_message =
75 reinterpret_cast<const ErrorAckMessage *>(&raw_message);
76 if (error_ack_message->error()) {
77 LOG(ERROR) << __func__ << ": Message (seq: "
78 << raw_message.sequence_number() << ") failed: "
79 << error_ack_message->ToString();
80 } else {
81 SLOG(WiFi, 6) << __func__ << ": Message (seq: "
82 << raw_message.sequence_number() << ") ACKed";
83 }
84 return;
85 }
86
87 if (raw_message.message_type() != ControlNetlinkMessage::kMessageType) {
88 LOG(ERROR) << "Received unexpected message type: "
89 << raw_message.message_type();
90 return;
91 }
92
93 const ControlNetlinkMessage *message =
94 reinterpret_cast<const ControlNetlinkMessage *>(&raw_message);
95
96 if (!message->const_attributes()->GetU16AttributeValue(CTRL_ATTR_FAMILY_ID,
97 &family_id)) {
98 LOG(ERROR) << __func__ << ": Couldn't get family_id attribute";
99 return;
100 }
101
102 if (!message->const_attributes()->GetStringAttributeValue(
103 CTRL_ATTR_FAMILY_NAME, &family_name)) {
104 LOG(ERROR) << __func__ << ": Couldn't get family_name attribute";
105 return;
106 }
107
108 SLOG(WiFi, 3) << "Socket family '" << family_name << "' has id=" << family_id;
109
110 // Extract the available multicast groups from the message.
111 AttributeListConstRefPtr multicast_groups;
112 if (message->const_attributes()->ConstGetNestedAttributeList(
113 CTRL_ATTR_MCAST_GROUPS, &multicast_groups)) {
114 AttributeListConstRefPtr current_group;
115
116 for (int i = 1;
117 multicast_groups->ConstGetNestedAttributeList(i, &current_group);
118 ++i) {
119 string group_name;
120 uint32_t group_id;
121 if (!current_group->GetStringAttributeValue(CTRL_ATTR_MCAST_GRP_NAME,
122 &group_name)) {
123 LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_NAME, found none";
124 continue;
125 }
126 if (!current_group->GetU32AttributeValue(CTRL_ATTR_MCAST_GRP_ID,
127 &group_id)) {
128 LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_ID, found none";
129 continue;
130 }
131 SLOG(WiFi, 3) << " Adding group '" << group_name << "' = " << group_id;
132 message_types_[family_name].groups[group_name] = group_id;
133 }
134 }
135
136 message_types_[family_name].family_id = family_id;
137}
138
Wade Guthriebb9fca22013-04-10 17:21:42 -0700139bool NetlinkManager::Init() {
Wade Guthrie12f113a2013-03-12 17:15:46 -0700140 // Install message factory for control class of messages, which has
141 // statically-known message type.
142 message_factory_.AddFactoryMethod(
143 ControlNetlinkMessage::kMessageType,
144 Bind(&ControlNetlinkMessage::CreateMessage));
Wade Guthrie0d438532012-05-18 14:18:50 -0700145 if (!sock_) {
Wade Guthriecc53f232013-03-05 13:22:23 -0800146 sock_ = new NetlinkSocket;
Wade Guthrie0d438532012-05-18 14:18:50 -0700147 if (!sock_) {
148 LOG(ERROR) << "No memory";
149 return false;
150 }
151
152 if (!sock_->Init()) {
153 return false;
154 }
155 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800156 return true;
157}
Wade Guthrie0d438532012-05-18 14:18:50 -0700158
Wade Guthriebb9fca22013-04-10 17:21:42 -0700159void NetlinkManager::Start(EventDispatcher *dispatcher) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800160 dispatcher_ = dispatcher;
161 CHECK(dispatcher_);
162 // Install ourselves in the shill mainloop so we receive messages on the
163 // netlink socket.
164 dispatcher_handler_.reset(dispatcher_->CreateInputHandler(
165 file_descriptor(),
166 dispatcher_callback_,
Wade Guthriebb9fca22013-04-10 17:21:42 -0700167 Bind(&NetlinkManager::OnReadError, weak_ptr_factory_.GetWeakPtr())));
Wade Guthriebee87c22013-03-06 11:00:46 -0800168}
169
Wade Guthriebb9fca22013-04-10 17:21:42 -0700170int NetlinkManager::file_descriptor() const {
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800171 return (sock_ ? sock_->file_descriptor() : -1);
172}
173
Wade Guthriebb9fca22013-04-10 17:21:42 -0700174uint16_t NetlinkManager::GetFamily(string name,
Wade Guthrie12f113a2013-03-12 17:15:46 -0700175 const NetlinkMessageFactory::FactoryMethod &message_factory) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800176 MessageType &message_type = message_types_[name];
177 if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
178 return message_type.family_id;
179 }
180 if (!sock_) {
181 LOG(FATAL) << "Must call |Init| before this method.";
182 return false;
Wade Guthrie0d438532012-05-18 14:18:50 -0700183 }
184
Wade Guthriebee87c22013-03-06 11:00:46 -0800185 GetFamilyMessage msg;
186 if (!msg.attributes()->CreateStringAttribute(CTRL_ATTR_FAMILY_NAME,
187 "CTRL_ATTR_FAMILY_NAME")) {
188 LOG(ERROR) << "Couldn't create string attribute";
189 return false;
190 }
191 if (!msg.attributes()->SetStringAttributeValue(CTRL_ATTR_FAMILY_NAME, name)) {
192 LOG(ERROR) << "Couldn't set string attribute";
193 return false;
194 }
Wade Guthriebb9fca22013-04-10 17:21:42 -0700195 SendMessage(&msg, Bind(&NetlinkManager::OnNewFamilyMessage,
Wade Guthriebee87c22013-03-06 11:00:46 -0800196 weak_ptr_factory_.GetWeakPtr()));
197
198 // Wait for a response. The code absolutely needs family_ids for its
199 // message types so we do a synchronous wait. It's OK to do this because
200 // a) libnl does a synchronous wait (so there's prior art), b) waiting
201 // asynchronously would add significant and unnecessary complexity to the
202 // code that deals with pending messages that could, potentially, be waiting
203 // for a message type, and c) it really doesn't take very long for the
204 // GETFAMILY / NEWFAMILY transaction to transpire (this transaction was timed
205 // over 20 times and found a maximum duration of 11.1 microseconds and an
206 // average of 4.0 microseconds).
207 struct timeval start_time, now, end_time;
208 struct timeval maximum_wait_duration = {kMaximumNewFamilyWaitSeconds,
209 kMaximumNewFamilyWaitMicroSeconds};
210 Time *time = Time::GetInstance();
211 time->GetTimeMonotonic(&start_time);
212 now = start_time;
213 timeradd(&start_time, &maximum_wait_duration, &end_time);
214
215 do {
216 // Wait with timeout for a message from the netlink socket.
217 fd_set read_fds;
218 FD_ZERO(&read_fds);
219 FD_SET(file_descriptor(), &read_fds);
220 struct timeval wait_duration;
221 timersub(&end_time, &now, &wait_duration);
222 int result = select(file_descriptor() + 1, &read_fds, NULL, NULL,
223 &wait_duration);
224 if (result < 0) {
225 PLOG(ERROR) << "Select failed";
226 return NetlinkMessage::kIllegalMessageType;
227 }
228 if (result == 0) {
229 LOG(WARNING) << "Timed out waiting for family_id for family '"
230 << name << "'.";
231 return NetlinkMessage::kIllegalMessageType;
232 }
233
234 // Read and process any messages.
235 ByteString received;
236 sock_->RecvMessage(&received);
237 InputData input_data(received.GetData(), received.GetLength());
238 OnRawNlMessageReceived(&input_data);
239 if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
Wade Guthrie12f113a2013-03-12 17:15:46 -0700240 uint16_t family_id = message_type.family_id;
241 if (family_id != NetlinkMessage::kIllegalMessageType) {
242 message_factory_.AddFactoryMethod(family_id, message_factory);
243 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800244 time->GetTimeMonotonic(&now);
245 timersub(&now, &start_time, &wait_duration);
246 SLOG(WiFi, 5) << "Found id " << message_type.family_id
247 << " for name '" << name << "' in "
248 << wait_duration.tv_sec << " sec, "
249 << wait_duration.tv_usec << " usec.";
250 return message_type.family_id;
251 }
252 time->GetTimeMonotonic(&now);
253 } while (timercmp(&now, &end_time, <));
254
255 LOG(ERROR) << "Timed out waiting for family_id for family '" << name << "'.";
256 return NetlinkMessage::kIllegalMessageType;
Wade Guthrie0d438532012-05-18 14:18:50 -0700257}
258
Wade Guthriebb9fca22013-04-10 17:21:42 -0700259uint16_t NetlinkManager::GetMessageType(string name) const {
Wade Guthriec6c81962013-03-06 15:47:13 -0800260 map<const string, MessageType>::const_iterator family =
261 message_types_.find(name);
262 if (family == message_types_.end()) {
263 LOG(WARNING) << "Family '" << name << "' is not in list.";
264 return NetlinkMessage::kIllegalMessageType;
265 }
266 return family->second.family_id;
267}
268
Wade Guthriebb9fca22013-04-10 17:21:42 -0700269bool NetlinkManager::AddBroadcastHandler(const NetlinkMessageHandler &handler) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800270 list<NetlinkMessageHandler>::iterator i;
271 if (FindBroadcastHandler(handler)) {
272 LOG(WARNING) << "Trying to re-add a handler";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700273 return false; // Should only be one copy in the list.
274 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800275 if (handler.is_null()) {
276 LOG(WARNING) << "Trying to add a NULL handler";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700277 return false;
278 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800279 // And add the handler to the list.
Wade Guthriebb9fca22013-04-10 17:21:42 -0700280 SLOG(WiFi, 3) << "NetlinkManager::" << __func__ << " - adding handler";
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800281 broadcast_handlers_.push_back(handler);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700282 return true;
283}
284
Wade Guthriebb9fca22013-04-10 17:21:42 -0700285bool NetlinkManager::RemoveBroadcastHandler(
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800286 const NetlinkMessageHandler &handler) {
287 list<NetlinkMessageHandler>::iterator i;
288 for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
289 if ((*i).Equals(handler)) {
290 broadcast_handlers_.erase(i);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700291 // Should only be one copy in the list so we don't have to continue
292 // looking for another one.
293 return true;
294 }
295 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800296 LOG(WARNING) << "NetlinkMessageHandler not found.";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700297 return false;
298}
299
Wade Guthriebb9fca22013-04-10 17:21:42 -0700300bool NetlinkManager::FindBroadcastHandler(const NetlinkMessageHandler &handler)
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800301 const {
302 list<NetlinkMessageHandler>::const_iterator i;
303 for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
304 if ((*i).Equals(handler)) {
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700305 return true;
306 }
307 }
308 return false;
309}
310
Wade Guthriebb9fca22013-04-10 17:21:42 -0700311void NetlinkManager::ClearBroadcastHandlers() {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800312 broadcast_handlers_.clear();
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700313}
314
Wade Guthriebb9fca22013-04-10 17:21:42 -0700315bool NetlinkManager::SendMessage(NetlinkMessage *message,
Wade Guthrie92d06362013-04-25 15:41:30 -0700316 const NetlinkMessageHandler &handler) {
Wade Guthrie5d53d492012-11-07 09:53:31 -0800317 if (!message) {
318 LOG(ERROR) << "Message is NULL.";
319 return false;
320 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800321
Wade Guthriebee87c22013-03-06 11:00:46 -0800322 ByteString message_string = message->Encode(this->GetSequenceNumber());
Wade Guthriecc53f232013-03-05 13:22:23 -0800323
324 if (handler.is_null()) {
325 SLOG(WiFi, 3) << "Handler for message was null.";
326 } else if (ContainsKey(message_handlers_, message->sequence_number())) {
327 LOG(ERROR) << "A handler already existed for sequence: "
Wade Guthriebee87c22013-03-06 11:00:46 -0800328 << message->sequence_number();
329 return false;
Wade Guthriecc53f232013-03-05 13:22:23 -0800330 } else {
331 message_handlers_[message->sequence_number()] = handler;
332 }
Wade Guthrie8e278612013-02-26 10:32:34 -0800333
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700334 SLOG(WiFi, 5) << "NL Message " << message->sequence_number()
Wade Guthriecc53f232013-03-05 13:22:23 -0800335 << " Sending (" << message_string.GetLength()
336 << " bytes) ===>";
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700337 message->Print(6, 7);
338 NetlinkMessage::PrintBytes(8, message_string.GetConstData(),
Wade Guthriecc53f232013-03-05 13:22:23 -0800339 message_string.GetLength());
Wade Guthrie8e278612013-02-26 10:32:34 -0800340
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800341 if (!sock_->SendMessage(message_string)) {
Wade Guthrief48a1952013-03-04 17:33:47 -0800342 LOG(ERROR) << "Failed to send Netlink message.";
Wade Guthrie5d53d492012-11-07 09:53:31 -0800343 return false;
344 }
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700345 return true;
346}
347
Wade Guthriebb9fca22013-04-10 17:21:42 -0700348bool NetlinkManager::RemoveMessageHandler(const NetlinkMessage &message) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800349 if (!ContainsKey(message_handlers_, message.sequence_number())) {
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700350 return false;
351 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800352 message_handlers_.erase(message.sequence_number());
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700353 return true;
354}
355
Wade Guthriebb9fca22013-04-10 17:21:42 -0700356uint32_t NetlinkManager::GetSequenceNumber() {
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800357 return sock_ ?
Wade Guthrief48a1952013-03-04 17:33:47 -0800358 sock_->GetSequenceNumber() : NetlinkMessage::kBroadcastSequenceNumber;
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800359}
360
Wade Guthriebb9fca22013-04-10 17:21:42 -0700361bool NetlinkManager::SubscribeToEvents(const string &family_id,
362 const string &group_name) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800363 if (!ContainsKey(message_types_, family_id)) {
364 LOG(ERROR) << "Family '" << family_id << "' doesn't exist";
Wade Guthrie0d438532012-05-18 14:18:50 -0700365 return false;
366 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800367
368 if (!ContainsKey(message_types_[family_id].groups, group_name)) {
369 LOG(ERROR) << "Group '" << group_name << "' doesn't exist in family '"
370 << family_id << "'";
371 return false;
372 }
373
374 uint32_t group_id = message_types_[family_id].groups[group_name];
375 if (!sock_) {
376 LOG(FATAL) << "Need to call |Init| first.";
377 }
378 return sock_->SubscribeToEvents(group_id);
Wade Guthrie0d438532012-05-18 14:18:50 -0700379}
380
Wade Guthriebb9fca22013-04-10 17:21:42 -0700381void NetlinkManager::OnRawNlMessageReceived(InputData *data) {
repo syncbcaa6942013-01-02 15:38:21 -0800382 if (!data) {
383 LOG(ERROR) << __func__ << "() called with null header.";
384 return;
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700385 }
repo syncbcaa6942013-01-02 15:38:21 -0800386 unsigned char *buf = data->buf;
387 unsigned char *end = buf + data->len;
388 while (buf < end) {
389 nlmsghdr *msg = reinterpret_cast<nlmsghdr *>(buf);
390 // Discard the message if there're not enough bytes to a) tell the code how
391 // much space is in the message (i.e., to access nlmsg_len) or b) to hold
392 // the entire message. The odd calculation is there to keep the code from
393 // potentially calculating an illegal address (causes a segfault on some
394 // architectures).
395 size_t bytes_left = end - buf;
396 if (((bytes_left < (offsetof(nlmsghdr, nlmsg_len) +
Liam McLoughlinf4baef22012-08-01 19:08:25 -0700397 sizeof(msg->nlmsg_len))) ||
repo syncbcaa6942013-01-02 15:38:21 -0800398 (bytes_left < msg->nlmsg_len))) {
399 LOG(ERROR) << "Discarding incomplete message.";
400 return;
401 }
402 OnNlMessageReceived(msg);
403 buf += msg->nlmsg_len;
404 }
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700405}
Wade Guthrie0d438532012-05-18 14:18:50 -0700406
Wade Guthriebb9fca22013-04-10 17:21:42 -0700407void NetlinkManager::OnNlMessageReceived(nlmsghdr *msg) {
Christopher Wiley393b93f2012-11-08 17:30:58 -0800408 if (!msg) {
409 LOG(ERROR) << __func__ << "() called with null header.";
repo syncbcaa6942013-01-02 15:38:21 -0800410 return;
Christopher Wiley393b93f2012-11-08 17:30:58 -0800411 }
412 const uint32 sequence_number = msg->nlmsg_seq;
Wade Guthrie12f113a2013-03-12 17:15:46 -0700413 scoped_ptr<NetlinkMessage> message(message_factory_.CreateMessage(msg));
Wade Guthrie0d438532012-05-18 14:18:50 -0700414 if (message == NULL) {
Wade Guthrie8e278612013-02-26 10:32:34 -0800415 SLOG(WiFi, 3) << "NL Message " << sequence_number << " <===";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700416 SLOG(WiFi, 3) << __func__ << "(msg:NULL)";
repo syncbcaa6942013-01-02 15:38:21 -0800417 return; // Skip current message, continue parsing buffer.
Christopher Wiley393b93f2012-11-08 17:30:58 -0800418 }
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700419 SLOG(WiFi, 5) << "NL Message " << sequence_number
Wade Guthrie8e278612013-02-26 10:32:34 -0800420 << " Received (" << msg->nlmsg_len << " bytes) <===";
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700421 message->Print(6, 7);
Wade Guthrief48a1952013-03-04 17:33:47 -0800422 NetlinkMessage::PrintBytes(8, reinterpret_cast<const unsigned char *>(msg),
Wade Guthrie8e278612013-02-26 10:32:34 -0800423 msg->nlmsg_len);
424
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800425 // Call (then erase) any message-specific handler.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800426 if (ContainsKey(message_handlers_, sequence_number)) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700427 SLOG(WiFi, 6) << "found message-specific handler";
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800428 if (message_handlers_[sequence_number].is_null()) {
429 LOG(ERROR) << "NetlinkMessageHandler exists but is NULL for ID "
430 << sequence_number;
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700431 } else {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800432 message_handlers_[sequence_number].Run(*message);
Christopher Wiley393b93f2012-11-08 17:30:58 -0800433 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800434
435 if (message->message_type() == ErrorAckMessage::kMessageType) {
436 const ErrorAckMessage *error_ack_message =
437 reinterpret_cast<const ErrorAckMessage *>(message.get());
438 if (error_ack_message->error()) {
439 SLOG(WiFi, 3) << "Removing callback";
440 message_handlers_.erase(sequence_number);
441 } else {
442 SLOG(WiFi, 3) << "ACK message -- not removing callback";
443 }
444 } else if ((message->flags() & NLM_F_MULTI) &&
445 (message->message_type() != NLMSG_DONE)) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700446 SLOG(WiFi, 6) << "Multi-part message -- not removing callback";
Wade Guthriebee87c22013-03-06 11:00:46 -0800447 } else {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700448 SLOG(WiFi, 6) << "Removing callback";
Wade Guthriebee87c22013-03-06 11:00:46 -0800449 message_handlers_.erase(sequence_number);
450 }
Christopher Wiley393b93f2012-11-08 17:30:58 -0800451 } else {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800452 list<NetlinkMessageHandler>::const_iterator i =
453 broadcast_handlers_.begin();
454 while (i != broadcast_handlers_.end()) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700455 SLOG(WiFi, 6) << __func__ << " - calling broadcast handler";
repo syncbcaa6942013-01-02 15:38:21 -0800456 i->Run(*message);
457 ++i;
Wade Guthrie0d438532012-05-18 14:18:50 -0700458 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700459 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700460}
461
Wade Guthriebb9fca22013-04-10 17:21:42 -0700462void NetlinkManager::OnReadError(const Error &error) {
463 // TODO(wdg): When netlink_manager is used for scan, et al., this should
464 // either be LOG(FATAL) or the code should properly deal with errors,
465 // e.g., dropped messages due to the socket buffer being full.
466 LOG(ERROR) << "NetlinkManager's netlink Socket read returns error: "
repo syncbcaa6942013-01-02 15:38:21 -0800467 << error.message();
468}
469
470
Wade Guthrie0d438532012-05-18 14:18:50 -0700471} // namespace shill.