blob: 01726112b6279e3d4a088aa53e14b85e5849c331 [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 Guthriefa2100e2013-05-15 10:11:22 -070025#include "shill/sockets.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070026
27using base::Bind;
28using base::LazyInstance;
Wade Guthrieb1ec8602012-10-18 17:26:14 -070029using std::list;
Wade Guthriec6c81962013-03-06 15:47:13 -080030using std::map;
Wade Guthrie0d438532012-05-18 14:18:50 -070031using std::string;
32
33namespace shill {
34
35namespace {
Wade Guthriebb9fca22013-04-10 17:21:42 -070036LazyInstance<NetlinkManager> g_netlink_manager = LAZY_INSTANCE_INITIALIZER;
Wade Guthrie0d438532012-05-18 14:18:50 -070037} // namespace
38
Wade Guthriebb9fca22013-04-10 17:21:42 -070039const char NetlinkManager::kEventTypeConfig[] = "config";
40const char NetlinkManager::kEventTypeScan[] = "scan";
41const char NetlinkManager::kEventTypeRegulatory[] = "regulatory";
42const char NetlinkManager::kEventTypeMlme[] = "mlme";
43const long NetlinkManager::kMaximumNewFamilyWaitSeconds = 1;
44const long NetlinkManager::kMaximumNewFamilyWaitMicroSeconds = 0;
Wade Guthriebee87c22013-03-06 11:00:46 -080045
Wade Guthriebb9fca22013-04-10 17:21:42 -070046NetlinkManager::MessageType::MessageType() :
Wade Guthriebee87c22013-03-06 11:00:46 -080047 family_id(NetlinkMessage::kIllegalMessageType) {}
Wade Guthrie0d438532012-05-18 14:18:50 -070048
Wade Guthriebb9fca22013-04-10 17:21:42 -070049NetlinkManager::NetlinkManager()
Wade Guthriebee87c22013-03-06 11:00:46 -080050 : dispatcher_(NULL),
Wade Guthrie0d438532012-05-18 14:18:50 -070051 weak_ptr_factory_(this),
Wade Guthriebb9fca22013-04-10 17:21:42 -070052 dispatcher_callback_(Bind(&NetlinkManager::OnRawNlMessageReceived,
repo syncbcaa6942013-01-02 15:38:21 -080053 weak_ptr_factory_.GetWeakPtr())),
Wade Guthriefa2100e2013-05-15 10:11:22 -070054 sock_(NULL),
55 time_(Time::GetInstance()) {}
Wade Guthrie0d438532012-05-18 14:18:50 -070056
Wade Guthriebb9fca22013-04-10 17:21:42 -070057NetlinkManager *NetlinkManager::GetInstance() {
58 return g_netlink_manager.Pointer();
Wade Guthrie0d438532012-05-18 14:18:50 -070059}
60
Wade Guthriebb9fca22013-04-10 17:21:42 -070061void NetlinkManager::Reset(bool full) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -080062 ClearBroadcastHandlers();
Wade Guthriefa2100e2013-05-15 10:11:22 -070063 message_handlers_.clear();
Wade Guthriebee87c22013-03-06 11:00:46 -080064 message_types_.clear();
Darin Petkovd5818382013-01-28 16:27:07 +010065 if (full) {
66 dispatcher_ = NULL;
67 delete sock_;
68 sock_ = NULL;
69 }
Wade Guthried6153612012-08-23 11:36:14 -070070}
71
Wade Guthriebb9fca22013-04-10 17:21:42 -070072void NetlinkManager::OnNewFamilyMessage(const NetlinkMessage &raw_message) {
Wade Guthriebee87c22013-03-06 11:00:46 -080073 uint16_t family_id;
74 string family_name;
75
76 if (raw_message.message_type() == ErrorAckMessage::kMessageType) {
77 const ErrorAckMessage *error_ack_message =
78 reinterpret_cast<const ErrorAckMessage *>(&raw_message);
79 if (error_ack_message->error()) {
80 LOG(ERROR) << __func__ << ": Message (seq: "
81 << raw_message.sequence_number() << ") failed: "
82 << error_ack_message->ToString();
83 } else {
84 SLOG(WiFi, 6) << __func__ << ": Message (seq: "
85 << raw_message.sequence_number() << ") ACKed";
86 }
87 return;
88 }
89
90 if (raw_message.message_type() != ControlNetlinkMessage::kMessageType) {
91 LOG(ERROR) << "Received unexpected message type: "
92 << raw_message.message_type();
93 return;
94 }
95
96 const ControlNetlinkMessage *message =
97 reinterpret_cast<const ControlNetlinkMessage *>(&raw_message);
98
99 if (!message->const_attributes()->GetU16AttributeValue(CTRL_ATTR_FAMILY_ID,
100 &family_id)) {
101 LOG(ERROR) << __func__ << ": Couldn't get family_id attribute";
102 return;
103 }
104
105 if (!message->const_attributes()->GetStringAttributeValue(
106 CTRL_ATTR_FAMILY_NAME, &family_name)) {
107 LOG(ERROR) << __func__ << ": Couldn't get family_name attribute";
108 return;
109 }
110
111 SLOG(WiFi, 3) << "Socket family '" << family_name << "' has id=" << family_id;
112
113 // Extract the available multicast groups from the message.
114 AttributeListConstRefPtr multicast_groups;
115 if (message->const_attributes()->ConstGetNestedAttributeList(
116 CTRL_ATTR_MCAST_GROUPS, &multicast_groups)) {
117 AttributeListConstRefPtr current_group;
118
119 for (int i = 1;
120 multicast_groups->ConstGetNestedAttributeList(i, &current_group);
121 ++i) {
122 string group_name;
123 uint32_t group_id;
124 if (!current_group->GetStringAttributeValue(CTRL_ATTR_MCAST_GRP_NAME,
125 &group_name)) {
126 LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_NAME, found none";
127 continue;
128 }
129 if (!current_group->GetU32AttributeValue(CTRL_ATTR_MCAST_GRP_ID,
130 &group_id)) {
131 LOG(WARNING) << "Expected CTRL_ATTR_MCAST_GRP_ID, found none";
132 continue;
133 }
134 SLOG(WiFi, 3) << " Adding group '" << group_name << "' = " << group_id;
135 message_types_[family_name].groups[group_name] = group_id;
136 }
137 }
138
139 message_types_[family_name].family_id = family_id;
140}
141
Wade Guthriebb9fca22013-04-10 17:21:42 -0700142bool NetlinkManager::Init() {
Wade Guthrie12f113a2013-03-12 17:15:46 -0700143 // Install message factory for control class of messages, which has
144 // statically-known message type.
145 message_factory_.AddFactoryMethod(
146 ControlNetlinkMessage::kMessageType,
147 Bind(&ControlNetlinkMessage::CreateMessage));
Wade Guthrie0d438532012-05-18 14:18:50 -0700148 if (!sock_) {
Wade Guthriecc53f232013-03-05 13:22:23 -0800149 sock_ = new NetlinkSocket;
Wade Guthrie0d438532012-05-18 14:18:50 -0700150 if (!sock_) {
151 LOG(ERROR) << "No memory";
152 return false;
153 }
154
155 if (!sock_->Init()) {
156 return false;
157 }
158 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800159 return true;
160}
Wade Guthrie0d438532012-05-18 14:18:50 -0700161
Wade Guthriebb9fca22013-04-10 17:21:42 -0700162void NetlinkManager::Start(EventDispatcher *dispatcher) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800163 dispatcher_ = dispatcher;
164 CHECK(dispatcher_);
165 // Install ourselves in the shill mainloop so we receive messages on the
166 // netlink socket.
167 dispatcher_handler_.reset(dispatcher_->CreateInputHandler(
168 file_descriptor(),
169 dispatcher_callback_,
Wade Guthriebb9fca22013-04-10 17:21:42 -0700170 Bind(&NetlinkManager::OnReadError, weak_ptr_factory_.GetWeakPtr())));
Wade Guthriebee87c22013-03-06 11:00:46 -0800171}
172
Wade Guthriebb9fca22013-04-10 17:21:42 -0700173int NetlinkManager::file_descriptor() const {
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800174 return (sock_ ? sock_->file_descriptor() : -1);
175}
176
Wade Guthriefa2100e2013-05-15 10:11:22 -0700177uint16_t NetlinkManager::GetFamily(const string &name,
Wade Guthrie12f113a2013-03-12 17:15:46 -0700178 const NetlinkMessageFactory::FactoryMethod &message_factory) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800179 MessageType &message_type = message_types_[name];
180 if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
181 return message_type.family_id;
182 }
183 if (!sock_) {
184 LOG(FATAL) << "Must call |Init| before this method.";
185 return false;
Wade Guthrie0d438532012-05-18 14:18:50 -0700186 }
187
Wade Guthriebee87c22013-03-06 11:00:46 -0800188 GetFamilyMessage msg;
189 if (!msg.attributes()->CreateStringAttribute(CTRL_ATTR_FAMILY_NAME,
190 "CTRL_ATTR_FAMILY_NAME")) {
191 LOG(ERROR) << "Couldn't create string attribute";
192 return false;
193 }
194 if (!msg.attributes()->SetStringAttributeValue(CTRL_ATTR_FAMILY_NAME, name)) {
195 LOG(ERROR) << "Couldn't set string attribute";
196 return false;
197 }
Wade Guthriebb9fca22013-04-10 17:21:42 -0700198 SendMessage(&msg, Bind(&NetlinkManager::OnNewFamilyMessage,
Wade Guthriebee87c22013-03-06 11:00:46 -0800199 weak_ptr_factory_.GetWeakPtr()));
200
201 // Wait for a response. The code absolutely needs family_ids for its
202 // message types so we do a synchronous wait. It's OK to do this because
203 // a) libnl does a synchronous wait (so there's prior art), b) waiting
204 // asynchronously would add significant and unnecessary complexity to the
205 // code that deals with pending messages that could, potentially, be waiting
206 // for a message type, and c) it really doesn't take very long for the
207 // GETFAMILY / NEWFAMILY transaction to transpire (this transaction was timed
208 // over 20 times and found a maximum duration of 11.1 microseconds and an
209 // average of 4.0 microseconds).
210 struct timeval start_time, now, end_time;
211 struct timeval maximum_wait_duration = {kMaximumNewFamilyWaitSeconds,
212 kMaximumNewFamilyWaitMicroSeconds};
Wade Guthriefa2100e2013-05-15 10:11:22 -0700213 time_->GetTimeMonotonic(&start_time);
Wade Guthriebee87c22013-03-06 11:00:46 -0800214 now = start_time;
215 timeradd(&start_time, &maximum_wait_duration, &end_time);
216
217 do {
218 // Wait with timeout for a message from the netlink socket.
219 fd_set read_fds;
220 FD_ZERO(&read_fds);
221 FD_SET(file_descriptor(), &read_fds);
222 struct timeval wait_duration;
223 timersub(&end_time, &now, &wait_duration);
Wade Guthriefa2100e2013-05-15 10:11:22 -0700224 int result = sock_->sockets()->Select(file_descriptor() + 1,
225 &read_fds,
226 NULL,
227 NULL,
228 &wait_duration);
Wade Guthriebee87c22013-03-06 11:00:46 -0800229 if (result < 0) {
230 PLOG(ERROR) << "Select failed";
231 return NetlinkMessage::kIllegalMessageType;
232 }
233 if (result == 0) {
234 LOG(WARNING) << "Timed out waiting for family_id for family '"
235 << name << "'.";
236 return NetlinkMessage::kIllegalMessageType;
237 }
238
239 // Read and process any messages.
240 ByteString received;
241 sock_->RecvMessage(&received);
242 InputData input_data(received.GetData(), received.GetLength());
243 OnRawNlMessageReceived(&input_data);
244 if (message_type.family_id != NetlinkMessage::kIllegalMessageType) {
Wade Guthrie12f113a2013-03-12 17:15:46 -0700245 uint16_t family_id = message_type.family_id;
246 if (family_id != NetlinkMessage::kIllegalMessageType) {
247 message_factory_.AddFactoryMethod(family_id, message_factory);
248 }
Wade Guthriefa2100e2013-05-15 10:11:22 -0700249 time_->GetTimeMonotonic(&now);
Wade Guthriebee87c22013-03-06 11:00:46 -0800250 timersub(&now, &start_time, &wait_duration);
251 SLOG(WiFi, 5) << "Found id " << message_type.family_id
252 << " for name '" << name << "' in "
253 << wait_duration.tv_sec << " sec, "
254 << wait_duration.tv_usec << " usec.";
255 return message_type.family_id;
256 }
Wade Guthriefa2100e2013-05-15 10:11:22 -0700257 time_->GetTimeMonotonic(&now);
Wade Guthriebee87c22013-03-06 11:00:46 -0800258 } while (timercmp(&now, &end_time, <));
259
260 LOG(ERROR) << "Timed out waiting for family_id for family '" << name << "'.";
261 return NetlinkMessage::kIllegalMessageType;
Wade Guthrie0d438532012-05-18 14:18:50 -0700262}
263
Wade Guthriebb9fca22013-04-10 17:21:42 -0700264bool NetlinkManager::AddBroadcastHandler(const NetlinkMessageHandler &handler) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800265 list<NetlinkMessageHandler>::iterator i;
266 if (FindBroadcastHandler(handler)) {
267 LOG(WARNING) << "Trying to re-add a handler";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700268 return false; // Should only be one copy in the list.
269 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800270 if (handler.is_null()) {
271 LOG(WARNING) << "Trying to add a NULL handler";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700272 return false;
273 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800274 // And add the handler to the list.
Wade Guthriebb9fca22013-04-10 17:21:42 -0700275 SLOG(WiFi, 3) << "NetlinkManager::" << __func__ << " - adding handler";
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800276 broadcast_handlers_.push_back(handler);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700277 return true;
278}
279
Wade Guthriebb9fca22013-04-10 17:21:42 -0700280bool NetlinkManager::RemoveBroadcastHandler(
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800281 const NetlinkMessageHandler &handler) {
282 list<NetlinkMessageHandler>::iterator i;
283 for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
284 if ((*i).Equals(handler)) {
285 broadcast_handlers_.erase(i);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700286 // Should only be one copy in the list so we don't have to continue
287 // looking for another one.
288 return true;
289 }
290 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800291 LOG(WARNING) << "NetlinkMessageHandler not found.";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700292 return false;
293}
294
Wade Guthriebb9fca22013-04-10 17:21:42 -0700295bool NetlinkManager::FindBroadcastHandler(const NetlinkMessageHandler &handler)
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800296 const {
297 list<NetlinkMessageHandler>::const_iterator i;
298 for (i = broadcast_handlers_.begin(); i != broadcast_handlers_.end(); ++i) {
299 if ((*i).Equals(handler)) {
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700300 return true;
301 }
302 }
303 return false;
304}
305
Wade Guthriebb9fca22013-04-10 17:21:42 -0700306void NetlinkManager::ClearBroadcastHandlers() {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800307 broadcast_handlers_.clear();
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700308}
309
Wade Guthriebb9fca22013-04-10 17:21:42 -0700310bool NetlinkManager::SendMessage(NetlinkMessage *message,
Wade Guthrie92d06362013-04-25 15:41:30 -0700311 const NetlinkMessageHandler &handler) {
Wade Guthrie5d53d492012-11-07 09:53:31 -0800312 if (!message) {
313 LOG(ERROR) << "Message is NULL.";
314 return false;
315 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800316
Wade Guthriebee87c22013-03-06 11:00:46 -0800317 ByteString message_string = message->Encode(this->GetSequenceNumber());
Wade Guthriecc53f232013-03-05 13:22:23 -0800318
319 if (handler.is_null()) {
320 SLOG(WiFi, 3) << "Handler for message was null.";
321 } else if (ContainsKey(message_handlers_, message->sequence_number())) {
322 LOG(ERROR) << "A handler already existed for sequence: "
Wade Guthriebee87c22013-03-06 11:00:46 -0800323 << message->sequence_number();
324 return false;
Wade Guthriecc53f232013-03-05 13:22:23 -0800325 } else {
326 message_handlers_[message->sequence_number()] = handler;
327 }
Wade Guthrie8e278612013-02-26 10:32:34 -0800328
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700329 SLOG(WiFi, 5) << "NL Message " << message->sequence_number()
Wade Guthriecc53f232013-03-05 13:22:23 -0800330 << " Sending (" << message_string.GetLength()
331 << " bytes) ===>";
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700332 message->Print(6, 7);
333 NetlinkMessage::PrintBytes(8, message_string.GetConstData(),
Wade Guthriecc53f232013-03-05 13:22:23 -0800334 message_string.GetLength());
Wade Guthrie8e278612013-02-26 10:32:34 -0800335
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800336 if (!sock_->SendMessage(message_string)) {
Wade Guthrief48a1952013-03-04 17:33:47 -0800337 LOG(ERROR) << "Failed to send Netlink message.";
Wade Guthrie5d53d492012-11-07 09:53:31 -0800338 return false;
339 }
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700340 return true;
341}
342
Wade Guthriebb9fca22013-04-10 17:21:42 -0700343bool NetlinkManager::RemoveMessageHandler(const NetlinkMessage &message) {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800344 if (!ContainsKey(message_handlers_, message.sequence_number())) {
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700345 return false;
346 }
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800347 message_handlers_.erase(message.sequence_number());
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700348 return true;
349}
350
Wade Guthriebb9fca22013-04-10 17:21:42 -0700351uint32_t NetlinkManager::GetSequenceNumber() {
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800352 return sock_ ?
Wade Guthrief48a1952013-03-04 17:33:47 -0800353 sock_->GetSequenceNumber() : NetlinkMessage::kBroadcastSequenceNumber;
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800354}
355
Wade Guthriebb9fca22013-04-10 17:21:42 -0700356bool NetlinkManager::SubscribeToEvents(const string &family_id,
357 const string &group_name) {
Wade Guthriebee87c22013-03-06 11:00:46 -0800358 if (!ContainsKey(message_types_, family_id)) {
359 LOG(ERROR) << "Family '" << family_id << "' doesn't exist";
Wade Guthrie0d438532012-05-18 14:18:50 -0700360 return false;
361 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800362
363 if (!ContainsKey(message_types_[family_id].groups, group_name)) {
364 LOG(ERROR) << "Group '" << group_name << "' doesn't exist in family '"
365 << family_id << "'";
366 return false;
367 }
368
369 uint32_t group_id = message_types_[family_id].groups[group_name];
370 if (!sock_) {
371 LOG(FATAL) << "Need to call |Init| first.";
372 }
373 return sock_->SubscribeToEvents(group_id);
Wade Guthrie0d438532012-05-18 14:18:50 -0700374}
375
Wade Guthriebb9fca22013-04-10 17:21:42 -0700376void NetlinkManager::OnRawNlMessageReceived(InputData *data) {
repo syncbcaa6942013-01-02 15:38:21 -0800377 if (!data) {
378 LOG(ERROR) << __func__ << "() called with null header.";
379 return;
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700380 }
repo syncbcaa6942013-01-02 15:38:21 -0800381 unsigned char *buf = data->buf;
382 unsigned char *end = buf + data->len;
383 while (buf < end) {
384 nlmsghdr *msg = reinterpret_cast<nlmsghdr *>(buf);
385 // Discard the message if there're not enough bytes to a) tell the code how
386 // much space is in the message (i.e., to access nlmsg_len) or b) to hold
387 // the entire message. The odd calculation is there to keep the code from
388 // potentially calculating an illegal address (causes a segfault on some
389 // architectures).
390 size_t bytes_left = end - buf;
391 if (((bytes_left < (offsetof(nlmsghdr, nlmsg_len) +
Liam McLoughlinf4baef22012-08-01 19:08:25 -0700392 sizeof(msg->nlmsg_len))) ||
repo syncbcaa6942013-01-02 15:38:21 -0800393 (bytes_left < msg->nlmsg_len))) {
394 LOG(ERROR) << "Discarding incomplete message.";
395 return;
396 }
397 OnNlMessageReceived(msg);
398 buf += msg->nlmsg_len;
399 }
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700400}
Wade Guthrie0d438532012-05-18 14:18:50 -0700401
Wade Guthriebb9fca22013-04-10 17:21:42 -0700402void NetlinkManager::OnNlMessageReceived(nlmsghdr *msg) {
Christopher Wiley393b93f2012-11-08 17:30:58 -0800403 if (!msg) {
404 LOG(ERROR) << __func__ << "() called with null header.";
repo syncbcaa6942013-01-02 15:38:21 -0800405 return;
Christopher Wiley393b93f2012-11-08 17:30:58 -0800406 }
407 const uint32 sequence_number = msg->nlmsg_seq;
Wade Guthrie12f113a2013-03-12 17:15:46 -0700408 scoped_ptr<NetlinkMessage> message(message_factory_.CreateMessage(msg));
Wade Guthrie0d438532012-05-18 14:18:50 -0700409 if (message == NULL) {
Wade Guthrie8e278612013-02-26 10:32:34 -0800410 SLOG(WiFi, 3) << "NL Message " << sequence_number << " <===";
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700411 SLOG(WiFi, 3) << __func__ << "(msg:NULL)";
repo syncbcaa6942013-01-02 15:38:21 -0800412 return; // Skip current message, continue parsing buffer.
Christopher Wiley393b93f2012-11-08 17:30:58 -0800413 }
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700414 SLOG(WiFi, 5) << "NL Message " << sequence_number
Wade Guthrie8e278612013-02-26 10:32:34 -0800415 << " Received (" << msg->nlmsg_len << " bytes) <===";
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700416 message->Print(6, 7);
Wade Guthrief48a1952013-03-04 17:33:47 -0800417 NetlinkMessage::PrintBytes(8, reinterpret_cast<const unsigned char *>(msg),
Wade Guthrie8e278612013-02-26 10:32:34 -0800418 msg->nlmsg_len);
419
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800420 // Call (then erase) any message-specific handler.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800421 if (ContainsKey(message_handlers_, sequence_number)) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700422 SLOG(WiFi, 6) << "found message-specific handler";
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800423 if (message_handlers_[sequence_number].is_null()) {
424 LOG(ERROR) << "NetlinkMessageHandler exists but is NULL for ID "
425 << sequence_number;
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700426 } else {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800427 message_handlers_[sequence_number].Run(*message);
Christopher Wiley393b93f2012-11-08 17:30:58 -0800428 }
Wade Guthriebee87c22013-03-06 11:00:46 -0800429
430 if (message->message_type() == ErrorAckMessage::kMessageType) {
431 const ErrorAckMessage *error_ack_message =
432 reinterpret_cast<const ErrorAckMessage *>(message.get());
433 if (error_ack_message->error()) {
434 SLOG(WiFi, 3) << "Removing callback";
435 message_handlers_.erase(sequence_number);
436 } else {
437 SLOG(WiFi, 3) << "ACK message -- not removing callback";
438 }
439 } else if ((message->flags() & NLM_F_MULTI) &&
440 (message->message_type() != NLMSG_DONE)) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700441 SLOG(WiFi, 6) << "Multi-part message -- not removing callback";
Wade Guthriebee87c22013-03-06 11:00:46 -0800442 } else {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700443 SLOG(WiFi, 6) << "Removing callback";
Wade Guthriebee87c22013-03-06 11:00:46 -0800444 message_handlers_.erase(sequence_number);
445 }
Christopher Wiley393b93f2012-11-08 17:30:58 -0800446 } else {
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800447 list<NetlinkMessageHandler>::const_iterator i =
448 broadcast_handlers_.begin();
449 while (i != broadcast_handlers_.end()) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700450 SLOG(WiFi, 6) << __func__ << " - calling broadcast handler";
repo syncbcaa6942013-01-02 15:38:21 -0800451 i->Run(*message);
452 ++i;
Wade Guthrie0d438532012-05-18 14:18:50 -0700453 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700454 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700455}
456
Wade Guthriebb9fca22013-04-10 17:21:42 -0700457void NetlinkManager::OnReadError(const Error &error) {
458 // TODO(wdg): When netlink_manager is used for scan, et al., this should
459 // either be LOG(FATAL) or the code should properly deal with errors,
460 // e.g., dropped messages due to the socket buffer being full.
461 LOG(ERROR) << "NetlinkManager's netlink Socket read returns error: "
repo syncbcaa6942013-01-02 15:38:21 -0800462 << error.message();
463}
464
465
Wade Guthrie0d438532012-05-18 14:18:50 -0700466} // namespace shill.