blob: d990a760a916cb3c88562a1b1f3642579adc77b7 [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//
5// This code is derived from the 'iw' source code. The copyright and license
6// of that code is as follows:
7//
8// Copyright (c) 2007, 2008 Johannes Berg
9// Copyright (c) 2007 Andy Lutomirski
10// Copyright (c) 2007 Mike Kershaw
11// Copyright (c) 2008-2009 Luis R. Rodriguez
12//
13// Permission to use, copy, modify, and/or distribute this software for any
14// purpose with or without fee is hereby granted, provided that the above
15// copyright notice and this permission notice appear in all copies.
16//
17// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
repo syncdc085c82012-12-28 08:54:41 -080025#include "shill/nl80211_message.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070026
Wade Guthriebdcdaa72013-03-04 12:47:12 -080027#include <limits.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070028#include <netlink/attr.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070029#include <netlink/msg.h>
30#include <netlink/netlink.h>
31
Wade Guthrie8e278612013-02-26 10:32:34 -080032#include <algorithm>
Wade Guthrie89e6cb32013-03-07 08:03:45 -080033#include <map>
Wade Guthrie0d438532012-05-18 14:18:50 -070034#include <string>
Wade Guthrie89e6cb32013-03-07 08:03:45 -080035#include <vector>
Wade Guthrie0d438532012-05-18 14:18:50 -070036
Wade Guthrie68da97c2013-02-26 13:09:35 -080037#include <base/bind.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070038#include <base/format_macros.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070039#include <base/stringprintf.h>
40
repo sync90ee0fa2012-12-18 10:08:08 -080041#include "shill/attribute_list.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070042#include "shill/ieee80211.h"
43#include "shill/logging.h"
Wade Guthrief162f8b2013-02-27 14:13:55 -080044#include "shill/netlink_attribute.h"
Wade Guthrie89e6cb32013-03-07 08:03:45 -080045#include "shill/refptr_types.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070046
Wade Guthrie68da97c2013-02-26 13:09:35 -080047using base::Bind;
Wade Guthrie0d438532012-05-18 14:18:50 -070048using base::LazyInstance;
49using base::StringAppendF;
50using base::StringPrintf;
51using std::map;
Wade Guthrie8e278612013-02-26 10:32:34 -080052using std::min;
Wade Guthrie0d438532012-05-18 14:18:50 -070053using std::string;
54using std::vector;
55
56namespace shill {
57
58namespace {
repo syncdc085c82012-12-28 08:54:41 -080059LazyInstance<Nl80211MessageDataCollector> g_datacollector =
Wade Guthrie0d438532012-05-18 14:18:50 -070060 LAZY_INSTANCE_INITIALIZER;
61} // namespace
62
Wade Guthrie0d438532012-05-18 14:18:50 -070063const uint8_t Nl80211Frame::kMinimumFrameByteCount = 26;
64const uint8_t Nl80211Frame::kFrameTypeMask = 0xfc;
65
Wade Guthrief48a1952013-03-04 17:33:47 -080066const uint32_t NetlinkMessage::kBroadcastSequenceNumber = 0;
67const uint16_t NetlinkMessage::kIllegalMessageType = UINT16_MAX;
Wade Guthriebdcdaa72013-03-04 12:47:12 -080068
69const char Nl80211Message::kBogusMacAddress[] = "XX:XX:XX:XX:XX:XX";
repo syncdc085c82012-12-28 08:54:41 -080070const unsigned int Nl80211Message::kEthernetAddressBytes = 6;
Wade Guthriebee87c22013-03-06 11:00:46 -080071const char Nl80211Message::kMessageTypeString[] = "nl80211";
repo syncdc085c82012-12-28 08:54:41 -080072map<uint16_t, string> *Nl80211Message::reason_code_string_ = NULL;
73map<uint16_t, string> *Nl80211Message::status_code_string_ = NULL;
Wade Guthriebdcdaa72013-03-04 12:47:12 -080074uint16_t Nl80211Message::nl80211_message_type_ = kIllegalMessageType;
75
Wade Guthrief48a1952013-03-04 17:33:47 -080076// NetlinkMessage
Wade Guthrie0d438532012-05-18 14:18:50 -070077
Wade Guthriebee87c22013-03-06 11:00:46 -080078ByteString NetlinkMessage::EncodeHeader(uint32_t sequence_number) {
Wade Guthrief48a1952013-03-04 17:33:47 -080079 ByteString result;
Wade Guthriebee87c22013-03-06 11:00:46 -080080 if (message_type_ == kIllegalMessageType) {
81 LOG(ERROR) << "Message type not set";
82 return result;
83 }
Wade Guthrief48a1952013-03-04 17:33:47 -080084 sequence_number_ = sequence_number;
85 if (sequence_number_ == kBroadcastSequenceNumber) {
86 LOG(ERROR) << "Couldn't get a legal sequence number";
87 return result;
88 }
Wade Guthrie0d438532012-05-18 14:18:50 -070089
Wade Guthrief48a1952013-03-04 17:33:47 -080090 // Build netlink header.
91 nlmsghdr header;
92 size_t nlmsghdr_with_pad = NLMSG_ALIGN(sizeof(header));
93 header.nlmsg_len = nlmsghdr_with_pad;
Wade Guthriebee87c22013-03-06 11:00:46 -080094 header.nlmsg_type = message_type_;
Wade Guthrief48a1952013-03-04 17:33:47 -080095 header.nlmsg_flags = NLM_F_REQUEST | flags_;
96 header.nlmsg_seq = sequence_number_;
97 header.nlmsg_pid = getpid();
Wade Guthrie0d438532012-05-18 14:18:50 -070098
Wade Guthrief48a1952013-03-04 17:33:47 -080099 // Netlink header + pad.
100 result.Append(ByteString(reinterpret_cast<unsigned char *>(&header),
101 sizeof(header)));
102 result.Resize(nlmsghdr_with_pad); // Zero-fill pad space (if any).
103 return result;
104}
105
106bool NetlinkMessage::InitAndStripHeader(ByteString *input) {
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800107 if (!input) {
108 LOG(ERROR) << "NULL input";
109 return false;
110 }
Wade Guthrief48a1952013-03-04 17:33:47 -0800111 if (input->GetLength() < sizeof(nlmsghdr)) {
112 LOG(ERROR) << "Insufficient input to extract nlmsghdr";
113 return false;
114 }
115
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800116 // Read the nlmsghdr.
117 nlmsghdr *header = reinterpret_cast<nlmsghdr *>(input->GetData());
118 message_type_ = header->nlmsg_type;
119 flags_ = header->nlmsg_flags;
120 sequence_number_ = header->nlmsg_seq;
121
122 // Strip the nlmsghdr.
123 input->RemovePrefix(NLMSG_ALIGN(sizeof(struct nlmsghdr)));
Wade Guthrief48a1952013-03-04 17:33:47 -0800124 return true;
125}
126
127bool NetlinkMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
128 if (!const_msg) {
129 LOG(ERROR) << "Null |const_msg| parameter";
130 return false;
131 }
132 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
133 const_msg->nlmsg_len);
134 if (!InitAndStripHeader(&message)) {
135 return false;
136 }
137 return true;
138}
139
140// static
141void NetlinkMessage::PrintBytes(int log_level, const unsigned char *buf,
142 size_t num_bytes) {
143 SLOG(WiFi, log_level) << "Netlink Message -- Examining Bytes";
144 if (!buf) {
145 SLOG(WiFi, log_level) << "<NULL Buffer>";
146 return;
147 }
148
149 if (num_bytes >= sizeof(nlmsghdr)) {
150 const nlmsghdr *header = reinterpret_cast<const nlmsghdr *>(buf);
151 SLOG(WiFi, log_level) << StringPrintf(
152 "len: %02x %02x %02x %02x = %u bytes",
153 buf[0], buf[1], buf[2], buf[3], header->nlmsg_len);
154
155 SLOG(WiFi, log_level) << StringPrintf(
156 "type | flags: %02x %02x %02x %02x - type:%u flags:%s%s%s%s%s",
157 buf[4], buf[5], buf[6], buf[7], header->nlmsg_type,
158 ((header->nlmsg_flags & NLM_F_REQUEST) ? " REQUEST" : ""),
159 ((header->nlmsg_flags & NLM_F_MULTI) ? " MULTI" : ""),
160 ((header->nlmsg_flags & NLM_F_ACK) ? " ACK" : ""),
161 ((header->nlmsg_flags & NLM_F_ECHO) ? " ECHO" : ""),
162 ((header->nlmsg_flags & NLM_F_DUMP_INTR) ? " BAD-SEQ" : ""));
163
164 SLOG(WiFi, log_level) << StringPrintf(
165 "sequence: %02x %02x %02x %02x = %u",
166 buf[8], buf[9], buf[10], buf[11], header->nlmsg_seq);
167 SLOG(WiFi, log_level) << StringPrintf(
168 "pid: %02x %02x %02x %02x = %u",
169 buf[12], buf[13], buf[14], buf[15], header->nlmsg_pid);
170 buf += sizeof(nlmsghdr);
171 num_bytes -= sizeof(nlmsghdr);
172 } else {
173 SLOG(WiFi, log_level) << "Not enough bytes (" << num_bytes
174 << ") for a complete nlmsghdr (requires "
175 << sizeof(nlmsghdr) << ").";
176 }
177
178 while (num_bytes) {
179 string output;
180 size_t bytes_this_row = min(num_bytes, static_cast<size_t>(32));
181 for (size_t i = 0; i < bytes_this_row; ++i) {
182 StringAppendF(&output, " %02x", *buf++);
183 }
184 SLOG(WiFi, log_level) << output;
185 num_bytes -= bytes_this_row;
186 }
187}
188
Wade Guthrie71872472013-03-05 10:33:38 -0800189const uint16_t ErrorAckMessage::kMessageType = NLMSG_ERROR;
190
191bool ErrorAckMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
192 if (!const_msg) {
193 LOG(ERROR) << "Null |const_msg| parameter";
194 return false;
195 }
196 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
197 const_msg->nlmsg_len);
198 if (!InitAndStripHeader(&message)) {
199 return false;
200 }
201
202 // Get the error code from the payload.
203 error_ = *(reinterpret_cast<const uint32_t *>(message.GetConstData()));
204 return true;
205}
206
Wade Guthriebee87c22013-03-06 11:00:46 -0800207ByteString ErrorAckMessage::Encode(uint32_t sequence_number) {
Wade Guthrie71872472013-03-05 10:33:38 -0800208 LOG(ERROR) << "We're not supposed to send errors or Acks to the kernel";
209 return ByteString();
210}
211
212string ErrorAckMessage::ToString() const {
213 string output;
214 if (error()) {
215 StringAppendF(&output, "NL80211_ERROR 0x%" PRIx32 ": %s",
216 -error_, strerror(-error_));
217 } else {
218 StringAppendF(&output, "ACK");
219 }
220 return output;
221}
222
223void ErrorAckMessage::Print(int log_level) const {
224 SLOG(WiFi, log_level) << ToString();
225}
226
227const uint16_t NoopMessage::kMessageType = NLMSG_NOOP;
228
Wade Guthriebee87c22013-03-06 11:00:46 -0800229ByteString NoopMessage::Encode(uint32_t sequence_number) {
Wade Guthrie71872472013-03-05 10:33:38 -0800230 LOG(ERROR) << "We're not supposed to send NOOP to the kernel";
231 return ByteString();
232}
233
234void NoopMessage::Print(int log_level) const {
235 SLOG(WiFi, log_level) << ToString();
236}
237
238const uint16_t DoneMessage::kMessageType = NLMSG_DONE;
239
Wade Guthriebee87c22013-03-06 11:00:46 -0800240ByteString DoneMessage::Encode(uint32_t sequence_number) {
Wade Guthrie71872472013-03-05 10:33:38 -0800241 LOG(ERROR)
242 << "We're not supposed to send Done messages (are we?) to the kernel";
243 return ByteString();
244}
245
246void DoneMessage::Print(int log_level) const {
247 SLOG(WiFi, log_level) << ToString();
248}
249
250const uint16_t OverrunMessage::kMessageType = NLMSG_OVERRUN;
251
Wade Guthriebee87c22013-03-06 11:00:46 -0800252ByteString OverrunMessage::Encode(uint32_t sequence_number) {
Wade Guthrie71872472013-03-05 10:33:38 -0800253 LOG(ERROR) << "We're not supposed to send Overruns to the kernel";
254 return ByteString();
255}
256
257void OverrunMessage::Print(int log_level) const {
258 SLOG(WiFi, log_level) << ToString();
259}
260
Wade Guthrief48a1952013-03-04 17:33:47 -0800261// GenericNetlinkMessage
262
Wade Guthriebee87c22013-03-06 11:00:46 -0800263ByteString GenericNetlinkMessage::EncodeHeader(uint32_t sequence_number) {
Wade Guthrief48a1952013-03-04 17:33:47 -0800264 // Build nlmsghdr.
Wade Guthriebee87c22013-03-06 11:00:46 -0800265 ByteString result(NetlinkMessage::EncodeHeader(sequence_number));
Wade Guthrief48a1952013-03-04 17:33:47 -0800266 if (result.GetLength() == 0) {
267 LOG(ERROR) << "Couldn't encode message header.";
268 return result;
269 }
270
271 // Build and append the genl message header.
272 genlmsghdr genl_header;
273 genl_header.cmd = command();
274 genl_header.version = 1;
275 genl_header.reserved = 0;
276
277 ByteString genl_header_string(
278 reinterpret_cast<unsigned char *>(&genl_header), sizeof(genl_header));
279 size_t genlmsghdr_with_pad = NLMSG_ALIGN(sizeof(genl_header));
280 genl_header_string.Resize(genlmsghdr_with_pad); // Zero-fill.
281
282 nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
283 pheader->nlmsg_len += genlmsghdr_with_pad;
284 result.Append(genl_header_string);
285 return result;
286}
287
Wade Guthriebee87c22013-03-06 11:00:46 -0800288ByteString GenericNetlinkMessage::Encode(uint32_t sequence_number) {
289 ByteString result(EncodeHeader(sequence_number));
Wade Guthrief48a1952013-03-04 17:33:47 -0800290 if (result.GetLength() == 0) {
291 LOG(ERROR) << "Couldn't encode message header.";
292 return result;
293 }
294
295 // Build and append attributes (padding is included by
296 // AttributeList::Encode).
297 ByteString attribute_string = attributes_->Encode();
298
299 // Need to re-calculate |header| since |Append|, above, moves the data.
300 nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
301 pheader->nlmsg_len += attribute_string.GetLength();
302 result.Append(attribute_string);
303
304 return result;
305}
306
307bool GenericNetlinkMessage::InitAndStripHeader(ByteString *input) {
308 if (!input) {
309 LOG(ERROR) << "NULL input";
310 return false;
311 }
312 if (!NetlinkMessage::InitAndStripHeader(input)) {
313 return false;
314 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800315
316 // Read the genlmsghdr.
317 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(input->GetData());
318 if (command_ != gnlh->cmd) {
319 LOG(WARNING) << "This object thinks it's a " << command_
320 << " but the message thinks it's a " << gnlh->cmd;
321 }
322
323 // Strip the genlmsghdr.
324 input->RemovePrefix(NLMSG_ALIGN(sizeof(struct genlmsghdr)));
325 return true;
Wade Guthrie8e278612013-02-26 10:32:34 -0800326}
327
Wade Guthrief48a1952013-03-04 17:33:47 -0800328void GenericNetlinkMessage::Print(int log_level) const {
329 SLOG(WiFi, log_level) << StringPrintf("Message %s (%d)",
330 command_string(),
331 command());
332 attributes_->Print(log_level, 1);
333}
334
335// Nl80211Message
336
Wade Guthriebee87c22013-03-06 11:00:46 -0800337// static
338void Nl80211Message::SetMessageType(uint16_t message_type) {
339 if (message_type == NetlinkMessage::kIllegalMessageType) {
340 LOG(FATAL) << "Absolutely need a legal message type for Nl80211 messages.";
341 }
342 nl80211_message_type_ = message_type;
343}
344
repo sync0efa9f02012-12-28 13:40:20 -0800345bool Nl80211Message::InitFromNlmsg(const nlmsghdr *const_msg) {
346 if (!const_msg) {
347 LOG(ERROR) << "Null |msg| parameter";
Wade Guthrie0d438532012-05-18 14:18:50 -0700348 return false;
349 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800350 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
351 const_msg->nlmsg_len);
Wade Guthrie0d438532012-05-18 14:18:50 -0700352
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800353 if (!InitAndStripHeader(&message)) {
354 return false;
355 }
repo sync0efa9f02012-12-28 13:40:20 -0800356
357 // Attributes.
358 // Parse the attributes from the nl message payload into the 'tb' array.
359 nlattr *tb[NL80211_ATTR_MAX + 1];
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800360 nla_parse(tb, NL80211_ATTR_MAX,
361 reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
362 NULL);
repo sync0efa9f02012-12-28 13:40:20 -0800363
Wade Guthrie0d438532012-05-18 14:18:50 -0700364 for (int i = 0; i < NL80211_ATTR_MAX + 1; ++i) {
365 if (tb[i]) {
repo sync0efa9f02012-12-28 13:40:20 -0800366 // TODO(wdg): When Nl80211Messages instantiate their own attributes,
367 // this call should, instead, call |SetAttributeFromNlAttr|.
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800368 attributes_->CreateAndInitAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800369 i, tb[i], Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
Wade Guthrie0d438532012-05-18 14:18:50 -0700370 }
371 }
372
373 // Convert integer values provided by libnl (for example, from the
374 // NL80211_ATTR_STATUS_CODE or NL80211_ATTR_REASON_CODE attribute) into
375 // strings describing the status.
Wade Guthried4977f22012-08-22 12:37:54 -0700376 if (!reason_code_string_) {
377 reason_code_string_ = new map<uint16_t, string>;
378 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecified] =
379 "Unspecified reason";
380 (*reason_code_string_)[
381 IEEE_80211::kReasonCodePreviousAuthenticationInvalid] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700382 "Previous authentication no longer valid";
Wade Guthried4977f22012-08-22 12:37:54 -0700383 (*reason_code_string_)[IEEE_80211::kReasonCodeSenderHasLeft] =
384 "Deauthentcated because sending STA is leaving (or has left) IBSS or "
385 "ESS";
386 (*reason_code_string_)[IEEE_80211::kReasonCodeInactivity] =
387 "Disassociated due to inactivity";
388 (*reason_code_string_)[IEEE_80211::kReasonCodeTooManySTAs] =
389 "Disassociated because AP is unable to handle all currently associated "
390 "STAs";
391 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAuthenticated] =
392 "Class 2 frame received from nonauthenticated STA";
393 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAssociated] =
394 "Class 3 frame received from nonassociated STA";
395 (*reason_code_string_)[IEEE_80211::kReasonCodeDisassociatedHasLeft] =
396 "Disassociated because sending STA is leaving (or has left) BSS";
397 (*reason_code_string_)[
398 IEEE_80211::kReasonCodeReassociationNotAuthenticated] =
399 "STA requesting (re)association is not authenticated with responding "
400 "STA";
401 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptablePowerCapability] =
402 "Disassociated because the information in the Power Capability "
403 "element is unacceptable";
404 (*reason_code_string_)[
405 IEEE_80211::kReasonCodeUnacceptableSupportedChannelInfo] =
406 "Disassociated because the information in the Supported Channels "
407 "element is unacceptable";
408 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidInfoElement] =
409 "Invalid information element, i.e., an information element defined in "
410 "this standard for which the content does not meet the specifications "
411 "in Clause 7";
412 (*reason_code_string_)[IEEE_80211::kReasonCodeMICFailure] =
413 "Message integrity code (MIC) failure";
414 (*reason_code_string_)[IEEE_80211::kReasonCode4WayTimeout] =
415 "4-Way Handshake timeout";
416 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupKeyHandshakeTimeout] =
417 "Group Key Handshake timeout";
418 (*reason_code_string_)[IEEE_80211::kReasonCodeDifferenIE] =
419 "Information element in 4-Way Handshake different from "
420 "(Re)Association Request/Probe Response/Beacon frame";
421 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupCipherInvalid] =
422 "Invalid group cipher";
423 (*reason_code_string_)[IEEE_80211::kReasonCodePairwiseCipherInvalid] =
424 "Invalid pairwise cipher";
425 (*reason_code_string_)[IEEE_80211::kReasonCodeAkmpInvalid] =
426 "Invalid AKMP";
427 (*reason_code_string_)[IEEE_80211::kReasonCodeUnsupportedRsnIeVersion] =
428 "Unsupported RSN information element version";
429 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidRsnIeCaps] =
430 "Invalid RSN information element capabilities";
431 (*reason_code_string_)[IEEE_80211::kReasonCode8021XAuth] =
432 "IEEE 802.1X authentication failed";
433 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteRejected] =
434 "Cipher suite rejected because of the security policy";
435 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecifiedQoS] =
436 "Disassociated for unspecified, QoS-related reason";
437 (*reason_code_string_)[IEEE_80211::kReasonCodeQoSBandwidth] =
438 "Disassociated because QoS AP lacks sufficient bandwidth for this "
439 "QoS STA";
440 (*reason_code_string_)[IEEE_80211::kReasonCodeiPoorConditions] =
441 "Disassociated because excessive number of frames need to be "
442 "acknowledged, but are not acknowledged due to AP transmissions "
443 "and/or poor channel conditions";
444 (*reason_code_string_)[IEEE_80211::kReasonCodeOutsideTxop] =
445 "Disassociated because STA is transmitting outside the limits of its "
446 "TXOPs";
447 (*reason_code_string_)[IEEE_80211::kReasonCodeStaLeaving] =
448 "Requested from peer STA as the STA is leaving the BSS (or resetting)";
449 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptableMechanism] =
450 "Requested from peer STA as it does not want to use the mechanism";
451 (*reason_code_string_)[IEEE_80211::kReasonCodeSetupRequired] =
452 "Requested from peer STA as the STA received frames using the "
453 "mechanism for which a setup is required";
454 (*reason_code_string_)[IEEE_80211::kReasonCodeTimeout] =
455 "Requested from peer STA due to timeout";
456 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteNotSupported] =
457 "Peer STA does not support the requested cipher suite";
458 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalid] = "<INVALID REASON>";
459 }
460
461 if (!status_code_string_) {
462 status_code_string_ = new map<uint16_t, string>;
463 (*status_code_string_)[IEEE_80211::kStatusCodeSuccessful] = "Successful";
464 (*status_code_string_)[IEEE_80211::kStatusCodeFailure] =
465 "Unspecified failure";
466 (*status_code_string_)[IEEE_80211::kStatusCodeAllCapabilitiesNotSupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700467 "Cannot support all requested capabilities in the capability "
468 "information field";
Wade Guthried4977f22012-08-22 12:37:54 -0700469 (*status_code_string_)[IEEE_80211::kStatusCodeCantConfirmAssociation] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700470 "Reassociation denied due to inability to confirm that association "
471 "exists";
Wade Guthried4977f22012-08-22 12:37:54 -0700472 (*status_code_string_)[IEEE_80211::kStatusCodeAssociationDenied] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700473 "Association denied due to reason outside the scope of this standard";
Wade Guthried4977f22012-08-22 12:37:54 -0700474 (*status_code_string_)[
475 IEEE_80211::kStatusCodeAuthenticationUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700476 "Responding station does not support the specified authentication "
477 "algorithm";
Wade Guthried4977f22012-08-22 12:37:54 -0700478 (*status_code_string_)[IEEE_80211::kStatusCodeOutOfSequence] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700479 "Received an authentication frame with authentication transaction "
480 "sequence number out of expected sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700481 (*status_code_string_)[IEEE_80211::kStatusCodeChallengeFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700482 "Authentication rejected because of challenge failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700483 (*status_code_string_)[IEEE_80211::kStatusCodeFrameTimeout] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700484 "Authentication rejected due to timeout waiting for next frame in "
485 "sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700486 (*status_code_string_)[IEEE_80211::kStatusCodeMaxSta] =
487 "Association denied because AP is unable to handle additional "
488 "associated STA";
489 (*status_code_string_)[IEEE_80211::kStatusCodeDataRateUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700490 "Association denied due to requesting station not supporting all of "
491 "the data rates in the BSSBasicRateSet parameter";
Wade Guthried4977f22012-08-22 12:37:54 -0700492 (*status_code_string_)[IEEE_80211::kStatusCodeShortPreambleUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700493 "Association denied due to requesting station not supporting the "
494 "short preamble option";
Wade Guthried4977f22012-08-22 12:37:54 -0700495 (*status_code_string_)[IEEE_80211::kStatusCodePbccUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700496 "Association denied due to requesting station not supporting the PBCC "
497 "modulation option";
Wade Guthried4977f22012-08-22 12:37:54 -0700498 (*status_code_string_)[
499 IEEE_80211::kStatusCodeChannelAgilityUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700500 "Association denied due to requesting station not supporting the "
501 "channel agility option";
Wade Guthried4977f22012-08-22 12:37:54 -0700502 (*status_code_string_)[IEEE_80211::kStatusCodeNeedSpectrumManagement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700503 "Association request rejected because Spectrum Management capability "
504 "is required";
Wade Guthried4977f22012-08-22 12:37:54 -0700505 (*status_code_string_)[
506 IEEE_80211::kStatusCodeUnacceptablePowerCapability] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700507 "Association request rejected because the information in the Power "
508 "Capability element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700509 (*status_code_string_)[
510 IEEE_80211::kStatusCodeUnacceptableSupportedChannelInfo] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700511 "Association request rejected because the information in the "
512 "Supported Channels element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700513 (*status_code_string_)[IEEE_80211::kStatusCodeShortTimeSlotRequired] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700514 "Association request rejected due to requesting station not "
Wade Guthried4977f22012-08-22 12:37:54 -0700515 "supporting the Short Slot Time option";
516 (*status_code_string_)[IEEE_80211::kStatusCodeDssOfdmRequired] =
517 "Association request rejected due to requesting station not "
518 "supporting the DSSS-OFDM option";
519 (*status_code_string_)[IEEE_80211::kStatusCodeQosFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700520 "Unspecified, QoS related failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700521 (*status_code_string_)[
522 IEEE_80211::kStatusCodeInsufficientBandwithForQsta] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700523 "Association denied due to QAP having insufficient bandwidth to handle "
524 "another QSTA";
Wade Guthried4977f22012-08-22 12:37:54 -0700525 (*status_code_string_)[IEEE_80211::kStatusCodePoorConditions] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700526 "Association denied due to poor channel conditions";
Wade Guthried4977f22012-08-22 12:37:54 -0700527 (*status_code_string_)[IEEE_80211::kStatusCodeQosNotSupported] =
528 "Association (with QoS BSS) denied due to requesting station not "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700529 "supporting the QoS facility";
Wade Guthried4977f22012-08-22 12:37:54 -0700530 (*status_code_string_)[IEEE_80211::kStatusCodeDeclined] =
531 "The request has been declined";
532 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidParameterValues] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700533 "The request has not been successful as one or more parameters have "
534 "invalid values";
Wade Guthried4977f22012-08-22 12:37:54 -0700535 (*status_code_string_)[IEEE_80211::kStatusCodeCannotBeHonored] =
536 "The TS has not been created because the request cannot be honored. "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700537 "However, a suggested Tspec is provided so that the initiating QSTA "
538 "may attempt to send another TS with the suggested changes to the "
539 "TSpec";
Wade Guthried4977f22012-08-22 12:37:54 -0700540 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidInfoElement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700541 "Invalid Information Element";
Wade Guthried4977f22012-08-22 12:37:54 -0700542 (*status_code_string_)[IEEE_80211::kStatusCodeGroupCipherInvalid] =
543 "Invalid Group Cipher";
544 (*status_code_string_)[IEEE_80211::kStatusCodePairwiseCipherInvalid] =
545 "Invalid Pairwise Cipher";
546 (*status_code_string_)[IEEE_80211::kStatusCodeAkmpInvalid] = "Invalid AKMP";
547 (*status_code_string_)[IEEE_80211::kStatusCodeUnsupportedRsnIeVersion] =
548 "Unsupported RSN Information Element version";
549 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidRsnIeCaps] =
550 "Invalid RSN Information Element Capabilities";
551 (*status_code_string_)[IEEE_80211::kStatusCodeCipherSuiteRejected] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700552 "Cipher suite is rejected per security policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700553 (*status_code_string_)[IEEE_80211::kStatusCodeTsDelayNotMet] =
554 "The TS has not been created. However, the HC may be capable of "
555 "creating a TS, in response to a request, after the time indicated in "
556 "the TS Delay element";
557 (*status_code_string_)[IEEE_80211::kStatusCodeDirectLinkIllegal] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700558 "Direct link is not allowed in the BSS by policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700559 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInBss] =
560 "Destination STA is not present within this BSS";
561 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInQsta] =
562 "The destination STA is not a QoS STA";
563 (*status_code_string_)[IEEE_80211::kStatusCodeExcessiveListenInterval] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700564 "Association denied because Listen Interval is too large";
Wade Guthried4977f22012-08-22 12:37:54 -0700565 (*status_code_string_)[IEEE_80211::kStatusCodeInvalid] = "<INVALID STATUS>";
Wade Guthrie0d438532012-05-18 14:18:50 -0700566 }
567
568 return true;
569}
570
Wade Guthrie0d438532012-05-18 14:18:50 -0700571// Helper function to provide a string for a MAC address.
Wade Guthrie68da97c2013-02-26 13:09:35 -0800572bool Nl80211Message::GetMacAttributeString(int id, string *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700573 if (!value) {
574 LOG(ERROR) << "Null |value| parameter";
575 return false;
576 }
577
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800578 ByteString data;
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800579 if (!const_attributes()->GetRawAttributeValue(id, &data)) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700580 value->assign(kBogusMacAddress);
581 return false;
582 }
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800583 value->assign(StringFromMacAddress(data.GetConstData()));
Wade Guthrie0d438532012-05-18 14:18:50 -0700584
585 return true;
586}
587
588// Helper function to provide a string for NL80211_ATTR_SCAN_FREQUENCIES.
repo syncdc085c82012-12-28 08:54:41 -0800589bool Nl80211Message::GetScanFrequenciesAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800590 int id, vector<uint32_t> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700591 if (!value) {
592 LOG(ERROR) << "Null |value| parameter";
593 return false;
594 }
595
596 value->clear();
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800597
598 AttributeListConstRefPtr frequency_list;
599 if (!const_attributes()->ConstGetNestedAttributeList(
600 NL80211_ATTR_SCAN_FREQUENCIES, &frequency_list) || !frequency_list) {
601 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_FREQUENCIES attribute";
repo syncd316eb72012-12-10 15:48:47 -0800602 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800603 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700604
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800605 // Assume IDs for the nested attribute array are linear starting from 1.
606 // Currently, that is enforced in the input to the nested attribute.
607 uint32_t freq;
608 int i = 1;
609 while (frequency_list->GetU32AttributeValue(i, &freq)) {
610 value->push_back(freq);
611 ++i;
Wade Guthrie0d438532012-05-18 14:18:50 -0700612 }
repo syncd316eb72012-12-10 15:48:47 -0800613 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700614}
615
616// Helper function to provide a string for NL80211_ATTR_SCAN_SSIDS.
repo syncdc085c82012-12-28 08:54:41 -0800617bool Nl80211Message::GetScanSsidsAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800618 int id, vector<string> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700619 if (!value) {
620 LOG(ERROR) << "Null |value| parameter";
621 return false;
622 }
623
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800624 AttributeListConstRefPtr ssid_list;
625 if (!const_attributes()->ConstGetNestedAttributeList(
626 NL80211_ATTR_SCAN_SSIDS, &ssid_list) || !ssid_list) {
627 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_SSIDS attribute";
repo sync90ee0fa2012-12-18 10:08:08 -0800628 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800629 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700630
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800631 // Assume IDs for the nested attribute array are linear starting from 1.
632 // Currently, that is enforced in the input to the nested attribute.
633 string ssid;
634 int i = 1;
635 while (ssid_list->GetStringAttributeValue(i, &ssid)) {
636 value->push_back(ssid);
637 ++i;
Wade Guthrie0d438532012-05-18 14:18:50 -0700638 }
repo sync90ee0fa2012-12-18 10:08:08 -0800639 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700640}
641
Wade Guthrie0d438532012-05-18 14:18:50 -0700642// static
repo syncdc085c82012-12-28 08:54:41 -0800643string Nl80211Message::StringFromMacAddress(const uint8_t *arg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700644 string output;
645
646 if (!arg) {
647 output = kBogusMacAddress;
648 LOG(ERROR) << "|arg| parameter is NULL.";
649 } else {
650 StringAppendF(&output, "%02x", arg[0]);
651
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800652 for (unsigned int i = 1; i < kEthernetAddressBytes ; ++i) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700653 StringAppendF(&output, ":%02x", arg[i]);
654 }
655 }
656 return output;
657}
658
659// static
repo syncdc085c82012-12-28 08:54:41 -0800660string Nl80211Message::StringFromReason(uint16_t status) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700661 map<uint16_t, string>::const_iterator match;
Wade Guthried4977f22012-08-22 12:37:54 -0700662 match = reason_code_string_->find(status);
663 if (match == reason_code_string_->end()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700664 string output;
Wade Guthried4977f22012-08-22 12:37:54 -0700665 if (status < IEEE_80211::kReasonCodeMax) {
666 StringAppendF(&output, "<Reserved Reason:%u>", status);
667 } else {
668 StringAppendF(&output, "<Unknown Reason:%u>", status);
669 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700670 return output;
671 }
672 return match->second;
673}
674
Wade Guthried4977f22012-08-22 12:37:54 -0700675// static
repo syncdc085c82012-12-28 08:54:41 -0800676string Nl80211Message::StringFromStatus(uint16_t status) {
Wade Guthried4977f22012-08-22 12:37:54 -0700677 map<uint16_t, string>::const_iterator match;
678 match = status_code_string_->find(status);
679 if (match == status_code_string_->end()) {
680 string output;
681 if (status < IEEE_80211::kStatusCodeMax) {
682 StringAppendF(&output, "<Reserved Status:%u>", status);
683 } else {
684 StringAppendF(&output, "<Unknown Status:%u>", status);
685 }
686 return output;
687 }
688 return match->second;
689}
690
repo syncdc085c82012-12-28 08:54:41 -0800691
Wade Guthrie71872472013-03-05 10:33:38 -0800692// Control Message
693
694const uint16_t ControlNetlinkMessage::kMessageType = GENL_ID_CTRL;
695
696bool ControlNetlinkMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
697 if (!const_msg) {
698 LOG(ERROR) << "Null |msg| parameter";
699 return false;
700 }
701 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
702 const_msg->nlmsg_len);
703
704 if (!InitAndStripHeader(&message)) {
705 return false;
706 }
707
708 // Attributes.
709 // Parse the attributes from the nl message payload into the 'tb' array.
710 nlattr *tb[CTRL_ATTR_MAX + 1];
711 nla_parse(tb, CTRL_ATTR_MAX,
712 reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
713 NULL);
714
715 for (int i = 0; i < CTRL_ATTR_MAX + 1; ++i) {
716 if (tb[i]) {
717 // TODO(wdg): When Nl80211Messages instantiate their own attributes,
718 // this call should, instead, call |SetAttributeFromNlAttr|.
719 attributes_->CreateAndInitAttribute(
720 i, tb[i], Bind(&NetlinkAttribute::NewControlAttributeFromId));
721 }
722 }
723 return true;
724}
725
726// Specific Control types.
727
728const uint8_t NewFamilyMessage::kCommand = CTRL_CMD_NEWFAMILY;
729const char NewFamilyMessage::kCommandString[] = "CTRL_CMD_NEWFAMILY";
730
731const uint8_t GetFamilyMessage::kCommand = CTRL_CMD_GETFAMILY;
732const char GetFamilyMessage::kCommandString[] = "CTRL_CMD_GETFAMILY";
733
734// Nl80211Frame
735
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800736Nl80211Frame::Nl80211Frame(const ByteString &raw_frame)
Wade Guthried4977f22012-08-22 12:37:54 -0700737 : frame_type_(kIllegalFrameType), reason_(UINT16_MAX), status_(UINT16_MAX),
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800738 frame_(raw_frame) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700739 const IEEE_80211::ieee80211_frame *frame =
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800740 reinterpret_cast<const IEEE_80211::ieee80211_frame *>(
741 frame_.GetConstData());
Wade Guthrie0d438532012-05-18 14:18:50 -0700742
743 // Now, let's populate the other stuff.
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800744 if (frame_.GetLength() >= kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700745 mac_from_ =
repo syncdc085c82012-12-28 08:54:41 -0800746 Nl80211Message::StringFromMacAddress(&frame->destination_mac[0]);
747 mac_to_ = Nl80211Message::StringFromMacAddress(&frame->source_mac[0]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700748 frame_type_ = frame->frame_control & kFrameTypeMask;
749
750 switch (frame_type_) {
751 case kAssocResponseFrameType:
752 case kReassocResponseFrameType:
753 status_ = le16toh(frame->u.associate_response.status_code);
754 break;
755
756 case kAuthFrameType:
757 status_ = le16toh(frame->u.authentiate_message.status_code);
758 break;
759
760 case kDisassocFrameType:
761 case kDeauthFrameType:
Wade Guthried4977f22012-08-22 12:37:54 -0700762 reason_ = le16toh(frame->u.deauthentiate_message.reason_code);
Wade Guthrie0d438532012-05-18 14:18:50 -0700763 break;
764
765 default:
766 break;
767 }
768 }
769}
770
Wade Guthried4977f22012-08-22 12:37:54 -0700771bool Nl80211Frame::ToString(string *output) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700772 if (!output) {
773 LOG(ERROR) << "NULL |output|";
774 return false;
775 }
776
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800777 if (frame_.IsEmpty()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700778 output->append(" [no frame]");
779 return true;
780 }
781
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800782 if (frame_.GetLength() < kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700783 output->append(" [invalid frame: ");
784 } else {
785 StringAppendF(output, " %s -> %s", mac_from_.c_str(), mac_to_.c_str());
786
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800787 switch (frame_.GetConstData()[0] & kFrameTypeMask) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700788 case kAssocResponseFrameType:
789 StringAppendF(output, "; AssocResponse status: %u: %s",
790 status_,
repo syncdc085c82012-12-28 08:54:41 -0800791 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700792 break;
793 case kReassocResponseFrameType:
794 StringAppendF(output, "; ReassocResponse status: %u: %s",
795 status_,
repo syncdc085c82012-12-28 08:54:41 -0800796 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700797 break;
798 case kAuthFrameType:
799 StringAppendF(output, "; Auth status: %u: %s",
800 status_,
repo syncdc085c82012-12-28 08:54:41 -0800801 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700802 break;
803
804 case kDisassocFrameType:
805 StringAppendF(output, "; Disassoc reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700806 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800807 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700808 break;
809 case kDeauthFrameType:
810 StringAppendF(output, "; Deauth reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700811 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800812 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700813 break;
814
815 default:
816 break;
817 }
818 output->append(" [frame: ");
819 }
820
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800821 const unsigned char *frame = frame_.GetConstData();
822 for (size_t i = 0; i < frame_.GetLength(); ++i) {
823 StringAppendF(output, "%02x, ", frame[i]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700824 }
825 output->append("]");
826
827 return true;
828}
829
Wade Guthried4977f22012-08-22 12:37:54 -0700830bool Nl80211Frame::IsEqual(const Nl80211Frame &other) const {
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800831 return frame_.Equals(other.frame_);
Wade Guthrie0d438532012-05-18 14:18:50 -0700832}
833
Wade Guthried4977f22012-08-22 12:37:54 -0700834
Wade Guthrie0d438532012-05-18 14:18:50 -0700835//
repo syncdc085c82012-12-28 08:54:41 -0800836// Specific Nl80211Message types.
Wade Guthrie0d438532012-05-18 14:18:50 -0700837//
838
839const uint8_t AssociateMessage::kCommand = NL80211_CMD_ASSOCIATE;
840const char AssociateMessage::kCommandString[] = "NL80211_CMD_ASSOCIATE";
841
Wade Guthrie0d438532012-05-18 14:18:50 -0700842const uint8_t AuthenticateMessage::kCommand = NL80211_CMD_AUTHENTICATE;
843const char AuthenticateMessage::kCommandString[] = "NL80211_CMD_AUTHENTICATE";
844
Wade Guthrie0d438532012-05-18 14:18:50 -0700845const uint8_t CancelRemainOnChannelMessage::kCommand =
846 NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL;
847const char CancelRemainOnChannelMessage::kCommandString[] =
848 "NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL";
849
Wade Guthrie0d438532012-05-18 14:18:50 -0700850const uint8_t ConnectMessage::kCommand = NL80211_CMD_CONNECT;
851const char ConnectMessage::kCommandString[] = "NL80211_CMD_CONNECT";
852
Wade Guthrie0d438532012-05-18 14:18:50 -0700853const uint8_t DeauthenticateMessage::kCommand = NL80211_CMD_DEAUTHENTICATE;
854const char DeauthenticateMessage::kCommandString[] =
855 "NL80211_CMD_DEAUTHENTICATE";
856
Wade Guthrie0d438532012-05-18 14:18:50 -0700857const uint8_t DeleteStationMessage::kCommand = NL80211_CMD_DEL_STATION;
858const char DeleteStationMessage::kCommandString[] = "NL80211_CMD_DEL_STATION";
859
Wade Guthrie0d438532012-05-18 14:18:50 -0700860const uint8_t DisassociateMessage::kCommand = NL80211_CMD_DISASSOCIATE;
861const char DisassociateMessage::kCommandString[] = "NL80211_CMD_DISASSOCIATE";
862
Wade Guthrie0d438532012-05-18 14:18:50 -0700863const uint8_t DisconnectMessage::kCommand = NL80211_CMD_DISCONNECT;
864const char DisconnectMessage::kCommandString[] = "NL80211_CMD_DISCONNECT";
865
Wade Guthrie0d438532012-05-18 14:18:50 -0700866const uint8_t FrameTxStatusMessage::kCommand = NL80211_CMD_FRAME_TX_STATUS;
867const char FrameTxStatusMessage::kCommandString[] =
868 "NL80211_CMD_FRAME_TX_STATUS";
869
repo sync0efa9f02012-12-28 13:40:20 -0800870const uint8_t GetRegMessage::kCommand = NL80211_CMD_GET_REG;
871const char GetRegMessage::kCommandString[] = "NL80211_CMD_GET_REG";
872
Wade Guthrie0d438532012-05-18 14:18:50 -0700873const uint8_t JoinIbssMessage::kCommand = NL80211_CMD_JOIN_IBSS;
874const char JoinIbssMessage::kCommandString[] = "NL80211_CMD_JOIN_IBSS";
875
Wade Guthrie0d438532012-05-18 14:18:50 -0700876const uint8_t MichaelMicFailureMessage::kCommand =
877 NL80211_CMD_MICHAEL_MIC_FAILURE;
878const char MichaelMicFailureMessage::kCommandString[] =
879 "NL80211_CMD_MICHAEL_MIC_FAILURE";
880
Wade Guthrie0d438532012-05-18 14:18:50 -0700881const uint8_t NewScanResultsMessage::kCommand = NL80211_CMD_NEW_SCAN_RESULTS;
882const char NewScanResultsMessage::kCommandString[] =
883 "NL80211_CMD_NEW_SCAN_RESULTS";
884
Wade Guthrie0d438532012-05-18 14:18:50 -0700885const uint8_t NewStationMessage::kCommand = NL80211_CMD_NEW_STATION;
886const char NewStationMessage::kCommandString[] = "NL80211_CMD_NEW_STATION";
887
Wade Guthrie0d438532012-05-18 14:18:50 -0700888const uint8_t NewWifiMessage::kCommand = NL80211_CMD_NEW_WIPHY;
889const char NewWifiMessage::kCommandString[] = "NL80211_CMD_NEW_WIPHY";
890
Wade Guthrie0d438532012-05-18 14:18:50 -0700891const uint8_t NotifyCqmMessage::kCommand = NL80211_CMD_NOTIFY_CQM;
892const char NotifyCqmMessage::kCommandString[] = "NL80211_CMD_NOTIFY_CQM";
893
Wade Guthrie0d438532012-05-18 14:18:50 -0700894const uint8_t PmksaCandidateMessage::kCommand = NL80211_ATTR_PMKSA_CANDIDATE;
895const char PmksaCandidateMessage::kCommandString[] =
896 "NL80211_ATTR_PMKSA_CANDIDATE";
897
Wade Guthrie0d438532012-05-18 14:18:50 -0700898const uint8_t RegBeaconHintMessage::kCommand = NL80211_CMD_REG_BEACON_HINT;
899const char RegBeaconHintMessage::kCommandString[] =
900 "NL80211_CMD_REG_BEACON_HINT";
901
Wade Guthrie0d438532012-05-18 14:18:50 -0700902const uint8_t RegChangeMessage::kCommand = NL80211_CMD_REG_CHANGE;
903const char RegChangeMessage::kCommandString[] = "NL80211_CMD_REG_CHANGE";
904
Wade Guthrie0d438532012-05-18 14:18:50 -0700905const uint8_t RemainOnChannelMessage::kCommand = NL80211_CMD_REMAIN_ON_CHANNEL;
906const char RemainOnChannelMessage::kCommandString[] =
907 "NL80211_CMD_REMAIN_ON_CHANNEL";
908
Wade Guthrie0d438532012-05-18 14:18:50 -0700909const uint8_t RoamMessage::kCommand = NL80211_CMD_ROAM;
910const char RoamMessage::kCommandString[] = "NL80211_CMD_ROAM";
911
Wade Guthrie0d438532012-05-18 14:18:50 -0700912const uint8_t ScanAbortedMessage::kCommand = NL80211_CMD_SCAN_ABORTED;
913const char ScanAbortedMessage::kCommandString[] = "NL80211_CMD_SCAN_ABORTED";
914
Wade Guthrie71872472013-03-05 10:33:38 -0800915const uint8_t GetScanMessage::kCommand = NL80211_CMD_GET_SCAN;
916const char GetScanMessage::kCommandString[] = "NL80211_CMD_GET_SCAN";
917
Wade Guthrie0d438532012-05-18 14:18:50 -0700918const uint8_t TriggerScanMessage::kCommand = NL80211_CMD_TRIGGER_SCAN;
919const char TriggerScanMessage::kCommandString[] = "NL80211_CMD_TRIGGER_SCAN";
920
Wade Guthrie0d438532012-05-18 14:18:50 -0700921const uint8_t UnknownMessage::kCommand = 0xff;
922const char UnknownMessage::kCommandString[] = "<Unknown Message Type>";
923
Wade Guthrie0d438532012-05-18 14:18:50 -0700924const uint8_t UnprotDeauthenticateMessage::kCommand =
925 NL80211_CMD_UNPROT_DEAUTHENTICATE;
926const char UnprotDeauthenticateMessage::kCommandString[] =
927 "NL80211_CMD_UNPROT_DEAUTHENTICATE";
928
Wade Guthrie0d438532012-05-18 14:18:50 -0700929const uint8_t UnprotDisassociateMessage::kCommand =
930 NL80211_CMD_UNPROT_DISASSOCIATE;
931const char UnprotDisassociateMessage::kCommandString[] =
932 "NL80211_CMD_UNPROT_DISASSOCIATE";
933
Wade Guthrie0d438532012-05-18 14:18:50 -0700934//
935// Factory class.
936//
937
Wade Guthrie71872472013-03-05 10:33:38 -0800938// TODO(wdg): later, each message_type should register its own callback for
939// creating messages. For now, however, this is much easier.
Wade Guthrief48a1952013-03-04 17:33:47 -0800940NetlinkMessage *NetlinkMessageFactory::CreateMessage(nlmsghdr *msg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700941 if (!msg) {
942 LOG(ERROR) << "NULL |msg| parameter";
943 return NULL;
944 }
945
Wade Guthrief48a1952013-03-04 17:33:47 -0800946 scoped_ptr<NetlinkMessage> message;
repo sync0efa9f02012-12-28 13:40:20 -0800947 void *payload = nlmsg_data(msg);
repo syncdc085c82012-12-28 08:54:41 -0800948
Wade Guthrie71872472013-03-05 10:33:38 -0800949 if (msg->nlmsg_type == NoopMessage::kMessageType) {
repo sync0efa9f02012-12-28 13:40:20 -0800950 message.reset(new NoopMessage());
Wade Guthrie71872472013-03-05 10:33:38 -0800951 } else if (msg->nlmsg_type == DoneMessage::kMessageType) {
952 message.reset(new DoneMessage());
953 } else if (msg->nlmsg_type == OverrunMessage::kMessageType) {
954 message.reset(new OverrunMessage());
955 } else if (msg->nlmsg_type == ErrorAckMessage::kMessageType) {
956 message.reset(new ErrorAckMessage());
957 } else if (msg->nlmsg_type == ControlNetlinkMessage::kMessageType) {
958 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);
959
960 switch (gnlh->cmd) {
961 case NewFamilyMessage::kCommand:
962 message.reset(new NewFamilyMessage()); break;
963 case GetFamilyMessage::kCommand:
964 message.reset(new GetFamilyMessage()); break;
965
966 default:
967 message.reset(new UnknownMessage(gnlh->cmd)); break;
repo sync0efa9f02012-12-28 13:40:20 -0800968 }
969 } else {
repo sync0efa9f02012-12-28 13:40:20 -0800970 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);
Wade Guthrie0d438532012-05-18 14:18:50 -0700971
repo sync0efa9f02012-12-28 13:40:20 -0800972 switch (gnlh->cmd) {
973 case AssociateMessage::kCommand:
974 message.reset(new AssociateMessage()); break;
975 case AuthenticateMessage::kCommand:
976 message.reset(new AuthenticateMessage()); break;
977 case CancelRemainOnChannelMessage::kCommand:
978 message.reset(new CancelRemainOnChannelMessage()); break;
979 case ConnectMessage::kCommand:
980 message.reset(new ConnectMessage()); break;
981 case DeauthenticateMessage::kCommand:
982 message.reset(new DeauthenticateMessage()); break;
983 case DeleteStationMessage::kCommand:
984 message.reset(new DeleteStationMessage()); break;
985 case DisassociateMessage::kCommand:
986 message.reset(new DisassociateMessage()); break;
987 case DisconnectMessage::kCommand:
988 message.reset(new DisconnectMessage()); break;
989 case FrameTxStatusMessage::kCommand:
990 message.reset(new FrameTxStatusMessage()); break;
991 case GetRegMessage::kCommand:
992 message.reset(new GetRegMessage()); break;
993 case JoinIbssMessage::kCommand:
994 message.reset(new JoinIbssMessage()); break;
995 case MichaelMicFailureMessage::kCommand:
996 message.reset(new MichaelMicFailureMessage()); break;
997 case NewScanResultsMessage::kCommand:
998 message.reset(new NewScanResultsMessage()); break;
999 case NewStationMessage::kCommand:
1000 message.reset(new NewStationMessage()); break;
1001 case NewWifiMessage::kCommand:
1002 message.reset(new NewWifiMessage()); break;
1003 case NotifyCqmMessage::kCommand:
1004 message.reset(new NotifyCqmMessage()); break;
1005 case PmksaCandidateMessage::kCommand:
1006 message.reset(new PmksaCandidateMessage()); break;
1007 case RegBeaconHintMessage::kCommand:
1008 message.reset(new RegBeaconHintMessage()); break;
1009 case RegChangeMessage::kCommand:
1010 message.reset(new RegChangeMessage()); break;
1011 case RemainOnChannelMessage::kCommand:
1012 message.reset(new RemainOnChannelMessage()); break;
1013 case RoamMessage::kCommand:
1014 message.reset(new RoamMessage()); break;
1015 case ScanAbortedMessage::kCommand:
1016 message.reset(new ScanAbortedMessage()); break;
1017 case TriggerScanMessage::kCommand:
1018 message.reset(new TriggerScanMessage()); break;
1019 case UnprotDeauthenticateMessage::kCommand:
1020 message.reset(new UnprotDeauthenticateMessage()); break;
1021 case UnprotDisassociateMessage::kCommand:
1022 message.reset(new UnprotDisassociateMessage()); break;
Wade Guthrie0d438532012-05-18 14:18:50 -07001023
repo sync0efa9f02012-12-28 13:40:20 -08001024 default:
1025 message.reset(new UnknownMessage(gnlh->cmd)); break;
1026 }
Wade Guthrie71872472013-03-05 10:33:38 -08001027 }
Wade Guthrie0d438532012-05-18 14:18:50 -07001028
Wade Guthrie71872472013-03-05 10:33:38 -08001029 if (!message->InitFromNlmsg(msg)) {
1030 LOG(ERROR) << "Message did not initialize properly";
1031 return NULL;
Wade Guthrie0d438532012-05-18 14:18:50 -07001032 }
1033
Wade Guthrie0d438532012-05-18 14:18:50 -07001034 return message.release();
1035}
1036
repo syncdc085c82012-12-28 08:54:41 -08001037Nl80211MessageDataCollector *
1038 Nl80211MessageDataCollector::GetInstance() {
Wade Guthrie0d438532012-05-18 14:18:50 -07001039 return g_datacollector.Pointer();
1040}
1041
repo syncdc085c82012-12-28 08:54:41 -08001042Nl80211MessageDataCollector::Nl80211MessageDataCollector() {
Wade Guthrie0d438532012-05-18 14:18:50 -07001043 need_to_print[NL80211_ATTR_PMKSA_CANDIDATE] = true;
1044 need_to_print[NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL] = true;
1045 need_to_print[NL80211_CMD_DEL_STATION] = true;
1046 need_to_print[NL80211_CMD_FRAME_TX_STATUS] = true;
1047 need_to_print[NL80211_CMD_JOIN_IBSS] = true;
1048 need_to_print[NL80211_CMD_MICHAEL_MIC_FAILURE] = true;
1049 need_to_print[NL80211_CMD_NEW_WIPHY] = true;
1050 need_to_print[NL80211_CMD_REG_BEACON_HINT] = true;
1051 need_to_print[NL80211_CMD_REG_CHANGE] = true;
1052 need_to_print[NL80211_CMD_REMAIN_ON_CHANNEL] = true;
1053 need_to_print[NL80211_CMD_ROAM] = true;
1054 need_to_print[NL80211_CMD_SCAN_ABORTED] = true;
1055 need_to_print[NL80211_CMD_UNPROT_DEAUTHENTICATE] = true;
1056 need_to_print[NL80211_CMD_UNPROT_DISASSOCIATE] = true;
1057}
1058
repo syncdc085c82012-12-28 08:54:41 -08001059void Nl80211MessageDataCollector::CollectDebugData(
1060 const Nl80211Message &message, nlmsghdr *msg) {
Wade Guthrie0d438532012-05-18 14:18:50 -07001061 if (!msg) {
1062 LOG(ERROR) << "NULL |msg| parameter";
1063 return;
1064 }
1065
1066 bool doit = false;
1067
1068 map<uint8_t, bool>::const_iterator node;
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001069 node = need_to_print.find(message.command());
Wade Guthrie0d438532012-05-18 14:18:50 -07001070 if (node != need_to_print.end())
1071 doit = node->second;
1072
1073 if (doit) {
Wade Guthried6153612012-08-23 11:36:14 -07001074 LOG(INFO) << "@@const unsigned char "
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001075 << "k" << message.command_string()
Wade Guthried6153612012-08-23 11:36:14 -07001076 << "[] = {";
Wade Guthrie0d438532012-05-18 14:18:50 -07001077
Christopher Wileyefd521f2012-11-07 17:32:46 -08001078 int payload_bytes = nlmsg_datalen(msg);
Wade Guthrie0d438532012-05-18 14:18:50 -07001079
1080 size_t bytes = nlmsg_total_size(payload_bytes);
1081 unsigned char *rawdata = reinterpret_cast<unsigned char *>(msg);
Wade Guthried4977f22012-08-22 12:37:54 -07001082 for (size_t i = 0; i < bytes; ++i) {
Wade Guthried6153612012-08-23 11:36:14 -07001083 LOG(INFO) << " 0x"
Wade Guthrie0d438532012-05-18 14:18:50 -07001084 << std::hex << std::setfill('0') << std::setw(2)
1085 << + rawdata[i] << ",";
1086 }
Wade Guthried6153612012-08-23 11:36:14 -07001087 LOG(INFO) << "};";
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001088 need_to_print[message.command()] = false;
Wade Guthrie0d438532012-05-18 14:18:50 -07001089 }
1090}
1091
1092} // namespace shill.