blob: 99646f31c98c2d8dfa182ce0b7df4657ffe52dbf [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
27#include <ctype.h>
28#include <endian.h>
29#include <errno.h>
Wade Guthriebdcdaa72013-03-04 12:47:12 -080030#include <limits.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070031#include <linux/nl80211.h>
32#include <net/if.h>
Wade Guthrie8343f7f2012-12-04 13:52:32 -080033#include <netinet/in.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070034#include <netlink/attr.h>
35#include <netlink/genl/ctrl.h>
36#include <netlink/genl/family.h>
37#include <netlink/genl/genl.h>
38#include <netlink/msg.h>
39#include <netlink/netlink.h>
40
Wade Guthrie8e278612013-02-26 10:32:34 -080041#include <algorithm>
Wade Guthrie0d438532012-05-18 14:18:50 -070042#include <iomanip>
43#include <string>
44
Wade Guthrie68da97c2013-02-26 13:09:35 -080045#include <base/bind.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070046#include <base/format_macros.h>
47#include <base/stl_util.h>
48#include <base/stringprintf.h>
49
repo sync90ee0fa2012-12-18 10:08:08 -080050#include "shill/attribute_list.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070051#include "shill/ieee80211.h"
52#include "shill/logging.h"
Wade Guthrief162f8b2013-02-27 14:13:55 -080053#include "shill/netlink_attribute.h"
repo syncdc085c82012-12-28 08:54:41 -080054#include "shill/netlink_socket.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070055#include "shill/scope_logger.h"
56
Wade Guthrie68da97c2013-02-26 13:09:35 -080057using base::Bind;
Wade Guthrie0d438532012-05-18 14:18:50 -070058using base::LazyInstance;
59using base::StringAppendF;
60using base::StringPrintf;
61using std::map;
Wade Guthrie8e278612013-02-26 10:32:34 -080062using std::min;
Wade Guthrie0d438532012-05-18 14:18:50 -070063using std::string;
64using std::vector;
65
66namespace shill {
67
68namespace {
repo syncdc085c82012-12-28 08:54:41 -080069LazyInstance<Nl80211MessageDataCollector> g_datacollector =
Wade Guthrie0d438532012-05-18 14:18:50 -070070 LAZY_INSTANCE_INITIALIZER;
71} // namespace
72
Wade Guthrie0d438532012-05-18 14:18:50 -070073const uint8_t Nl80211Frame::kMinimumFrameByteCount = 26;
74const uint8_t Nl80211Frame::kFrameTypeMask = 0xfc;
75
Wade Guthrief48a1952013-03-04 17:33:47 -080076const uint32_t NetlinkMessage::kBroadcastSequenceNumber = 0;
77const uint16_t NetlinkMessage::kIllegalMessageType = UINT16_MAX;
Wade Guthriebdcdaa72013-03-04 12:47:12 -080078
79const char Nl80211Message::kBogusMacAddress[] = "XX:XX:XX:XX:XX:XX";
repo syncdc085c82012-12-28 08:54:41 -080080const unsigned int Nl80211Message::kEthernetAddressBytes = 6;
Wade Guthriebee87c22013-03-06 11:00:46 -080081const char Nl80211Message::kMessageTypeString[] = "nl80211";
repo syncdc085c82012-12-28 08:54:41 -080082map<uint16_t, string> *Nl80211Message::reason_code_string_ = NULL;
83map<uint16_t, string> *Nl80211Message::status_code_string_ = NULL;
Wade Guthriebdcdaa72013-03-04 12:47:12 -080084uint16_t Nl80211Message::nl80211_message_type_ = kIllegalMessageType;
85
Wade Guthrief48a1952013-03-04 17:33:47 -080086// NetlinkMessage
Wade Guthrie0d438532012-05-18 14:18:50 -070087
Wade Guthriebee87c22013-03-06 11:00:46 -080088ByteString NetlinkMessage::EncodeHeader(uint32_t sequence_number) {
Wade Guthrief48a1952013-03-04 17:33:47 -080089 ByteString result;
Wade Guthriebee87c22013-03-06 11:00:46 -080090 if (message_type_ == kIllegalMessageType) {
91 LOG(ERROR) << "Message type not set";
92 return result;
93 }
Wade Guthrief48a1952013-03-04 17:33:47 -080094 sequence_number_ = sequence_number;
95 if (sequence_number_ == kBroadcastSequenceNumber) {
96 LOG(ERROR) << "Couldn't get a legal sequence number";
97 return result;
98 }
Wade Guthrie0d438532012-05-18 14:18:50 -070099
Wade Guthrief48a1952013-03-04 17:33:47 -0800100 // Build netlink header.
101 nlmsghdr header;
102 size_t nlmsghdr_with_pad = NLMSG_ALIGN(sizeof(header));
103 header.nlmsg_len = nlmsghdr_with_pad;
Wade Guthriebee87c22013-03-06 11:00:46 -0800104 header.nlmsg_type = message_type_;
Wade Guthrief48a1952013-03-04 17:33:47 -0800105 header.nlmsg_flags = NLM_F_REQUEST | flags_;
106 header.nlmsg_seq = sequence_number_;
107 header.nlmsg_pid = getpid();
Wade Guthrie0d438532012-05-18 14:18:50 -0700108
Wade Guthrief48a1952013-03-04 17:33:47 -0800109 // Netlink header + pad.
110 result.Append(ByteString(reinterpret_cast<unsigned char *>(&header),
111 sizeof(header)));
112 result.Resize(nlmsghdr_with_pad); // Zero-fill pad space (if any).
113 return result;
114}
115
116bool NetlinkMessage::InitAndStripHeader(ByteString *input) {
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800117 if (!input) {
118 LOG(ERROR) << "NULL input";
119 return false;
120 }
Wade Guthrief48a1952013-03-04 17:33:47 -0800121 if (input->GetLength() < sizeof(nlmsghdr)) {
122 LOG(ERROR) << "Insufficient input to extract nlmsghdr";
123 return false;
124 }
125
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800126 // Read the nlmsghdr.
127 nlmsghdr *header = reinterpret_cast<nlmsghdr *>(input->GetData());
128 message_type_ = header->nlmsg_type;
129 flags_ = header->nlmsg_flags;
130 sequence_number_ = header->nlmsg_seq;
131
132 // Strip the nlmsghdr.
133 input->RemovePrefix(NLMSG_ALIGN(sizeof(struct nlmsghdr)));
Wade Guthrief48a1952013-03-04 17:33:47 -0800134 return true;
135}
136
137bool NetlinkMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
138 if (!const_msg) {
139 LOG(ERROR) << "Null |const_msg| parameter";
140 return false;
141 }
142 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
143 const_msg->nlmsg_len);
144 if (!InitAndStripHeader(&message)) {
145 return false;
146 }
147 return true;
148}
149
150// static
151void NetlinkMessage::PrintBytes(int log_level, const unsigned char *buf,
152 size_t num_bytes) {
153 SLOG(WiFi, log_level) << "Netlink Message -- Examining Bytes";
154 if (!buf) {
155 SLOG(WiFi, log_level) << "<NULL Buffer>";
156 return;
157 }
158
159 if (num_bytes >= sizeof(nlmsghdr)) {
160 const nlmsghdr *header = reinterpret_cast<const nlmsghdr *>(buf);
161 SLOG(WiFi, log_level) << StringPrintf(
162 "len: %02x %02x %02x %02x = %u bytes",
163 buf[0], buf[1], buf[2], buf[3], header->nlmsg_len);
164
165 SLOG(WiFi, log_level) << StringPrintf(
166 "type | flags: %02x %02x %02x %02x - type:%u flags:%s%s%s%s%s",
167 buf[4], buf[5], buf[6], buf[7], header->nlmsg_type,
168 ((header->nlmsg_flags & NLM_F_REQUEST) ? " REQUEST" : ""),
169 ((header->nlmsg_flags & NLM_F_MULTI) ? " MULTI" : ""),
170 ((header->nlmsg_flags & NLM_F_ACK) ? " ACK" : ""),
171 ((header->nlmsg_flags & NLM_F_ECHO) ? " ECHO" : ""),
172 ((header->nlmsg_flags & NLM_F_DUMP_INTR) ? " BAD-SEQ" : ""));
173
174 SLOG(WiFi, log_level) << StringPrintf(
175 "sequence: %02x %02x %02x %02x = %u",
176 buf[8], buf[9], buf[10], buf[11], header->nlmsg_seq);
177 SLOG(WiFi, log_level) << StringPrintf(
178 "pid: %02x %02x %02x %02x = %u",
179 buf[12], buf[13], buf[14], buf[15], header->nlmsg_pid);
180 buf += sizeof(nlmsghdr);
181 num_bytes -= sizeof(nlmsghdr);
182 } else {
183 SLOG(WiFi, log_level) << "Not enough bytes (" << num_bytes
184 << ") for a complete nlmsghdr (requires "
185 << sizeof(nlmsghdr) << ").";
186 }
187
188 while (num_bytes) {
189 string output;
190 size_t bytes_this_row = min(num_bytes, static_cast<size_t>(32));
191 for (size_t i = 0; i < bytes_this_row; ++i) {
192 StringAppendF(&output, " %02x", *buf++);
193 }
194 SLOG(WiFi, log_level) << output;
195 num_bytes -= bytes_this_row;
196 }
197}
198
Wade Guthrie71872472013-03-05 10:33:38 -0800199const uint16_t ErrorAckMessage::kMessageType = NLMSG_ERROR;
200
201bool ErrorAckMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
202 if (!const_msg) {
203 LOG(ERROR) << "Null |const_msg| parameter";
204 return false;
205 }
206 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
207 const_msg->nlmsg_len);
208 if (!InitAndStripHeader(&message)) {
209 return false;
210 }
211
212 // Get the error code from the payload.
213 error_ = *(reinterpret_cast<const uint32_t *>(message.GetConstData()));
214 return true;
215}
216
Wade Guthriebee87c22013-03-06 11:00:46 -0800217ByteString ErrorAckMessage::Encode(uint32_t sequence_number) {
Wade Guthrie71872472013-03-05 10:33:38 -0800218 LOG(ERROR) << "We're not supposed to send errors or Acks to the kernel";
219 return ByteString();
220}
221
222string ErrorAckMessage::ToString() const {
223 string output;
224 if (error()) {
225 StringAppendF(&output, "NL80211_ERROR 0x%" PRIx32 ": %s",
226 -error_, strerror(-error_));
227 } else {
228 StringAppendF(&output, "ACK");
229 }
230 return output;
231}
232
233void ErrorAckMessage::Print(int log_level) const {
234 SLOG(WiFi, log_level) << ToString();
235}
236
237const uint16_t NoopMessage::kMessageType = NLMSG_NOOP;
238
Wade Guthriebee87c22013-03-06 11:00:46 -0800239ByteString NoopMessage::Encode(uint32_t sequence_number) {
Wade Guthrie71872472013-03-05 10:33:38 -0800240 LOG(ERROR) << "We're not supposed to send NOOP to the kernel";
241 return ByteString();
242}
243
244void NoopMessage::Print(int log_level) const {
245 SLOG(WiFi, log_level) << ToString();
246}
247
248const uint16_t DoneMessage::kMessageType = NLMSG_DONE;
249
Wade Guthriebee87c22013-03-06 11:00:46 -0800250ByteString DoneMessage::Encode(uint32_t sequence_number) {
Wade Guthrie71872472013-03-05 10:33:38 -0800251 LOG(ERROR)
252 << "We're not supposed to send Done messages (are we?) to the kernel";
253 return ByteString();
254}
255
256void DoneMessage::Print(int log_level) const {
257 SLOG(WiFi, log_level) << ToString();
258}
259
260const uint16_t OverrunMessage::kMessageType = NLMSG_OVERRUN;
261
Wade Guthriebee87c22013-03-06 11:00:46 -0800262ByteString OverrunMessage::Encode(uint32_t sequence_number) {
Wade Guthrie71872472013-03-05 10:33:38 -0800263 LOG(ERROR) << "We're not supposed to send Overruns to the kernel";
264 return ByteString();
265}
266
267void OverrunMessage::Print(int log_level) const {
268 SLOG(WiFi, log_level) << ToString();
269}
270
Wade Guthrief48a1952013-03-04 17:33:47 -0800271// GenericNetlinkMessage
272
Wade Guthriebee87c22013-03-06 11:00:46 -0800273ByteString GenericNetlinkMessage::EncodeHeader(uint32_t sequence_number) {
Wade Guthrief48a1952013-03-04 17:33:47 -0800274 // Build nlmsghdr.
Wade Guthriebee87c22013-03-06 11:00:46 -0800275 ByteString result(NetlinkMessage::EncodeHeader(sequence_number));
Wade Guthrief48a1952013-03-04 17:33:47 -0800276 if (result.GetLength() == 0) {
277 LOG(ERROR) << "Couldn't encode message header.";
278 return result;
279 }
280
281 // Build and append the genl message header.
282 genlmsghdr genl_header;
283 genl_header.cmd = command();
284 genl_header.version = 1;
285 genl_header.reserved = 0;
286
287 ByteString genl_header_string(
288 reinterpret_cast<unsigned char *>(&genl_header), sizeof(genl_header));
289 size_t genlmsghdr_with_pad = NLMSG_ALIGN(sizeof(genl_header));
290 genl_header_string.Resize(genlmsghdr_with_pad); // Zero-fill.
291
292 nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
293 pheader->nlmsg_len += genlmsghdr_with_pad;
294 result.Append(genl_header_string);
295 return result;
296}
297
Wade Guthriebee87c22013-03-06 11:00:46 -0800298ByteString GenericNetlinkMessage::Encode(uint32_t sequence_number) {
299 ByteString result(EncodeHeader(sequence_number));
Wade Guthrief48a1952013-03-04 17:33:47 -0800300 if (result.GetLength() == 0) {
301 LOG(ERROR) << "Couldn't encode message header.";
302 return result;
303 }
304
305 // Build and append attributes (padding is included by
306 // AttributeList::Encode).
307 ByteString attribute_string = attributes_->Encode();
308
309 // Need to re-calculate |header| since |Append|, above, moves the data.
310 nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
311 pheader->nlmsg_len += attribute_string.GetLength();
312 result.Append(attribute_string);
313
314 return result;
315}
316
317bool GenericNetlinkMessage::InitAndStripHeader(ByteString *input) {
318 if (!input) {
319 LOG(ERROR) << "NULL input";
320 return false;
321 }
322 if (!NetlinkMessage::InitAndStripHeader(input)) {
323 return false;
324 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800325
326 // Read the genlmsghdr.
327 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(input->GetData());
328 if (command_ != gnlh->cmd) {
329 LOG(WARNING) << "This object thinks it's a " << command_
330 << " but the message thinks it's a " << gnlh->cmd;
331 }
332
333 // Strip the genlmsghdr.
334 input->RemovePrefix(NLMSG_ALIGN(sizeof(struct genlmsghdr)));
335 return true;
Wade Guthrie8e278612013-02-26 10:32:34 -0800336}
337
Wade Guthrief48a1952013-03-04 17:33:47 -0800338void GenericNetlinkMessage::Print(int log_level) const {
339 SLOG(WiFi, log_level) << StringPrintf("Message %s (%d)",
340 command_string(),
341 command());
342 attributes_->Print(log_level, 1);
343}
344
345// Nl80211Message
346
Wade Guthriebee87c22013-03-06 11:00:46 -0800347// static
348void Nl80211Message::SetMessageType(uint16_t message_type) {
349 if (message_type == NetlinkMessage::kIllegalMessageType) {
350 LOG(FATAL) << "Absolutely need a legal message type for Nl80211 messages.";
351 }
352 nl80211_message_type_ = message_type;
353}
354
repo sync0efa9f02012-12-28 13:40:20 -0800355bool Nl80211Message::InitFromNlmsg(const nlmsghdr *const_msg) {
356 if (!const_msg) {
357 LOG(ERROR) << "Null |msg| parameter";
Wade Guthrie0d438532012-05-18 14:18:50 -0700358 return false;
359 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800360 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
361 const_msg->nlmsg_len);
Wade Guthrie0d438532012-05-18 14:18:50 -0700362
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800363 if (!InitAndStripHeader(&message)) {
364 return false;
365 }
repo sync0efa9f02012-12-28 13:40:20 -0800366
367 // Attributes.
368 // Parse the attributes from the nl message payload into the 'tb' array.
369 nlattr *tb[NL80211_ATTR_MAX + 1];
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800370 nla_parse(tb, NL80211_ATTR_MAX,
371 reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
372 NULL);
repo sync0efa9f02012-12-28 13:40:20 -0800373
Wade Guthrie0d438532012-05-18 14:18:50 -0700374 for (int i = 0; i < NL80211_ATTR_MAX + 1; ++i) {
375 if (tb[i]) {
repo sync0efa9f02012-12-28 13:40:20 -0800376 // TODO(wdg): When Nl80211Messages instantiate their own attributes,
377 // this call should, instead, call |SetAttributeFromNlAttr|.
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800378 attributes_->CreateAndInitAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800379 i, tb[i], Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
Wade Guthrie0d438532012-05-18 14:18:50 -0700380 }
381 }
382
383 // Convert integer values provided by libnl (for example, from the
384 // NL80211_ATTR_STATUS_CODE or NL80211_ATTR_REASON_CODE attribute) into
385 // strings describing the status.
Wade Guthried4977f22012-08-22 12:37:54 -0700386 if (!reason_code_string_) {
387 reason_code_string_ = new map<uint16_t, string>;
388 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecified] =
389 "Unspecified reason";
390 (*reason_code_string_)[
391 IEEE_80211::kReasonCodePreviousAuthenticationInvalid] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700392 "Previous authentication no longer valid";
Wade Guthried4977f22012-08-22 12:37:54 -0700393 (*reason_code_string_)[IEEE_80211::kReasonCodeSenderHasLeft] =
394 "Deauthentcated because sending STA is leaving (or has left) IBSS or "
395 "ESS";
396 (*reason_code_string_)[IEEE_80211::kReasonCodeInactivity] =
397 "Disassociated due to inactivity";
398 (*reason_code_string_)[IEEE_80211::kReasonCodeTooManySTAs] =
399 "Disassociated because AP is unable to handle all currently associated "
400 "STAs";
401 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAuthenticated] =
402 "Class 2 frame received from nonauthenticated STA";
403 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAssociated] =
404 "Class 3 frame received from nonassociated STA";
405 (*reason_code_string_)[IEEE_80211::kReasonCodeDisassociatedHasLeft] =
406 "Disassociated because sending STA is leaving (or has left) BSS";
407 (*reason_code_string_)[
408 IEEE_80211::kReasonCodeReassociationNotAuthenticated] =
409 "STA requesting (re)association is not authenticated with responding "
410 "STA";
411 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptablePowerCapability] =
412 "Disassociated because the information in the Power Capability "
413 "element is unacceptable";
414 (*reason_code_string_)[
415 IEEE_80211::kReasonCodeUnacceptableSupportedChannelInfo] =
416 "Disassociated because the information in the Supported Channels "
417 "element is unacceptable";
418 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidInfoElement] =
419 "Invalid information element, i.e., an information element defined in "
420 "this standard for which the content does not meet the specifications "
421 "in Clause 7";
422 (*reason_code_string_)[IEEE_80211::kReasonCodeMICFailure] =
423 "Message integrity code (MIC) failure";
424 (*reason_code_string_)[IEEE_80211::kReasonCode4WayTimeout] =
425 "4-Way Handshake timeout";
426 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupKeyHandshakeTimeout] =
427 "Group Key Handshake timeout";
428 (*reason_code_string_)[IEEE_80211::kReasonCodeDifferenIE] =
429 "Information element in 4-Way Handshake different from "
430 "(Re)Association Request/Probe Response/Beacon frame";
431 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupCipherInvalid] =
432 "Invalid group cipher";
433 (*reason_code_string_)[IEEE_80211::kReasonCodePairwiseCipherInvalid] =
434 "Invalid pairwise cipher";
435 (*reason_code_string_)[IEEE_80211::kReasonCodeAkmpInvalid] =
436 "Invalid AKMP";
437 (*reason_code_string_)[IEEE_80211::kReasonCodeUnsupportedRsnIeVersion] =
438 "Unsupported RSN information element version";
439 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidRsnIeCaps] =
440 "Invalid RSN information element capabilities";
441 (*reason_code_string_)[IEEE_80211::kReasonCode8021XAuth] =
442 "IEEE 802.1X authentication failed";
443 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteRejected] =
444 "Cipher suite rejected because of the security policy";
445 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecifiedQoS] =
446 "Disassociated for unspecified, QoS-related reason";
447 (*reason_code_string_)[IEEE_80211::kReasonCodeQoSBandwidth] =
448 "Disassociated because QoS AP lacks sufficient bandwidth for this "
449 "QoS STA";
450 (*reason_code_string_)[IEEE_80211::kReasonCodeiPoorConditions] =
451 "Disassociated because excessive number of frames need to be "
452 "acknowledged, but are not acknowledged due to AP transmissions "
453 "and/or poor channel conditions";
454 (*reason_code_string_)[IEEE_80211::kReasonCodeOutsideTxop] =
455 "Disassociated because STA is transmitting outside the limits of its "
456 "TXOPs";
457 (*reason_code_string_)[IEEE_80211::kReasonCodeStaLeaving] =
458 "Requested from peer STA as the STA is leaving the BSS (or resetting)";
459 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptableMechanism] =
460 "Requested from peer STA as it does not want to use the mechanism";
461 (*reason_code_string_)[IEEE_80211::kReasonCodeSetupRequired] =
462 "Requested from peer STA as the STA received frames using the "
463 "mechanism for which a setup is required";
464 (*reason_code_string_)[IEEE_80211::kReasonCodeTimeout] =
465 "Requested from peer STA due to timeout";
466 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteNotSupported] =
467 "Peer STA does not support the requested cipher suite";
468 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalid] = "<INVALID REASON>";
469 }
470
471 if (!status_code_string_) {
472 status_code_string_ = new map<uint16_t, string>;
473 (*status_code_string_)[IEEE_80211::kStatusCodeSuccessful] = "Successful";
474 (*status_code_string_)[IEEE_80211::kStatusCodeFailure] =
475 "Unspecified failure";
476 (*status_code_string_)[IEEE_80211::kStatusCodeAllCapabilitiesNotSupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700477 "Cannot support all requested capabilities in the capability "
478 "information field";
Wade Guthried4977f22012-08-22 12:37:54 -0700479 (*status_code_string_)[IEEE_80211::kStatusCodeCantConfirmAssociation] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700480 "Reassociation denied due to inability to confirm that association "
481 "exists";
Wade Guthried4977f22012-08-22 12:37:54 -0700482 (*status_code_string_)[IEEE_80211::kStatusCodeAssociationDenied] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700483 "Association denied due to reason outside the scope of this standard";
Wade Guthried4977f22012-08-22 12:37:54 -0700484 (*status_code_string_)[
485 IEEE_80211::kStatusCodeAuthenticationUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700486 "Responding station does not support the specified authentication "
487 "algorithm";
Wade Guthried4977f22012-08-22 12:37:54 -0700488 (*status_code_string_)[IEEE_80211::kStatusCodeOutOfSequence] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700489 "Received an authentication frame with authentication transaction "
490 "sequence number out of expected sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700491 (*status_code_string_)[IEEE_80211::kStatusCodeChallengeFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700492 "Authentication rejected because of challenge failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700493 (*status_code_string_)[IEEE_80211::kStatusCodeFrameTimeout] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700494 "Authentication rejected due to timeout waiting for next frame in "
495 "sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700496 (*status_code_string_)[IEEE_80211::kStatusCodeMaxSta] =
497 "Association denied because AP is unable to handle additional "
498 "associated STA";
499 (*status_code_string_)[IEEE_80211::kStatusCodeDataRateUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700500 "Association denied due to requesting station not supporting all of "
501 "the data rates in the BSSBasicRateSet parameter";
Wade Guthried4977f22012-08-22 12:37:54 -0700502 (*status_code_string_)[IEEE_80211::kStatusCodeShortPreambleUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700503 "Association denied due to requesting station not supporting the "
504 "short preamble option";
Wade Guthried4977f22012-08-22 12:37:54 -0700505 (*status_code_string_)[IEEE_80211::kStatusCodePbccUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700506 "Association denied due to requesting station not supporting the PBCC "
507 "modulation option";
Wade Guthried4977f22012-08-22 12:37:54 -0700508 (*status_code_string_)[
509 IEEE_80211::kStatusCodeChannelAgilityUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700510 "Association denied due to requesting station not supporting the "
511 "channel agility option";
Wade Guthried4977f22012-08-22 12:37:54 -0700512 (*status_code_string_)[IEEE_80211::kStatusCodeNeedSpectrumManagement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700513 "Association request rejected because Spectrum Management capability "
514 "is required";
Wade Guthried4977f22012-08-22 12:37:54 -0700515 (*status_code_string_)[
516 IEEE_80211::kStatusCodeUnacceptablePowerCapability] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700517 "Association request rejected because the information in the Power "
518 "Capability element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700519 (*status_code_string_)[
520 IEEE_80211::kStatusCodeUnacceptableSupportedChannelInfo] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700521 "Association request rejected because the information in the "
522 "Supported Channels element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700523 (*status_code_string_)[IEEE_80211::kStatusCodeShortTimeSlotRequired] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700524 "Association request rejected due to requesting station not "
Wade Guthried4977f22012-08-22 12:37:54 -0700525 "supporting the Short Slot Time option";
526 (*status_code_string_)[IEEE_80211::kStatusCodeDssOfdmRequired] =
527 "Association request rejected due to requesting station not "
528 "supporting the DSSS-OFDM option";
529 (*status_code_string_)[IEEE_80211::kStatusCodeQosFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700530 "Unspecified, QoS related failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700531 (*status_code_string_)[
532 IEEE_80211::kStatusCodeInsufficientBandwithForQsta] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700533 "Association denied due to QAP having insufficient bandwidth to handle "
534 "another QSTA";
Wade Guthried4977f22012-08-22 12:37:54 -0700535 (*status_code_string_)[IEEE_80211::kStatusCodePoorConditions] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700536 "Association denied due to poor channel conditions";
Wade Guthried4977f22012-08-22 12:37:54 -0700537 (*status_code_string_)[IEEE_80211::kStatusCodeQosNotSupported] =
538 "Association (with QoS BSS) denied due to requesting station not "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700539 "supporting the QoS facility";
Wade Guthried4977f22012-08-22 12:37:54 -0700540 (*status_code_string_)[IEEE_80211::kStatusCodeDeclined] =
541 "The request has been declined";
542 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidParameterValues] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700543 "The request has not been successful as one or more parameters have "
544 "invalid values";
Wade Guthried4977f22012-08-22 12:37:54 -0700545 (*status_code_string_)[IEEE_80211::kStatusCodeCannotBeHonored] =
546 "The TS has not been created because the request cannot be honored. "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700547 "However, a suggested Tspec is provided so that the initiating QSTA "
548 "may attempt to send another TS with the suggested changes to the "
549 "TSpec";
Wade Guthried4977f22012-08-22 12:37:54 -0700550 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidInfoElement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700551 "Invalid Information Element";
Wade Guthried4977f22012-08-22 12:37:54 -0700552 (*status_code_string_)[IEEE_80211::kStatusCodeGroupCipherInvalid] =
553 "Invalid Group Cipher";
554 (*status_code_string_)[IEEE_80211::kStatusCodePairwiseCipherInvalid] =
555 "Invalid Pairwise Cipher";
556 (*status_code_string_)[IEEE_80211::kStatusCodeAkmpInvalid] = "Invalid AKMP";
557 (*status_code_string_)[IEEE_80211::kStatusCodeUnsupportedRsnIeVersion] =
558 "Unsupported RSN Information Element version";
559 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidRsnIeCaps] =
560 "Invalid RSN Information Element Capabilities";
561 (*status_code_string_)[IEEE_80211::kStatusCodeCipherSuiteRejected] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700562 "Cipher suite is rejected per security policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700563 (*status_code_string_)[IEEE_80211::kStatusCodeTsDelayNotMet] =
564 "The TS has not been created. However, the HC may be capable of "
565 "creating a TS, in response to a request, after the time indicated in "
566 "the TS Delay element";
567 (*status_code_string_)[IEEE_80211::kStatusCodeDirectLinkIllegal] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700568 "Direct link is not allowed in the BSS by policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700569 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInBss] =
570 "Destination STA is not present within this BSS";
571 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInQsta] =
572 "The destination STA is not a QoS STA";
573 (*status_code_string_)[IEEE_80211::kStatusCodeExcessiveListenInterval] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700574 "Association denied because Listen Interval is too large";
Wade Guthried4977f22012-08-22 12:37:54 -0700575 (*status_code_string_)[IEEE_80211::kStatusCodeInvalid] = "<INVALID STATUS>";
Wade Guthrie0d438532012-05-18 14:18:50 -0700576 }
577
578 return true;
579}
580
Wade Guthrie0d438532012-05-18 14:18:50 -0700581// Helper function to provide a string for a MAC address.
Wade Guthrie68da97c2013-02-26 13:09:35 -0800582bool Nl80211Message::GetMacAttributeString(int id, string *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700583 if (!value) {
584 LOG(ERROR) << "Null |value| parameter";
585 return false;
586 }
587
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800588 ByteString data;
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800589 if (!const_attributes()->GetRawAttributeValue(id, &data)) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700590 value->assign(kBogusMacAddress);
591 return false;
592 }
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800593 value->assign(StringFromMacAddress(data.GetConstData()));
Wade Guthrie0d438532012-05-18 14:18:50 -0700594
595 return true;
596}
597
598// Helper function to provide a string for NL80211_ATTR_SCAN_FREQUENCIES.
repo syncdc085c82012-12-28 08:54:41 -0800599bool Nl80211Message::GetScanFrequenciesAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800600 int id, vector<uint32_t> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700601 if (!value) {
602 LOG(ERROR) << "Null |value| parameter";
603 return false;
604 }
605
606 value->clear();
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800607
608 AttributeListConstRefPtr frequency_list;
609 if (!const_attributes()->ConstGetNestedAttributeList(
610 NL80211_ATTR_SCAN_FREQUENCIES, &frequency_list) || !frequency_list) {
611 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_FREQUENCIES attribute";
repo syncd316eb72012-12-10 15:48:47 -0800612 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800613 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700614
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800615 // Assume IDs for the nested attribute array are linear starting from 1.
616 // Currently, that is enforced in the input to the nested attribute.
617 uint32_t freq;
618 int i = 1;
619 while (frequency_list->GetU32AttributeValue(i, &freq)) {
620 value->push_back(freq);
621 ++i;
Wade Guthrie0d438532012-05-18 14:18:50 -0700622 }
repo syncd316eb72012-12-10 15:48:47 -0800623 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700624}
625
626// Helper function to provide a string for NL80211_ATTR_SCAN_SSIDS.
repo syncdc085c82012-12-28 08:54:41 -0800627bool Nl80211Message::GetScanSsidsAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800628 int id, vector<string> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700629 if (!value) {
630 LOG(ERROR) << "Null |value| parameter";
631 return false;
632 }
633
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800634 AttributeListConstRefPtr ssid_list;
635 if (!const_attributes()->ConstGetNestedAttributeList(
636 NL80211_ATTR_SCAN_SSIDS, &ssid_list) || !ssid_list) {
637 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_SSIDS attribute";
repo sync90ee0fa2012-12-18 10:08:08 -0800638 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800639 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700640
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800641 // Assume IDs for the nested attribute array are linear starting from 1.
642 // Currently, that is enforced in the input to the nested attribute.
643 string ssid;
644 int i = 1;
645 while (ssid_list->GetStringAttributeValue(i, &ssid)) {
646 value->push_back(ssid);
647 ++i;
Wade Guthrie0d438532012-05-18 14:18:50 -0700648 }
repo sync90ee0fa2012-12-18 10:08:08 -0800649 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700650}
651
Wade Guthrie0d438532012-05-18 14:18:50 -0700652// static
repo syncdc085c82012-12-28 08:54:41 -0800653string Nl80211Message::StringFromMacAddress(const uint8_t *arg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700654 string output;
655
656 if (!arg) {
657 output = kBogusMacAddress;
658 LOG(ERROR) << "|arg| parameter is NULL.";
659 } else {
660 StringAppendF(&output, "%02x", arg[0]);
661
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800662 for (unsigned int i = 1; i < kEthernetAddressBytes ; ++i) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700663 StringAppendF(&output, ":%02x", arg[i]);
664 }
665 }
666 return output;
667}
668
669// static
repo syncdc085c82012-12-28 08:54:41 -0800670string Nl80211Message::StringFromReason(uint16_t status) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700671 map<uint16_t, string>::const_iterator match;
Wade Guthried4977f22012-08-22 12:37:54 -0700672 match = reason_code_string_->find(status);
673 if (match == reason_code_string_->end()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700674 string output;
Wade Guthried4977f22012-08-22 12:37:54 -0700675 if (status < IEEE_80211::kReasonCodeMax) {
676 StringAppendF(&output, "<Reserved Reason:%u>", status);
677 } else {
678 StringAppendF(&output, "<Unknown Reason:%u>", status);
679 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700680 return output;
681 }
682 return match->second;
683}
684
Wade Guthried4977f22012-08-22 12:37:54 -0700685// static
repo syncdc085c82012-12-28 08:54:41 -0800686string Nl80211Message::StringFromStatus(uint16_t status) {
Wade Guthried4977f22012-08-22 12:37:54 -0700687 map<uint16_t, string>::const_iterator match;
688 match = status_code_string_->find(status);
689 if (match == status_code_string_->end()) {
690 string output;
691 if (status < IEEE_80211::kStatusCodeMax) {
692 StringAppendF(&output, "<Reserved Status:%u>", status);
693 } else {
694 StringAppendF(&output, "<Unknown Status:%u>", status);
695 }
696 return output;
697 }
698 return match->second;
699}
700
repo syncdc085c82012-12-28 08:54:41 -0800701
Wade Guthrie71872472013-03-05 10:33:38 -0800702// Control Message
703
704const uint16_t ControlNetlinkMessage::kMessageType = GENL_ID_CTRL;
705
706bool ControlNetlinkMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
707 if (!const_msg) {
708 LOG(ERROR) << "Null |msg| parameter";
709 return false;
710 }
711 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
712 const_msg->nlmsg_len);
713
714 if (!InitAndStripHeader(&message)) {
715 return false;
716 }
717
718 // Attributes.
719 // Parse the attributes from the nl message payload into the 'tb' array.
720 nlattr *tb[CTRL_ATTR_MAX + 1];
721 nla_parse(tb, CTRL_ATTR_MAX,
722 reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
723 NULL);
724
725 for (int i = 0; i < CTRL_ATTR_MAX + 1; ++i) {
726 if (tb[i]) {
727 // TODO(wdg): When Nl80211Messages instantiate their own attributes,
728 // this call should, instead, call |SetAttributeFromNlAttr|.
729 attributes_->CreateAndInitAttribute(
730 i, tb[i], Bind(&NetlinkAttribute::NewControlAttributeFromId));
731 }
732 }
733 return true;
734}
735
736// Specific Control types.
737
738const uint8_t NewFamilyMessage::kCommand = CTRL_CMD_NEWFAMILY;
739const char NewFamilyMessage::kCommandString[] = "CTRL_CMD_NEWFAMILY";
740
741const uint8_t GetFamilyMessage::kCommand = CTRL_CMD_GETFAMILY;
742const char GetFamilyMessage::kCommandString[] = "CTRL_CMD_GETFAMILY";
743
744// Nl80211Frame
745
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800746Nl80211Frame::Nl80211Frame(const ByteString &raw_frame)
Wade Guthried4977f22012-08-22 12:37:54 -0700747 : frame_type_(kIllegalFrameType), reason_(UINT16_MAX), status_(UINT16_MAX),
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800748 frame_(raw_frame) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700749 const IEEE_80211::ieee80211_frame *frame =
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800750 reinterpret_cast<const IEEE_80211::ieee80211_frame *>(
751 frame_.GetConstData());
Wade Guthrie0d438532012-05-18 14:18:50 -0700752
753 // Now, let's populate the other stuff.
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800754 if (frame_.GetLength() >= kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700755 mac_from_ =
repo syncdc085c82012-12-28 08:54:41 -0800756 Nl80211Message::StringFromMacAddress(&frame->destination_mac[0]);
757 mac_to_ = Nl80211Message::StringFromMacAddress(&frame->source_mac[0]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700758 frame_type_ = frame->frame_control & kFrameTypeMask;
759
760 switch (frame_type_) {
761 case kAssocResponseFrameType:
762 case kReassocResponseFrameType:
763 status_ = le16toh(frame->u.associate_response.status_code);
764 break;
765
766 case kAuthFrameType:
767 status_ = le16toh(frame->u.authentiate_message.status_code);
768 break;
769
770 case kDisassocFrameType:
771 case kDeauthFrameType:
Wade Guthried4977f22012-08-22 12:37:54 -0700772 reason_ = le16toh(frame->u.deauthentiate_message.reason_code);
Wade Guthrie0d438532012-05-18 14:18:50 -0700773 break;
774
775 default:
776 break;
777 }
778 }
779}
780
Wade Guthried4977f22012-08-22 12:37:54 -0700781bool Nl80211Frame::ToString(string *output) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700782 if (!output) {
783 LOG(ERROR) << "NULL |output|";
784 return false;
785 }
786
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800787 if (frame_.IsEmpty()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700788 output->append(" [no frame]");
789 return true;
790 }
791
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800792 if (frame_.GetLength() < kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700793 output->append(" [invalid frame: ");
794 } else {
795 StringAppendF(output, " %s -> %s", mac_from_.c_str(), mac_to_.c_str());
796
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800797 switch (frame_.GetConstData()[0] & kFrameTypeMask) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700798 case kAssocResponseFrameType:
799 StringAppendF(output, "; AssocResponse 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 case kReassocResponseFrameType:
804 StringAppendF(output, "; ReassocResponse status: %u: %s",
805 status_,
repo syncdc085c82012-12-28 08:54:41 -0800806 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700807 break;
808 case kAuthFrameType:
809 StringAppendF(output, "; Auth status: %u: %s",
810 status_,
repo syncdc085c82012-12-28 08:54:41 -0800811 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700812 break;
813
814 case kDisassocFrameType:
815 StringAppendF(output, "; Disassoc reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700816 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800817 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700818 break;
819 case kDeauthFrameType:
820 StringAppendF(output, "; Deauth reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700821 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800822 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700823 break;
824
825 default:
826 break;
827 }
828 output->append(" [frame: ");
829 }
830
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800831 const unsigned char *frame = frame_.GetConstData();
832 for (size_t i = 0; i < frame_.GetLength(); ++i) {
833 StringAppendF(output, "%02x, ", frame[i]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700834 }
835 output->append("]");
836
837 return true;
838}
839
Wade Guthried4977f22012-08-22 12:37:54 -0700840bool Nl80211Frame::IsEqual(const Nl80211Frame &other) const {
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800841 return frame_.Equals(other.frame_);
Wade Guthrie0d438532012-05-18 14:18:50 -0700842}
843
Wade Guthried4977f22012-08-22 12:37:54 -0700844
Wade Guthrie0d438532012-05-18 14:18:50 -0700845//
repo syncdc085c82012-12-28 08:54:41 -0800846// Specific Nl80211Message types.
Wade Guthrie0d438532012-05-18 14:18:50 -0700847//
848
849const uint8_t AssociateMessage::kCommand = NL80211_CMD_ASSOCIATE;
850const char AssociateMessage::kCommandString[] = "NL80211_CMD_ASSOCIATE";
851
Wade Guthrie0d438532012-05-18 14:18:50 -0700852const uint8_t AuthenticateMessage::kCommand = NL80211_CMD_AUTHENTICATE;
853const char AuthenticateMessage::kCommandString[] = "NL80211_CMD_AUTHENTICATE";
854
Wade Guthrie0d438532012-05-18 14:18:50 -0700855const uint8_t CancelRemainOnChannelMessage::kCommand =
856 NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL;
857const char CancelRemainOnChannelMessage::kCommandString[] =
858 "NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL";
859
Wade Guthrie0d438532012-05-18 14:18:50 -0700860const uint8_t ConnectMessage::kCommand = NL80211_CMD_CONNECT;
861const char ConnectMessage::kCommandString[] = "NL80211_CMD_CONNECT";
862
Wade Guthrie0d438532012-05-18 14:18:50 -0700863const uint8_t DeauthenticateMessage::kCommand = NL80211_CMD_DEAUTHENTICATE;
864const char DeauthenticateMessage::kCommandString[] =
865 "NL80211_CMD_DEAUTHENTICATE";
866
Wade Guthrie0d438532012-05-18 14:18:50 -0700867const uint8_t DeleteStationMessage::kCommand = NL80211_CMD_DEL_STATION;
868const char DeleteStationMessage::kCommandString[] = "NL80211_CMD_DEL_STATION";
869
Wade Guthrie0d438532012-05-18 14:18:50 -0700870const uint8_t DisassociateMessage::kCommand = NL80211_CMD_DISASSOCIATE;
871const char DisassociateMessage::kCommandString[] = "NL80211_CMD_DISASSOCIATE";
872
Wade Guthrie0d438532012-05-18 14:18:50 -0700873const uint8_t DisconnectMessage::kCommand = NL80211_CMD_DISCONNECT;
874const char DisconnectMessage::kCommandString[] = "NL80211_CMD_DISCONNECT";
875
Wade Guthrie0d438532012-05-18 14:18:50 -0700876const uint8_t FrameTxStatusMessage::kCommand = NL80211_CMD_FRAME_TX_STATUS;
877const char FrameTxStatusMessage::kCommandString[] =
878 "NL80211_CMD_FRAME_TX_STATUS";
879
repo sync0efa9f02012-12-28 13:40:20 -0800880const uint8_t GetRegMessage::kCommand = NL80211_CMD_GET_REG;
881const char GetRegMessage::kCommandString[] = "NL80211_CMD_GET_REG";
882
Wade Guthrie0d438532012-05-18 14:18:50 -0700883const uint8_t JoinIbssMessage::kCommand = NL80211_CMD_JOIN_IBSS;
884const char JoinIbssMessage::kCommandString[] = "NL80211_CMD_JOIN_IBSS";
885
Wade Guthrie0d438532012-05-18 14:18:50 -0700886const uint8_t MichaelMicFailureMessage::kCommand =
887 NL80211_CMD_MICHAEL_MIC_FAILURE;
888const char MichaelMicFailureMessage::kCommandString[] =
889 "NL80211_CMD_MICHAEL_MIC_FAILURE";
890
Wade Guthrie0d438532012-05-18 14:18:50 -0700891const uint8_t NewScanResultsMessage::kCommand = NL80211_CMD_NEW_SCAN_RESULTS;
892const char NewScanResultsMessage::kCommandString[] =
893 "NL80211_CMD_NEW_SCAN_RESULTS";
894
Wade Guthrie0d438532012-05-18 14:18:50 -0700895const uint8_t NewStationMessage::kCommand = NL80211_CMD_NEW_STATION;
896const char NewStationMessage::kCommandString[] = "NL80211_CMD_NEW_STATION";
897
Wade Guthrie0d438532012-05-18 14:18:50 -0700898const uint8_t NewWifiMessage::kCommand = NL80211_CMD_NEW_WIPHY;
899const char NewWifiMessage::kCommandString[] = "NL80211_CMD_NEW_WIPHY";
900
Wade Guthrie0d438532012-05-18 14:18:50 -0700901const uint8_t NotifyCqmMessage::kCommand = NL80211_CMD_NOTIFY_CQM;
902const char NotifyCqmMessage::kCommandString[] = "NL80211_CMD_NOTIFY_CQM";
903
Wade Guthrie0d438532012-05-18 14:18:50 -0700904const uint8_t PmksaCandidateMessage::kCommand = NL80211_ATTR_PMKSA_CANDIDATE;
905const char PmksaCandidateMessage::kCommandString[] =
906 "NL80211_ATTR_PMKSA_CANDIDATE";
907
Wade Guthrie0d438532012-05-18 14:18:50 -0700908const uint8_t RegBeaconHintMessage::kCommand = NL80211_CMD_REG_BEACON_HINT;
909const char RegBeaconHintMessage::kCommandString[] =
910 "NL80211_CMD_REG_BEACON_HINT";
911
Wade Guthrie0d438532012-05-18 14:18:50 -0700912const uint8_t RegChangeMessage::kCommand = NL80211_CMD_REG_CHANGE;
913const char RegChangeMessage::kCommandString[] = "NL80211_CMD_REG_CHANGE";
914
Wade Guthrie0d438532012-05-18 14:18:50 -0700915const uint8_t RemainOnChannelMessage::kCommand = NL80211_CMD_REMAIN_ON_CHANNEL;
916const char RemainOnChannelMessage::kCommandString[] =
917 "NL80211_CMD_REMAIN_ON_CHANNEL";
918
Wade Guthrie0d438532012-05-18 14:18:50 -0700919const uint8_t RoamMessage::kCommand = NL80211_CMD_ROAM;
920const char RoamMessage::kCommandString[] = "NL80211_CMD_ROAM";
921
Wade Guthrie0d438532012-05-18 14:18:50 -0700922const uint8_t ScanAbortedMessage::kCommand = NL80211_CMD_SCAN_ABORTED;
923const char ScanAbortedMessage::kCommandString[] = "NL80211_CMD_SCAN_ABORTED";
924
Wade Guthrie71872472013-03-05 10:33:38 -0800925const uint8_t GetScanMessage::kCommand = NL80211_CMD_GET_SCAN;
926const char GetScanMessage::kCommandString[] = "NL80211_CMD_GET_SCAN";
927
Wade Guthrie0d438532012-05-18 14:18:50 -0700928const uint8_t TriggerScanMessage::kCommand = NL80211_CMD_TRIGGER_SCAN;
929const char TriggerScanMessage::kCommandString[] = "NL80211_CMD_TRIGGER_SCAN";
930
Wade Guthrie0d438532012-05-18 14:18:50 -0700931const uint8_t UnknownMessage::kCommand = 0xff;
932const char UnknownMessage::kCommandString[] = "<Unknown Message Type>";
933
Wade Guthrie0d438532012-05-18 14:18:50 -0700934const uint8_t UnprotDeauthenticateMessage::kCommand =
935 NL80211_CMD_UNPROT_DEAUTHENTICATE;
936const char UnprotDeauthenticateMessage::kCommandString[] =
937 "NL80211_CMD_UNPROT_DEAUTHENTICATE";
938
Wade Guthrie0d438532012-05-18 14:18:50 -0700939const uint8_t UnprotDisassociateMessage::kCommand =
940 NL80211_CMD_UNPROT_DISASSOCIATE;
941const char UnprotDisassociateMessage::kCommandString[] =
942 "NL80211_CMD_UNPROT_DISASSOCIATE";
943
Wade Guthrie0d438532012-05-18 14:18:50 -0700944//
945// Factory class.
946//
947
Wade Guthrie71872472013-03-05 10:33:38 -0800948// TODO(wdg): later, each message_type should register its own callback for
949// creating messages. For now, however, this is much easier.
Wade Guthrief48a1952013-03-04 17:33:47 -0800950NetlinkMessage *NetlinkMessageFactory::CreateMessage(nlmsghdr *msg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700951 if (!msg) {
952 LOG(ERROR) << "NULL |msg| parameter";
953 return NULL;
954 }
955
Wade Guthrief48a1952013-03-04 17:33:47 -0800956 scoped_ptr<NetlinkMessage> message;
repo sync0efa9f02012-12-28 13:40:20 -0800957 void *payload = nlmsg_data(msg);
repo syncdc085c82012-12-28 08:54:41 -0800958
Wade Guthrie71872472013-03-05 10:33:38 -0800959 if (msg->nlmsg_type == NoopMessage::kMessageType) {
repo sync0efa9f02012-12-28 13:40:20 -0800960 message.reset(new NoopMessage());
Wade Guthrie71872472013-03-05 10:33:38 -0800961 } else if (msg->nlmsg_type == DoneMessage::kMessageType) {
962 message.reset(new DoneMessage());
963 } else if (msg->nlmsg_type == OverrunMessage::kMessageType) {
964 message.reset(new OverrunMessage());
965 } else if (msg->nlmsg_type == ErrorAckMessage::kMessageType) {
966 message.reset(new ErrorAckMessage());
967 } else if (msg->nlmsg_type == ControlNetlinkMessage::kMessageType) {
968 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);
969
970 switch (gnlh->cmd) {
971 case NewFamilyMessage::kCommand:
972 message.reset(new NewFamilyMessage()); break;
973 case GetFamilyMessage::kCommand:
974 message.reset(new GetFamilyMessage()); break;
975
976 default:
977 message.reset(new UnknownMessage(gnlh->cmd)); break;
repo sync0efa9f02012-12-28 13:40:20 -0800978 }
979 } else {
repo sync0efa9f02012-12-28 13:40:20 -0800980 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);
Wade Guthrie0d438532012-05-18 14:18:50 -0700981
repo sync0efa9f02012-12-28 13:40:20 -0800982 switch (gnlh->cmd) {
983 case AssociateMessage::kCommand:
984 message.reset(new AssociateMessage()); break;
985 case AuthenticateMessage::kCommand:
986 message.reset(new AuthenticateMessage()); break;
987 case CancelRemainOnChannelMessage::kCommand:
988 message.reset(new CancelRemainOnChannelMessage()); break;
989 case ConnectMessage::kCommand:
990 message.reset(new ConnectMessage()); break;
991 case DeauthenticateMessage::kCommand:
992 message.reset(new DeauthenticateMessage()); break;
993 case DeleteStationMessage::kCommand:
994 message.reset(new DeleteStationMessage()); break;
995 case DisassociateMessage::kCommand:
996 message.reset(new DisassociateMessage()); break;
997 case DisconnectMessage::kCommand:
998 message.reset(new DisconnectMessage()); break;
999 case FrameTxStatusMessage::kCommand:
1000 message.reset(new FrameTxStatusMessage()); break;
1001 case GetRegMessage::kCommand:
1002 message.reset(new GetRegMessage()); break;
1003 case JoinIbssMessage::kCommand:
1004 message.reset(new JoinIbssMessage()); break;
1005 case MichaelMicFailureMessage::kCommand:
1006 message.reset(new MichaelMicFailureMessage()); break;
1007 case NewScanResultsMessage::kCommand:
1008 message.reset(new NewScanResultsMessage()); break;
1009 case NewStationMessage::kCommand:
1010 message.reset(new NewStationMessage()); break;
1011 case NewWifiMessage::kCommand:
1012 message.reset(new NewWifiMessage()); break;
1013 case NotifyCqmMessage::kCommand:
1014 message.reset(new NotifyCqmMessage()); break;
1015 case PmksaCandidateMessage::kCommand:
1016 message.reset(new PmksaCandidateMessage()); break;
1017 case RegBeaconHintMessage::kCommand:
1018 message.reset(new RegBeaconHintMessage()); break;
1019 case RegChangeMessage::kCommand:
1020 message.reset(new RegChangeMessage()); break;
1021 case RemainOnChannelMessage::kCommand:
1022 message.reset(new RemainOnChannelMessage()); break;
1023 case RoamMessage::kCommand:
1024 message.reset(new RoamMessage()); break;
1025 case ScanAbortedMessage::kCommand:
1026 message.reset(new ScanAbortedMessage()); break;
1027 case TriggerScanMessage::kCommand:
1028 message.reset(new TriggerScanMessage()); break;
1029 case UnprotDeauthenticateMessage::kCommand:
1030 message.reset(new UnprotDeauthenticateMessage()); break;
1031 case UnprotDisassociateMessage::kCommand:
1032 message.reset(new UnprotDisassociateMessage()); break;
Wade Guthrie0d438532012-05-18 14:18:50 -07001033
repo sync0efa9f02012-12-28 13:40:20 -08001034 default:
1035 message.reset(new UnknownMessage(gnlh->cmd)); break;
1036 }
Wade Guthrie71872472013-03-05 10:33:38 -08001037 }
Wade Guthrie0d438532012-05-18 14:18:50 -07001038
Wade Guthrie71872472013-03-05 10:33:38 -08001039 if (!message->InitFromNlmsg(msg)) {
1040 LOG(ERROR) << "Message did not initialize properly";
1041 return NULL;
Wade Guthrie0d438532012-05-18 14:18:50 -07001042 }
1043
Wade Guthrie0d438532012-05-18 14:18:50 -07001044 return message.release();
1045}
1046
repo syncdc085c82012-12-28 08:54:41 -08001047Nl80211MessageDataCollector *
1048 Nl80211MessageDataCollector::GetInstance() {
Wade Guthrie0d438532012-05-18 14:18:50 -07001049 return g_datacollector.Pointer();
1050}
1051
repo syncdc085c82012-12-28 08:54:41 -08001052Nl80211MessageDataCollector::Nl80211MessageDataCollector() {
Wade Guthrie0d438532012-05-18 14:18:50 -07001053 need_to_print[NL80211_ATTR_PMKSA_CANDIDATE] = true;
1054 need_to_print[NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL] = true;
1055 need_to_print[NL80211_CMD_DEL_STATION] = true;
1056 need_to_print[NL80211_CMD_FRAME_TX_STATUS] = true;
1057 need_to_print[NL80211_CMD_JOIN_IBSS] = true;
1058 need_to_print[NL80211_CMD_MICHAEL_MIC_FAILURE] = true;
1059 need_to_print[NL80211_CMD_NEW_WIPHY] = true;
1060 need_to_print[NL80211_CMD_REG_BEACON_HINT] = true;
1061 need_to_print[NL80211_CMD_REG_CHANGE] = true;
1062 need_to_print[NL80211_CMD_REMAIN_ON_CHANNEL] = true;
1063 need_to_print[NL80211_CMD_ROAM] = true;
1064 need_to_print[NL80211_CMD_SCAN_ABORTED] = true;
1065 need_to_print[NL80211_CMD_UNPROT_DEAUTHENTICATE] = true;
1066 need_to_print[NL80211_CMD_UNPROT_DISASSOCIATE] = true;
1067}
1068
repo syncdc085c82012-12-28 08:54:41 -08001069void Nl80211MessageDataCollector::CollectDebugData(
1070 const Nl80211Message &message, nlmsghdr *msg) {
Wade Guthrie0d438532012-05-18 14:18:50 -07001071 if (!msg) {
1072 LOG(ERROR) << "NULL |msg| parameter";
1073 return;
1074 }
1075
1076 bool doit = false;
1077
1078 map<uint8_t, bool>::const_iterator node;
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001079 node = need_to_print.find(message.command());
Wade Guthrie0d438532012-05-18 14:18:50 -07001080 if (node != need_to_print.end())
1081 doit = node->second;
1082
1083 if (doit) {
Wade Guthried6153612012-08-23 11:36:14 -07001084 LOG(INFO) << "@@const unsigned char "
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001085 << "k" << message.command_string()
Wade Guthried6153612012-08-23 11:36:14 -07001086 << "[] = {";
Wade Guthrie0d438532012-05-18 14:18:50 -07001087
Christopher Wileyefd521f2012-11-07 17:32:46 -08001088 int payload_bytes = nlmsg_datalen(msg);
Wade Guthrie0d438532012-05-18 14:18:50 -07001089
1090 size_t bytes = nlmsg_total_size(payload_bytes);
1091 unsigned char *rawdata = reinterpret_cast<unsigned char *>(msg);
Wade Guthried4977f22012-08-22 12:37:54 -07001092 for (size_t i = 0; i < bytes; ++i) {
Wade Guthried6153612012-08-23 11:36:14 -07001093 LOG(INFO) << " 0x"
Wade Guthrie0d438532012-05-18 14:18:50 -07001094 << std::hex << std::setfill('0') << std::setw(2)
1095 << + rawdata[i] << ",";
1096 }
Wade Guthried6153612012-08-23 11:36:14 -07001097 LOG(INFO) << "};";
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001098 need_to_print[message.command()] = false;
Wade Guthrie0d438532012-05-18 14:18:50 -07001099 }
1100}
1101
1102} // namespace shill.