blob: d9df4200951c70f6bd5fd851e9058ff3ddabd6e0 [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;
81map<uint16_t, string> *Nl80211Message::reason_code_string_ = NULL;
82map<uint16_t, string> *Nl80211Message::status_code_string_ = NULL;
Wade Guthriebdcdaa72013-03-04 12:47:12 -080083uint16_t Nl80211Message::nl80211_message_type_ = kIllegalMessageType;
84
Wade Guthrief48a1952013-03-04 17:33:47 -080085// NetlinkMessage
Wade Guthrie0d438532012-05-18 14:18:50 -070086
Wade Guthrief48a1952013-03-04 17:33:47 -080087ByteString NetlinkMessage::EncodeHeader(uint32_t sequence_number,
88 uint16_t nlmsg_type) {
89 ByteString result;
90 sequence_number_ = sequence_number;
91 if (sequence_number_ == kBroadcastSequenceNumber) {
92 LOG(ERROR) << "Couldn't get a legal sequence number";
93 return result;
94 }
Wade Guthrie0d438532012-05-18 14:18:50 -070095
Wade Guthrief48a1952013-03-04 17:33:47 -080096 // Build netlink header.
97 nlmsghdr header;
98 size_t nlmsghdr_with_pad = NLMSG_ALIGN(sizeof(header));
99 header.nlmsg_len = nlmsghdr_with_pad;
100 header.nlmsg_type = nlmsg_type;
101 header.nlmsg_flags = NLM_F_REQUEST | flags_;
102 header.nlmsg_seq = sequence_number_;
103 header.nlmsg_pid = getpid();
Wade Guthrie0d438532012-05-18 14:18:50 -0700104
Wade Guthrief48a1952013-03-04 17:33:47 -0800105 // Netlink header + pad.
106 result.Append(ByteString(reinterpret_cast<unsigned char *>(&header),
107 sizeof(header)));
108 result.Resize(nlmsghdr_with_pad); // Zero-fill pad space (if any).
109 return result;
110}
111
112bool NetlinkMessage::InitAndStripHeader(ByteString *input) {
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800113 if (!input) {
114 LOG(ERROR) << "NULL input";
115 return false;
116 }
Wade Guthrief48a1952013-03-04 17:33:47 -0800117 if (input->GetLength() < sizeof(nlmsghdr)) {
118 LOG(ERROR) << "Insufficient input to extract nlmsghdr";
119 return false;
120 }
121
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800122 // Read the nlmsghdr.
123 nlmsghdr *header = reinterpret_cast<nlmsghdr *>(input->GetData());
124 message_type_ = header->nlmsg_type;
125 flags_ = header->nlmsg_flags;
126 sequence_number_ = header->nlmsg_seq;
127
128 // Strip the nlmsghdr.
129 input->RemovePrefix(NLMSG_ALIGN(sizeof(struct nlmsghdr)));
Wade Guthrief48a1952013-03-04 17:33:47 -0800130 return true;
131}
132
133bool NetlinkMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
134 if (!const_msg) {
135 LOG(ERROR) << "Null |const_msg| parameter";
136 return false;
137 }
138 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
139 const_msg->nlmsg_len);
140 if (!InitAndStripHeader(&message)) {
141 return false;
142 }
143 return true;
144}
145
146// static
147void NetlinkMessage::PrintBytes(int log_level, const unsigned char *buf,
148 size_t num_bytes) {
149 SLOG(WiFi, log_level) << "Netlink Message -- Examining Bytes";
150 if (!buf) {
151 SLOG(WiFi, log_level) << "<NULL Buffer>";
152 return;
153 }
154
155 if (num_bytes >= sizeof(nlmsghdr)) {
156 const nlmsghdr *header = reinterpret_cast<const nlmsghdr *>(buf);
157 SLOG(WiFi, log_level) << StringPrintf(
158 "len: %02x %02x %02x %02x = %u bytes",
159 buf[0], buf[1], buf[2], buf[3], header->nlmsg_len);
160
161 SLOG(WiFi, log_level) << StringPrintf(
162 "type | flags: %02x %02x %02x %02x - type:%u flags:%s%s%s%s%s",
163 buf[4], buf[5], buf[6], buf[7], header->nlmsg_type,
164 ((header->nlmsg_flags & NLM_F_REQUEST) ? " REQUEST" : ""),
165 ((header->nlmsg_flags & NLM_F_MULTI) ? " MULTI" : ""),
166 ((header->nlmsg_flags & NLM_F_ACK) ? " ACK" : ""),
167 ((header->nlmsg_flags & NLM_F_ECHO) ? " ECHO" : ""),
168 ((header->nlmsg_flags & NLM_F_DUMP_INTR) ? " BAD-SEQ" : ""));
169
170 SLOG(WiFi, log_level) << StringPrintf(
171 "sequence: %02x %02x %02x %02x = %u",
172 buf[8], buf[9], buf[10], buf[11], header->nlmsg_seq);
173 SLOG(WiFi, log_level) << StringPrintf(
174 "pid: %02x %02x %02x %02x = %u",
175 buf[12], buf[13], buf[14], buf[15], header->nlmsg_pid);
176 buf += sizeof(nlmsghdr);
177 num_bytes -= sizeof(nlmsghdr);
178 } else {
179 SLOG(WiFi, log_level) << "Not enough bytes (" << num_bytes
180 << ") for a complete nlmsghdr (requires "
181 << sizeof(nlmsghdr) << ").";
182 }
183
184 while (num_bytes) {
185 string output;
186 size_t bytes_this_row = min(num_bytes, static_cast<size_t>(32));
187 for (size_t i = 0; i < bytes_this_row; ++i) {
188 StringAppendF(&output, " %02x", *buf++);
189 }
190 SLOG(WiFi, log_level) << output;
191 num_bytes -= bytes_this_row;
192 }
193}
194
Wade Guthrie71872472013-03-05 10:33:38 -0800195const uint16_t ErrorAckMessage::kMessageType = NLMSG_ERROR;
196
197bool ErrorAckMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
198 if (!const_msg) {
199 LOG(ERROR) << "Null |const_msg| parameter";
200 return false;
201 }
202 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
203 const_msg->nlmsg_len);
204 if (!InitAndStripHeader(&message)) {
205 return false;
206 }
207
208 // Get the error code from the payload.
209 error_ = *(reinterpret_cast<const uint32_t *>(message.GetConstData()));
210 return true;
211}
212
213ByteString ErrorAckMessage::Encode(uint32_t sequence_number,
214 uint16_t nlmsg_type) {
215 LOG(ERROR) << "We're not supposed to send errors or Acks to the kernel";
216 return ByteString();
217}
218
219string ErrorAckMessage::ToString() const {
220 string output;
221 if (error()) {
222 StringAppendF(&output, "NL80211_ERROR 0x%" PRIx32 ": %s",
223 -error_, strerror(-error_));
224 } else {
225 StringAppendF(&output, "ACK");
226 }
227 return output;
228}
229
230void ErrorAckMessage::Print(int log_level) const {
231 SLOG(WiFi, log_level) << ToString();
232}
233
234const uint16_t NoopMessage::kMessageType = NLMSG_NOOP;
235
236ByteString NoopMessage::Encode(uint32_t sequence_number, uint16_t nlmsg_type) {
237 LOG(ERROR) << "We're not supposed to send NOOP to the kernel";
238 return ByteString();
239}
240
241void NoopMessage::Print(int log_level) const {
242 SLOG(WiFi, log_level) << ToString();
243}
244
245const uint16_t DoneMessage::kMessageType = NLMSG_DONE;
246
247ByteString DoneMessage::Encode(uint32_t sequence_number, uint16_t nlmsg_type) {
248 LOG(ERROR)
249 << "We're not supposed to send Done messages (are we?) to the kernel";
250 return ByteString();
251}
252
253void DoneMessage::Print(int log_level) const {
254 SLOG(WiFi, log_level) << ToString();
255}
256
257const uint16_t OverrunMessage::kMessageType = NLMSG_OVERRUN;
258
259ByteString OverrunMessage::Encode(uint32_t sequence_number,
260 uint16_t nlmsg_type) {
261 LOG(ERROR) << "We're not supposed to send Overruns to the kernel";
262 return ByteString();
263}
264
265void OverrunMessage::Print(int log_level) const {
266 SLOG(WiFi, log_level) << ToString();
267}
268
Wade Guthrief48a1952013-03-04 17:33:47 -0800269// GenericNetlinkMessage
270
271ByteString GenericNetlinkMessage::EncodeHeader(uint32_t sequence_number,
272 uint16_t nlmsg_type) {
273 // Build nlmsghdr.
274 ByteString result(NetlinkMessage::EncodeHeader(sequence_number, nlmsg_type));
275 if (result.GetLength() == 0) {
276 LOG(ERROR) << "Couldn't encode message header.";
277 return result;
278 }
279
280 // Build and append the genl message header.
281 genlmsghdr genl_header;
282 genl_header.cmd = command();
283 genl_header.version = 1;
284 genl_header.reserved = 0;
285
286 ByteString genl_header_string(
287 reinterpret_cast<unsigned char *>(&genl_header), sizeof(genl_header));
288 size_t genlmsghdr_with_pad = NLMSG_ALIGN(sizeof(genl_header));
289 genl_header_string.Resize(genlmsghdr_with_pad); // Zero-fill.
290
291 nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
292 pheader->nlmsg_len += genlmsghdr_with_pad;
293 result.Append(genl_header_string);
294 return result;
295}
296
297ByteString GenericNetlinkMessage::Encode(uint32_t sequence_number,
298 uint16_t nlmsg_type) {
299 ByteString result(EncodeHeader(sequence_number, nlmsg_type));
300 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
repo sync0efa9f02012-12-28 13:40:20 -0800347bool Nl80211Message::InitFromNlmsg(const nlmsghdr *const_msg) {
348 if (!const_msg) {
349 LOG(ERROR) << "Null |msg| parameter";
Wade Guthrie0d438532012-05-18 14:18:50 -0700350 return false;
351 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800352 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
353 const_msg->nlmsg_len);
Wade Guthrie0d438532012-05-18 14:18:50 -0700354
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800355 if (!InitAndStripHeader(&message)) {
356 return false;
357 }
repo sync0efa9f02012-12-28 13:40:20 -0800358
359 // Attributes.
360 // Parse the attributes from the nl message payload into the 'tb' array.
361 nlattr *tb[NL80211_ATTR_MAX + 1];
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800362 nla_parse(tb, NL80211_ATTR_MAX,
363 reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
364 NULL);
repo sync0efa9f02012-12-28 13:40:20 -0800365
Wade Guthrie0d438532012-05-18 14:18:50 -0700366 for (int i = 0; i < NL80211_ATTR_MAX + 1; ++i) {
367 if (tb[i]) {
repo sync0efa9f02012-12-28 13:40:20 -0800368 // TODO(wdg): When Nl80211Messages instantiate their own attributes,
369 // this call should, instead, call |SetAttributeFromNlAttr|.
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800370 attributes_->CreateAndInitAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800371 i, tb[i], Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
Wade Guthrie0d438532012-05-18 14:18:50 -0700372 }
373 }
374
375 // Convert integer values provided by libnl (for example, from the
376 // NL80211_ATTR_STATUS_CODE or NL80211_ATTR_REASON_CODE attribute) into
377 // strings describing the status.
Wade Guthried4977f22012-08-22 12:37:54 -0700378 if (!reason_code_string_) {
379 reason_code_string_ = new map<uint16_t, string>;
380 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecified] =
381 "Unspecified reason";
382 (*reason_code_string_)[
383 IEEE_80211::kReasonCodePreviousAuthenticationInvalid] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700384 "Previous authentication no longer valid";
Wade Guthried4977f22012-08-22 12:37:54 -0700385 (*reason_code_string_)[IEEE_80211::kReasonCodeSenderHasLeft] =
386 "Deauthentcated because sending STA is leaving (or has left) IBSS or "
387 "ESS";
388 (*reason_code_string_)[IEEE_80211::kReasonCodeInactivity] =
389 "Disassociated due to inactivity";
390 (*reason_code_string_)[IEEE_80211::kReasonCodeTooManySTAs] =
391 "Disassociated because AP is unable to handle all currently associated "
392 "STAs";
393 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAuthenticated] =
394 "Class 2 frame received from nonauthenticated STA";
395 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAssociated] =
396 "Class 3 frame received from nonassociated STA";
397 (*reason_code_string_)[IEEE_80211::kReasonCodeDisassociatedHasLeft] =
398 "Disassociated because sending STA is leaving (or has left) BSS";
399 (*reason_code_string_)[
400 IEEE_80211::kReasonCodeReassociationNotAuthenticated] =
401 "STA requesting (re)association is not authenticated with responding "
402 "STA";
403 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptablePowerCapability] =
404 "Disassociated because the information in the Power Capability "
405 "element is unacceptable";
406 (*reason_code_string_)[
407 IEEE_80211::kReasonCodeUnacceptableSupportedChannelInfo] =
408 "Disassociated because the information in the Supported Channels "
409 "element is unacceptable";
410 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidInfoElement] =
411 "Invalid information element, i.e., an information element defined in "
412 "this standard for which the content does not meet the specifications "
413 "in Clause 7";
414 (*reason_code_string_)[IEEE_80211::kReasonCodeMICFailure] =
415 "Message integrity code (MIC) failure";
416 (*reason_code_string_)[IEEE_80211::kReasonCode4WayTimeout] =
417 "4-Way Handshake timeout";
418 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupKeyHandshakeTimeout] =
419 "Group Key Handshake timeout";
420 (*reason_code_string_)[IEEE_80211::kReasonCodeDifferenIE] =
421 "Information element in 4-Way Handshake different from "
422 "(Re)Association Request/Probe Response/Beacon frame";
423 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupCipherInvalid] =
424 "Invalid group cipher";
425 (*reason_code_string_)[IEEE_80211::kReasonCodePairwiseCipherInvalid] =
426 "Invalid pairwise cipher";
427 (*reason_code_string_)[IEEE_80211::kReasonCodeAkmpInvalid] =
428 "Invalid AKMP";
429 (*reason_code_string_)[IEEE_80211::kReasonCodeUnsupportedRsnIeVersion] =
430 "Unsupported RSN information element version";
431 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidRsnIeCaps] =
432 "Invalid RSN information element capabilities";
433 (*reason_code_string_)[IEEE_80211::kReasonCode8021XAuth] =
434 "IEEE 802.1X authentication failed";
435 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteRejected] =
436 "Cipher suite rejected because of the security policy";
437 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecifiedQoS] =
438 "Disassociated for unspecified, QoS-related reason";
439 (*reason_code_string_)[IEEE_80211::kReasonCodeQoSBandwidth] =
440 "Disassociated because QoS AP lacks sufficient bandwidth for this "
441 "QoS STA";
442 (*reason_code_string_)[IEEE_80211::kReasonCodeiPoorConditions] =
443 "Disassociated because excessive number of frames need to be "
444 "acknowledged, but are not acknowledged due to AP transmissions "
445 "and/or poor channel conditions";
446 (*reason_code_string_)[IEEE_80211::kReasonCodeOutsideTxop] =
447 "Disassociated because STA is transmitting outside the limits of its "
448 "TXOPs";
449 (*reason_code_string_)[IEEE_80211::kReasonCodeStaLeaving] =
450 "Requested from peer STA as the STA is leaving the BSS (or resetting)";
451 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptableMechanism] =
452 "Requested from peer STA as it does not want to use the mechanism";
453 (*reason_code_string_)[IEEE_80211::kReasonCodeSetupRequired] =
454 "Requested from peer STA as the STA received frames using the "
455 "mechanism for which a setup is required";
456 (*reason_code_string_)[IEEE_80211::kReasonCodeTimeout] =
457 "Requested from peer STA due to timeout";
458 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteNotSupported] =
459 "Peer STA does not support the requested cipher suite";
460 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalid] = "<INVALID REASON>";
461 }
462
463 if (!status_code_string_) {
464 status_code_string_ = new map<uint16_t, string>;
465 (*status_code_string_)[IEEE_80211::kStatusCodeSuccessful] = "Successful";
466 (*status_code_string_)[IEEE_80211::kStatusCodeFailure] =
467 "Unspecified failure";
468 (*status_code_string_)[IEEE_80211::kStatusCodeAllCapabilitiesNotSupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700469 "Cannot support all requested capabilities in the capability "
470 "information field";
Wade Guthried4977f22012-08-22 12:37:54 -0700471 (*status_code_string_)[IEEE_80211::kStatusCodeCantConfirmAssociation] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700472 "Reassociation denied due to inability to confirm that association "
473 "exists";
Wade Guthried4977f22012-08-22 12:37:54 -0700474 (*status_code_string_)[IEEE_80211::kStatusCodeAssociationDenied] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700475 "Association denied due to reason outside the scope of this standard";
Wade Guthried4977f22012-08-22 12:37:54 -0700476 (*status_code_string_)[
477 IEEE_80211::kStatusCodeAuthenticationUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700478 "Responding station does not support the specified authentication "
479 "algorithm";
Wade Guthried4977f22012-08-22 12:37:54 -0700480 (*status_code_string_)[IEEE_80211::kStatusCodeOutOfSequence] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700481 "Received an authentication frame with authentication transaction "
482 "sequence number out of expected sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700483 (*status_code_string_)[IEEE_80211::kStatusCodeChallengeFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700484 "Authentication rejected because of challenge failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700485 (*status_code_string_)[IEEE_80211::kStatusCodeFrameTimeout] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700486 "Authentication rejected due to timeout waiting for next frame in "
487 "sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700488 (*status_code_string_)[IEEE_80211::kStatusCodeMaxSta] =
489 "Association denied because AP is unable to handle additional "
490 "associated STA";
491 (*status_code_string_)[IEEE_80211::kStatusCodeDataRateUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700492 "Association denied due to requesting station not supporting all of "
493 "the data rates in the BSSBasicRateSet parameter";
Wade Guthried4977f22012-08-22 12:37:54 -0700494 (*status_code_string_)[IEEE_80211::kStatusCodeShortPreambleUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700495 "Association denied due to requesting station not supporting the "
496 "short preamble option";
Wade Guthried4977f22012-08-22 12:37:54 -0700497 (*status_code_string_)[IEEE_80211::kStatusCodePbccUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700498 "Association denied due to requesting station not supporting the PBCC "
499 "modulation option";
Wade Guthried4977f22012-08-22 12:37:54 -0700500 (*status_code_string_)[
501 IEEE_80211::kStatusCodeChannelAgilityUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700502 "Association denied due to requesting station not supporting the "
503 "channel agility option";
Wade Guthried4977f22012-08-22 12:37:54 -0700504 (*status_code_string_)[IEEE_80211::kStatusCodeNeedSpectrumManagement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700505 "Association request rejected because Spectrum Management capability "
506 "is required";
Wade Guthried4977f22012-08-22 12:37:54 -0700507 (*status_code_string_)[
508 IEEE_80211::kStatusCodeUnacceptablePowerCapability] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700509 "Association request rejected because the information in the Power "
510 "Capability element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700511 (*status_code_string_)[
512 IEEE_80211::kStatusCodeUnacceptableSupportedChannelInfo] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700513 "Association request rejected because the information in the "
514 "Supported Channels element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700515 (*status_code_string_)[IEEE_80211::kStatusCodeShortTimeSlotRequired] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700516 "Association request rejected due to requesting station not "
Wade Guthried4977f22012-08-22 12:37:54 -0700517 "supporting the Short Slot Time option";
518 (*status_code_string_)[IEEE_80211::kStatusCodeDssOfdmRequired] =
519 "Association request rejected due to requesting station not "
520 "supporting the DSSS-OFDM option";
521 (*status_code_string_)[IEEE_80211::kStatusCodeQosFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700522 "Unspecified, QoS related failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700523 (*status_code_string_)[
524 IEEE_80211::kStatusCodeInsufficientBandwithForQsta] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700525 "Association denied due to QAP having insufficient bandwidth to handle "
526 "another QSTA";
Wade Guthried4977f22012-08-22 12:37:54 -0700527 (*status_code_string_)[IEEE_80211::kStatusCodePoorConditions] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700528 "Association denied due to poor channel conditions";
Wade Guthried4977f22012-08-22 12:37:54 -0700529 (*status_code_string_)[IEEE_80211::kStatusCodeQosNotSupported] =
530 "Association (with QoS BSS) denied due to requesting station not "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700531 "supporting the QoS facility";
Wade Guthried4977f22012-08-22 12:37:54 -0700532 (*status_code_string_)[IEEE_80211::kStatusCodeDeclined] =
533 "The request has been declined";
534 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidParameterValues] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700535 "The request has not been successful as one or more parameters have "
536 "invalid values";
Wade Guthried4977f22012-08-22 12:37:54 -0700537 (*status_code_string_)[IEEE_80211::kStatusCodeCannotBeHonored] =
538 "The TS has not been created because the request cannot be honored. "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700539 "However, a suggested Tspec is provided so that the initiating QSTA "
540 "may attempt to send another TS with the suggested changes to the "
541 "TSpec";
Wade Guthried4977f22012-08-22 12:37:54 -0700542 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidInfoElement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700543 "Invalid Information Element";
Wade Guthried4977f22012-08-22 12:37:54 -0700544 (*status_code_string_)[IEEE_80211::kStatusCodeGroupCipherInvalid] =
545 "Invalid Group Cipher";
546 (*status_code_string_)[IEEE_80211::kStatusCodePairwiseCipherInvalid] =
547 "Invalid Pairwise Cipher";
548 (*status_code_string_)[IEEE_80211::kStatusCodeAkmpInvalid] = "Invalid AKMP";
549 (*status_code_string_)[IEEE_80211::kStatusCodeUnsupportedRsnIeVersion] =
550 "Unsupported RSN Information Element version";
551 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidRsnIeCaps] =
552 "Invalid RSN Information Element Capabilities";
553 (*status_code_string_)[IEEE_80211::kStatusCodeCipherSuiteRejected] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700554 "Cipher suite is rejected per security policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700555 (*status_code_string_)[IEEE_80211::kStatusCodeTsDelayNotMet] =
556 "The TS has not been created. However, the HC may be capable of "
557 "creating a TS, in response to a request, after the time indicated in "
558 "the TS Delay element";
559 (*status_code_string_)[IEEE_80211::kStatusCodeDirectLinkIllegal] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700560 "Direct link is not allowed in the BSS by policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700561 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInBss] =
562 "Destination STA is not present within this BSS";
563 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInQsta] =
564 "The destination STA is not a QoS STA";
565 (*status_code_string_)[IEEE_80211::kStatusCodeExcessiveListenInterval] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700566 "Association denied because Listen Interval is too large";
Wade Guthried4977f22012-08-22 12:37:54 -0700567 (*status_code_string_)[IEEE_80211::kStatusCodeInvalid] = "<INVALID STATUS>";
Wade Guthrie0d438532012-05-18 14:18:50 -0700568 }
569
570 return true;
571}
572
Wade Guthrie8e278612013-02-26 10:32:34 -0800573
Wade Guthrie0d438532012-05-18 14:18:50 -0700574// Helper function to provide a string for a MAC address.
Wade Guthrie68da97c2013-02-26 13:09:35 -0800575bool Nl80211Message::GetMacAttributeString(int id, string *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700576 if (!value) {
577 LOG(ERROR) << "Null |value| parameter";
578 return false;
579 }
580
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800581 ByteString data;
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800582 if (!const_attributes()->GetRawAttributeValue(id, &data)) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700583 value->assign(kBogusMacAddress);
584 return false;
585 }
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800586 value->assign(StringFromMacAddress(data.GetConstData()));
Wade Guthrie0d438532012-05-18 14:18:50 -0700587
588 return true;
589}
590
591// Helper function to provide a string for NL80211_ATTR_SCAN_FREQUENCIES.
repo syncdc085c82012-12-28 08:54:41 -0800592bool Nl80211Message::GetScanFrequenciesAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800593 int id, vector<uint32_t> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700594 if (!value) {
595 LOG(ERROR) << "Null |value| parameter";
596 return false;
597 }
598
599 value->clear();
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800600
601 AttributeListConstRefPtr frequency_list;
602 if (!const_attributes()->ConstGetNestedAttributeList(
603 NL80211_ATTR_SCAN_FREQUENCIES, &frequency_list) || !frequency_list) {
604 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_FREQUENCIES attribute";
repo syncd316eb72012-12-10 15:48:47 -0800605 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800606 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700607
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800608 // Assume IDs for the nested attribute array are linear starting from 1.
609 // Currently, that is enforced in the input to the nested attribute.
610 uint32_t freq;
611 int i = 1;
612 while (frequency_list->GetU32AttributeValue(i, &freq)) {
613 value->push_back(freq);
614 ++i;
Wade Guthrie0d438532012-05-18 14:18:50 -0700615 }
repo syncd316eb72012-12-10 15:48:47 -0800616 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700617}
618
619// Helper function to provide a string for NL80211_ATTR_SCAN_SSIDS.
repo syncdc085c82012-12-28 08:54:41 -0800620bool Nl80211Message::GetScanSsidsAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800621 int id, vector<string> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700622 if (!value) {
623 LOG(ERROR) << "Null |value| parameter";
624 return false;
625 }
626
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800627 AttributeListConstRefPtr ssid_list;
628 if (!const_attributes()->ConstGetNestedAttributeList(
629 NL80211_ATTR_SCAN_SSIDS, &ssid_list) || !ssid_list) {
630 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_SSIDS attribute";
repo sync90ee0fa2012-12-18 10:08:08 -0800631 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800632 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700633
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800634 // Assume IDs for the nested attribute array are linear starting from 1.
635 // Currently, that is enforced in the input to the nested attribute.
636 string ssid;
637 int i = 1;
638 while (ssid_list->GetStringAttributeValue(i, &ssid)) {
639 value->push_back(ssid);
640 ++i;
Wade Guthrie0d438532012-05-18 14:18:50 -0700641 }
repo sync90ee0fa2012-12-18 10:08:08 -0800642 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700643}
644
Wade Guthrie0d438532012-05-18 14:18:50 -0700645// static
repo syncdc085c82012-12-28 08:54:41 -0800646string Nl80211Message::StringFromMacAddress(const uint8_t *arg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700647 string output;
648
649 if (!arg) {
650 output = kBogusMacAddress;
651 LOG(ERROR) << "|arg| parameter is NULL.";
652 } else {
653 StringAppendF(&output, "%02x", arg[0]);
654
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800655 for (unsigned int i = 1; i < kEthernetAddressBytes ; ++i) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700656 StringAppendF(&output, ":%02x", arg[i]);
657 }
658 }
659 return output;
660}
661
662// static
repo syncdc085c82012-12-28 08:54:41 -0800663string Nl80211Message::StringFromReason(uint16_t status) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700664 map<uint16_t, string>::const_iterator match;
Wade Guthried4977f22012-08-22 12:37:54 -0700665 match = reason_code_string_->find(status);
666 if (match == reason_code_string_->end()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700667 string output;
Wade Guthried4977f22012-08-22 12:37:54 -0700668 if (status < IEEE_80211::kReasonCodeMax) {
669 StringAppendF(&output, "<Reserved Reason:%u>", status);
670 } else {
671 StringAppendF(&output, "<Unknown Reason:%u>", status);
672 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700673 return output;
674 }
675 return match->second;
676}
677
Wade Guthried4977f22012-08-22 12:37:54 -0700678// static
repo syncdc085c82012-12-28 08:54:41 -0800679string Nl80211Message::StringFromStatus(uint16_t status) {
Wade Guthried4977f22012-08-22 12:37:54 -0700680 map<uint16_t, string>::const_iterator match;
681 match = status_code_string_->find(status);
682 if (match == status_code_string_->end()) {
683 string output;
684 if (status < IEEE_80211::kStatusCodeMax) {
685 StringAppendF(&output, "<Reserved Status:%u>", status);
686 } else {
687 StringAppendF(&output, "<Unknown Status:%u>", status);
688 }
689 return output;
690 }
691 return match->second;
692}
693
repo syncdc085c82012-12-28 08:54:41 -0800694
Wade Guthrie71872472013-03-05 10:33:38 -0800695// Control Message
696
697const uint16_t ControlNetlinkMessage::kMessageType = GENL_ID_CTRL;
698
699bool ControlNetlinkMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
700 if (!const_msg) {
701 LOG(ERROR) << "Null |msg| parameter";
702 return false;
703 }
704 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
705 const_msg->nlmsg_len);
706
707 if (!InitAndStripHeader(&message)) {
708 return false;
709 }
710
711 // Attributes.
712 // Parse the attributes from the nl message payload into the 'tb' array.
713 nlattr *tb[CTRL_ATTR_MAX + 1];
714 nla_parse(tb, CTRL_ATTR_MAX,
715 reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
716 NULL);
717
718 for (int i = 0; i < CTRL_ATTR_MAX + 1; ++i) {
719 if (tb[i]) {
720 // TODO(wdg): When Nl80211Messages instantiate their own attributes,
721 // this call should, instead, call |SetAttributeFromNlAttr|.
722 attributes_->CreateAndInitAttribute(
723 i, tb[i], Bind(&NetlinkAttribute::NewControlAttributeFromId));
724 }
725 }
726 return true;
727}
728
729// Specific Control types.
730
731const uint8_t NewFamilyMessage::kCommand = CTRL_CMD_NEWFAMILY;
732const char NewFamilyMessage::kCommandString[] = "CTRL_CMD_NEWFAMILY";
733
734const uint8_t GetFamilyMessage::kCommand = CTRL_CMD_GETFAMILY;
735const char GetFamilyMessage::kCommandString[] = "CTRL_CMD_GETFAMILY";
736
737// Nl80211Frame
738
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800739Nl80211Frame::Nl80211Frame(const ByteString &raw_frame)
Wade Guthried4977f22012-08-22 12:37:54 -0700740 : frame_type_(kIllegalFrameType), reason_(UINT16_MAX), status_(UINT16_MAX),
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800741 frame_(raw_frame) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700742 const IEEE_80211::ieee80211_frame *frame =
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800743 reinterpret_cast<const IEEE_80211::ieee80211_frame *>(
744 frame_.GetConstData());
Wade Guthrie0d438532012-05-18 14:18:50 -0700745
746 // Now, let's populate the other stuff.
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800747 if (frame_.GetLength() >= kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700748 mac_from_ =
repo syncdc085c82012-12-28 08:54:41 -0800749 Nl80211Message::StringFromMacAddress(&frame->destination_mac[0]);
750 mac_to_ = Nl80211Message::StringFromMacAddress(&frame->source_mac[0]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700751 frame_type_ = frame->frame_control & kFrameTypeMask;
752
753 switch (frame_type_) {
754 case kAssocResponseFrameType:
755 case kReassocResponseFrameType:
756 status_ = le16toh(frame->u.associate_response.status_code);
757 break;
758
759 case kAuthFrameType:
760 status_ = le16toh(frame->u.authentiate_message.status_code);
761 break;
762
763 case kDisassocFrameType:
764 case kDeauthFrameType:
Wade Guthried4977f22012-08-22 12:37:54 -0700765 reason_ = le16toh(frame->u.deauthentiate_message.reason_code);
Wade Guthrie0d438532012-05-18 14:18:50 -0700766 break;
767
768 default:
769 break;
770 }
771 }
772}
773
Wade Guthried4977f22012-08-22 12:37:54 -0700774bool Nl80211Frame::ToString(string *output) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700775 if (!output) {
776 LOG(ERROR) << "NULL |output|";
777 return false;
778 }
779
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800780 if (frame_.IsEmpty()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700781 output->append(" [no frame]");
782 return true;
783 }
784
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800785 if (frame_.GetLength() < kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700786 output->append(" [invalid frame: ");
787 } else {
788 StringAppendF(output, " %s -> %s", mac_from_.c_str(), mac_to_.c_str());
789
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800790 switch (frame_.GetConstData()[0] & kFrameTypeMask) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700791 case kAssocResponseFrameType:
792 StringAppendF(output, "; AssocResponse status: %u: %s",
793 status_,
repo syncdc085c82012-12-28 08:54:41 -0800794 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700795 break;
796 case kReassocResponseFrameType:
797 StringAppendF(output, "; ReassocResponse status: %u: %s",
798 status_,
repo syncdc085c82012-12-28 08:54:41 -0800799 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700800 break;
801 case kAuthFrameType:
802 StringAppendF(output, "; Auth status: %u: %s",
803 status_,
repo syncdc085c82012-12-28 08:54:41 -0800804 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700805 break;
806
807 case kDisassocFrameType:
808 StringAppendF(output, "; Disassoc reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700809 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800810 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700811 break;
812 case kDeauthFrameType:
813 StringAppendF(output, "; Deauth reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700814 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800815 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700816 break;
817
818 default:
819 break;
820 }
821 output->append(" [frame: ");
822 }
823
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800824 const unsigned char *frame = frame_.GetConstData();
825 for (size_t i = 0; i < frame_.GetLength(); ++i) {
826 StringAppendF(output, "%02x, ", frame[i]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700827 }
828 output->append("]");
829
830 return true;
831}
832
Wade Guthried4977f22012-08-22 12:37:54 -0700833bool Nl80211Frame::IsEqual(const Nl80211Frame &other) const {
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800834 return frame_.Equals(other.frame_);
Wade Guthrie0d438532012-05-18 14:18:50 -0700835}
836
Wade Guthried4977f22012-08-22 12:37:54 -0700837
Wade Guthrie0d438532012-05-18 14:18:50 -0700838//
repo syncdc085c82012-12-28 08:54:41 -0800839// Specific Nl80211Message types.
Wade Guthrie0d438532012-05-18 14:18:50 -0700840//
841
842const uint8_t AssociateMessage::kCommand = NL80211_CMD_ASSOCIATE;
843const char AssociateMessage::kCommandString[] = "NL80211_CMD_ASSOCIATE";
844
Wade Guthrie0d438532012-05-18 14:18:50 -0700845const uint8_t AuthenticateMessage::kCommand = NL80211_CMD_AUTHENTICATE;
846const char AuthenticateMessage::kCommandString[] = "NL80211_CMD_AUTHENTICATE";
847
Wade Guthrie0d438532012-05-18 14:18:50 -0700848const uint8_t CancelRemainOnChannelMessage::kCommand =
849 NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL;
850const char CancelRemainOnChannelMessage::kCommandString[] =
851 "NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL";
852
Wade Guthrie0d438532012-05-18 14:18:50 -0700853const uint8_t ConnectMessage::kCommand = NL80211_CMD_CONNECT;
854const char ConnectMessage::kCommandString[] = "NL80211_CMD_CONNECT";
855
Wade Guthrie0d438532012-05-18 14:18:50 -0700856const uint8_t DeauthenticateMessage::kCommand = NL80211_CMD_DEAUTHENTICATE;
857const char DeauthenticateMessage::kCommandString[] =
858 "NL80211_CMD_DEAUTHENTICATE";
859
Wade Guthrie0d438532012-05-18 14:18:50 -0700860const uint8_t DeleteStationMessage::kCommand = NL80211_CMD_DEL_STATION;
861const char DeleteStationMessage::kCommandString[] = "NL80211_CMD_DEL_STATION";
862
Wade Guthrie0d438532012-05-18 14:18:50 -0700863const uint8_t DisassociateMessage::kCommand = NL80211_CMD_DISASSOCIATE;
864const char DisassociateMessage::kCommandString[] = "NL80211_CMD_DISASSOCIATE";
865
Wade Guthrie0d438532012-05-18 14:18:50 -0700866const uint8_t DisconnectMessage::kCommand = NL80211_CMD_DISCONNECT;
867const char DisconnectMessage::kCommandString[] = "NL80211_CMD_DISCONNECT";
868
Wade Guthrie0d438532012-05-18 14:18:50 -0700869const uint8_t FrameTxStatusMessage::kCommand = NL80211_CMD_FRAME_TX_STATUS;
870const char FrameTxStatusMessage::kCommandString[] =
871 "NL80211_CMD_FRAME_TX_STATUS";
872
repo sync0efa9f02012-12-28 13:40:20 -0800873const uint8_t GetRegMessage::kCommand = NL80211_CMD_GET_REG;
874const char GetRegMessage::kCommandString[] = "NL80211_CMD_GET_REG";
875
Wade Guthrie0d438532012-05-18 14:18:50 -0700876const uint8_t JoinIbssMessage::kCommand = NL80211_CMD_JOIN_IBSS;
877const char JoinIbssMessage::kCommandString[] = "NL80211_CMD_JOIN_IBSS";
878
Wade Guthrie0d438532012-05-18 14:18:50 -0700879const uint8_t MichaelMicFailureMessage::kCommand =
880 NL80211_CMD_MICHAEL_MIC_FAILURE;
881const char MichaelMicFailureMessage::kCommandString[] =
882 "NL80211_CMD_MICHAEL_MIC_FAILURE";
883
Wade Guthrie0d438532012-05-18 14:18:50 -0700884const uint8_t NewScanResultsMessage::kCommand = NL80211_CMD_NEW_SCAN_RESULTS;
885const char NewScanResultsMessage::kCommandString[] =
886 "NL80211_CMD_NEW_SCAN_RESULTS";
887
Wade Guthrie0d438532012-05-18 14:18:50 -0700888const uint8_t NewStationMessage::kCommand = NL80211_CMD_NEW_STATION;
889const char NewStationMessage::kCommandString[] = "NL80211_CMD_NEW_STATION";
890
Wade Guthrie0d438532012-05-18 14:18:50 -0700891const uint8_t NewWifiMessage::kCommand = NL80211_CMD_NEW_WIPHY;
892const char NewWifiMessage::kCommandString[] = "NL80211_CMD_NEW_WIPHY";
893
Wade Guthrie0d438532012-05-18 14:18:50 -0700894const uint8_t NotifyCqmMessage::kCommand = NL80211_CMD_NOTIFY_CQM;
895const char NotifyCqmMessage::kCommandString[] = "NL80211_CMD_NOTIFY_CQM";
896
Wade Guthrie0d438532012-05-18 14:18:50 -0700897const uint8_t PmksaCandidateMessage::kCommand = NL80211_ATTR_PMKSA_CANDIDATE;
898const char PmksaCandidateMessage::kCommandString[] =
899 "NL80211_ATTR_PMKSA_CANDIDATE";
900
Wade Guthrie0d438532012-05-18 14:18:50 -0700901const uint8_t RegBeaconHintMessage::kCommand = NL80211_CMD_REG_BEACON_HINT;
902const char RegBeaconHintMessage::kCommandString[] =
903 "NL80211_CMD_REG_BEACON_HINT";
904
Wade Guthrie0d438532012-05-18 14:18:50 -0700905const uint8_t RegChangeMessage::kCommand = NL80211_CMD_REG_CHANGE;
906const char RegChangeMessage::kCommandString[] = "NL80211_CMD_REG_CHANGE";
907
Wade Guthrie0d438532012-05-18 14:18:50 -0700908const uint8_t RemainOnChannelMessage::kCommand = NL80211_CMD_REMAIN_ON_CHANNEL;
909const char RemainOnChannelMessage::kCommandString[] =
910 "NL80211_CMD_REMAIN_ON_CHANNEL";
911
Wade Guthrie0d438532012-05-18 14:18:50 -0700912const uint8_t RoamMessage::kCommand = NL80211_CMD_ROAM;
913const char RoamMessage::kCommandString[] = "NL80211_CMD_ROAM";
914
Wade Guthrie0d438532012-05-18 14:18:50 -0700915const uint8_t ScanAbortedMessage::kCommand = NL80211_CMD_SCAN_ABORTED;
916const char ScanAbortedMessage::kCommandString[] = "NL80211_CMD_SCAN_ABORTED";
917
Wade Guthrie71872472013-03-05 10:33:38 -0800918const uint8_t GetScanMessage::kCommand = NL80211_CMD_GET_SCAN;
919const char GetScanMessage::kCommandString[] = "NL80211_CMD_GET_SCAN";
920
Wade Guthrie0d438532012-05-18 14:18:50 -0700921const uint8_t TriggerScanMessage::kCommand = NL80211_CMD_TRIGGER_SCAN;
922const char TriggerScanMessage::kCommandString[] = "NL80211_CMD_TRIGGER_SCAN";
923
Wade Guthrie0d438532012-05-18 14:18:50 -0700924const uint8_t UnknownMessage::kCommand = 0xff;
925const char UnknownMessage::kCommandString[] = "<Unknown Message Type>";
926
Wade Guthrie0d438532012-05-18 14:18:50 -0700927const uint8_t UnprotDeauthenticateMessage::kCommand =
928 NL80211_CMD_UNPROT_DEAUTHENTICATE;
929const char UnprotDeauthenticateMessage::kCommandString[] =
930 "NL80211_CMD_UNPROT_DEAUTHENTICATE";
931
Wade Guthrie0d438532012-05-18 14:18:50 -0700932const uint8_t UnprotDisassociateMessage::kCommand =
933 NL80211_CMD_UNPROT_DISASSOCIATE;
934const char UnprotDisassociateMessage::kCommandString[] =
935 "NL80211_CMD_UNPROT_DISASSOCIATE";
936
Wade Guthrie0d438532012-05-18 14:18:50 -0700937//
938// Factory class.
939//
940
Wade Guthrie71872472013-03-05 10:33:38 -0800941// TODO(wdg): later, each message_type should register its own callback for
942// creating messages. For now, however, this is much easier.
Wade Guthrief48a1952013-03-04 17:33:47 -0800943NetlinkMessage *NetlinkMessageFactory::CreateMessage(nlmsghdr *msg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700944 if (!msg) {
945 LOG(ERROR) << "NULL |msg| parameter";
946 return NULL;
947 }
948
Wade Guthrief48a1952013-03-04 17:33:47 -0800949 scoped_ptr<NetlinkMessage> message;
repo sync0efa9f02012-12-28 13:40:20 -0800950 void *payload = nlmsg_data(msg);
repo syncdc085c82012-12-28 08:54:41 -0800951
Wade Guthrie71872472013-03-05 10:33:38 -0800952 if (msg->nlmsg_type == NoopMessage::kMessageType) {
repo sync0efa9f02012-12-28 13:40:20 -0800953 message.reset(new NoopMessage());
Wade Guthrie71872472013-03-05 10:33:38 -0800954 } else if (msg->nlmsg_type == DoneMessage::kMessageType) {
955 message.reset(new DoneMessage());
956 } else if (msg->nlmsg_type == OverrunMessage::kMessageType) {
957 message.reset(new OverrunMessage());
958 } else if (msg->nlmsg_type == ErrorAckMessage::kMessageType) {
959 message.reset(new ErrorAckMessage());
960 } else if (msg->nlmsg_type == ControlNetlinkMessage::kMessageType) {
961 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);
962
963 switch (gnlh->cmd) {
964 case NewFamilyMessage::kCommand:
965 message.reset(new NewFamilyMessage()); break;
966 case GetFamilyMessage::kCommand:
967 message.reset(new GetFamilyMessage()); break;
968
969 default:
970 message.reset(new UnknownMessage(gnlh->cmd)); break;
repo sync0efa9f02012-12-28 13:40:20 -0800971 }
972 } else {
repo sync0efa9f02012-12-28 13:40:20 -0800973 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);
Wade Guthrie0d438532012-05-18 14:18:50 -0700974
repo sync0efa9f02012-12-28 13:40:20 -0800975 switch (gnlh->cmd) {
976 case AssociateMessage::kCommand:
977 message.reset(new AssociateMessage()); break;
978 case AuthenticateMessage::kCommand:
979 message.reset(new AuthenticateMessage()); break;
980 case CancelRemainOnChannelMessage::kCommand:
981 message.reset(new CancelRemainOnChannelMessage()); break;
982 case ConnectMessage::kCommand:
983 message.reset(new ConnectMessage()); break;
984 case DeauthenticateMessage::kCommand:
985 message.reset(new DeauthenticateMessage()); break;
986 case DeleteStationMessage::kCommand:
987 message.reset(new DeleteStationMessage()); break;
988 case DisassociateMessage::kCommand:
989 message.reset(new DisassociateMessage()); break;
990 case DisconnectMessage::kCommand:
991 message.reset(new DisconnectMessage()); break;
992 case FrameTxStatusMessage::kCommand:
993 message.reset(new FrameTxStatusMessage()); break;
994 case GetRegMessage::kCommand:
995 message.reset(new GetRegMessage()); break;
996 case JoinIbssMessage::kCommand:
997 message.reset(new JoinIbssMessage()); break;
998 case MichaelMicFailureMessage::kCommand:
999 message.reset(new MichaelMicFailureMessage()); break;
1000 case NewScanResultsMessage::kCommand:
1001 message.reset(new NewScanResultsMessage()); break;
1002 case NewStationMessage::kCommand:
1003 message.reset(new NewStationMessage()); break;
1004 case NewWifiMessage::kCommand:
1005 message.reset(new NewWifiMessage()); break;
1006 case NotifyCqmMessage::kCommand:
1007 message.reset(new NotifyCqmMessage()); break;
1008 case PmksaCandidateMessage::kCommand:
1009 message.reset(new PmksaCandidateMessage()); break;
1010 case RegBeaconHintMessage::kCommand:
1011 message.reset(new RegBeaconHintMessage()); break;
1012 case RegChangeMessage::kCommand:
1013 message.reset(new RegChangeMessage()); break;
1014 case RemainOnChannelMessage::kCommand:
1015 message.reset(new RemainOnChannelMessage()); break;
1016 case RoamMessage::kCommand:
1017 message.reset(new RoamMessage()); break;
1018 case ScanAbortedMessage::kCommand:
1019 message.reset(new ScanAbortedMessage()); break;
1020 case TriggerScanMessage::kCommand:
1021 message.reset(new TriggerScanMessage()); break;
1022 case UnprotDeauthenticateMessage::kCommand:
1023 message.reset(new UnprotDeauthenticateMessage()); break;
1024 case UnprotDisassociateMessage::kCommand:
1025 message.reset(new UnprotDisassociateMessage()); break;
Wade Guthrie0d438532012-05-18 14:18:50 -07001026
repo sync0efa9f02012-12-28 13:40:20 -08001027 default:
1028 message.reset(new UnknownMessage(gnlh->cmd)); break;
1029 }
Wade Guthrie71872472013-03-05 10:33:38 -08001030 }
Wade Guthrie0d438532012-05-18 14:18:50 -07001031
Wade Guthrie71872472013-03-05 10:33:38 -08001032 if (!message->InitFromNlmsg(msg)) {
1033 LOG(ERROR) << "Message did not initialize properly";
1034 return NULL;
Wade Guthrie0d438532012-05-18 14:18:50 -07001035 }
1036
Wade Guthrie0d438532012-05-18 14:18:50 -07001037 return message.release();
1038}
1039
repo syncdc085c82012-12-28 08:54:41 -08001040Nl80211MessageDataCollector *
1041 Nl80211MessageDataCollector::GetInstance() {
Wade Guthrie0d438532012-05-18 14:18:50 -07001042 return g_datacollector.Pointer();
1043}
1044
repo syncdc085c82012-12-28 08:54:41 -08001045Nl80211MessageDataCollector::Nl80211MessageDataCollector() {
Wade Guthrie0d438532012-05-18 14:18:50 -07001046 need_to_print[NL80211_ATTR_PMKSA_CANDIDATE] = true;
1047 need_to_print[NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL] = true;
1048 need_to_print[NL80211_CMD_DEL_STATION] = true;
1049 need_to_print[NL80211_CMD_FRAME_TX_STATUS] = true;
1050 need_to_print[NL80211_CMD_JOIN_IBSS] = true;
1051 need_to_print[NL80211_CMD_MICHAEL_MIC_FAILURE] = true;
1052 need_to_print[NL80211_CMD_NEW_WIPHY] = true;
1053 need_to_print[NL80211_CMD_REG_BEACON_HINT] = true;
1054 need_to_print[NL80211_CMD_REG_CHANGE] = true;
1055 need_to_print[NL80211_CMD_REMAIN_ON_CHANNEL] = true;
1056 need_to_print[NL80211_CMD_ROAM] = true;
1057 need_to_print[NL80211_CMD_SCAN_ABORTED] = true;
1058 need_to_print[NL80211_CMD_UNPROT_DEAUTHENTICATE] = true;
1059 need_to_print[NL80211_CMD_UNPROT_DISASSOCIATE] = true;
1060}
1061
repo syncdc085c82012-12-28 08:54:41 -08001062void Nl80211MessageDataCollector::CollectDebugData(
1063 const Nl80211Message &message, nlmsghdr *msg) {
Wade Guthrie0d438532012-05-18 14:18:50 -07001064 if (!msg) {
1065 LOG(ERROR) << "NULL |msg| parameter";
1066 return;
1067 }
1068
1069 bool doit = false;
1070
1071 map<uint8_t, bool>::const_iterator node;
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001072 node = need_to_print.find(message.command());
Wade Guthrie0d438532012-05-18 14:18:50 -07001073 if (node != need_to_print.end())
1074 doit = node->second;
1075
1076 if (doit) {
Wade Guthried6153612012-08-23 11:36:14 -07001077 LOG(INFO) << "@@const unsigned char "
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001078 << "k" << message.command_string()
Wade Guthried6153612012-08-23 11:36:14 -07001079 << "[] = {";
Wade Guthrie0d438532012-05-18 14:18:50 -07001080
Christopher Wileyefd521f2012-11-07 17:32:46 -08001081 int payload_bytes = nlmsg_datalen(msg);
Wade Guthrie0d438532012-05-18 14:18:50 -07001082
1083 size_t bytes = nlmsg_total_size(payload_bytes);
1084 unsigned char *rawdata = reinterpret_cast<unsigned char *>(msg);
Wade Guthried4977f22012-08-22 12:37:54 -07001085 for (size_t i = 0; i < bytes; ++i) {
Wade Guthried6153612012-08-23 11:36:14 -07001086 LOG(INFO) << " 0x"
Wade Guthrie0d438532012-05-18 14:18:50 -07001087 << std::hex << std::setfill('0') << std::setw(2)
1088 << + rawdata[i] << ",";
1089 }
Wade Guthried6153612012-08-23 11:36:14 -07001090 LOG(INFO) << "};";
Wade Guthriebdcdaa72013-03-04 12:47:12 -08001091 need_to_print[message.command()] = false;
Wade Guthrie0d438532012-05-18 14:18:50 -07001092 }
1093}
1094
1095} // namespace shill.