blob: 738e0e47013139179eb4772d6e5ecf92240625e0 [file] [log] [blame]
Wade Guthrie0d438532012-05-18 14:18:50 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// This code is derived from the 'iw' source code. The copyright and license
6// of that code is as follows:
7//
8// Copyright (c) 2007, 2008 Johannes Berg
9// Copyright (c) 2007 Andy Lutomirski
10// Copyright (c) 2007 Mike Kershaw
11// Copyright (c) 2008-2009 Luis R. Rodriguez
12//
13// Permission to use, copy, modify, and/or distribute this software for any
14// purpose with or without fee is hereby granted, provided that the above
15// copyright notice and this permission notice appear in all copies.
16//
17// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
repo syncdc085c82012-12-28 08:54:41 -080025#include "shill/nl80211_message.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070026
Wade Guthrie0d438532012-05-18 14:18:50 -070027#include <netlink/msg.h>
28#include <netlink/netlink.h>
29
Wade Guthrie92d06362013-04-25 15:41:30 -070030#include <limits>
Wade Guthrie89e6cb32013-03-07 08:03:45 -080031#include <map>
Wade Guthrie0d438532012-05-18 14:18:50 -070032#include <string>
Wade Guthrie89e6cb32013-03-07 08:03:45 -080033#include <vector>
Wade Guthrie0d438532012-05-18 14:18:50 -070034
Wade Guthrie68da97c2013-02-26 13:09:35 -080035#include <base/bind.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070036#include <base/stringprintf.h>
37
repo sync90ee0fa2012-12-18 10:08:08 -080038#include "shill/attribute_list.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070039#include "shill/ieee80211.h"
40#include "shill/logging.h"
Wade Guthrief162f8b2013-02-27 14:13:55 -080041#include "shill/netlink_attribute.h"
Wade Guthrie89e6cb32013-03-07 08:03:45 -080042#include "shill/refptr_types.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070043
Wade Guthrie68da97c2013-02-26 13:09:35 -080044using base::Bind;
Wade Guthrie0d438532012-05-18 14:18:50 -070045using base::LazyInstance;
46using base::StringAppendF;
Wade Guthrie0d438532012-05-18 14:18:50 -070047using std::map;
48using std::string;
49using std::vector;
50
51namespace shill {
52
53namespace {
repo syncdc085c82012-12-28 08:54:41 -080054LazyInstance<Nl80211MessageDataCollector> g_datacollector =
Wade Guthrie0d438532012-05-18 14:18:50 -070055 LAZY_INSTANCE_INITIALIZER;
56} // namespace
57
Wade Guthrie0d438532012-05-18 14:18:50 -070058const uint8_t Nl80211Frame::kMinimumFrameByteCount = 26;
59const uint8_t Nl80211Frame::kFrameTypeMask = 0xfc;
60
Wade Guthriebdcdaa72013-03-04 12:47:12 -080061const char Nl80211Message::kBogusMacAddress[] = "XX:XX:XX:XX:XX:XX";
repo syncdc085c82012-12-28 08:54:41 -080062const unsigned int Nl80211Message::kEthernetAddressBytes = 6;
Wade Guthriebee87c22013-03-06 11:00:46 -080063const char Nl80211Message::kMessageTypeString[] = "nl80211";
repo syncdc085c82012-12-28 08:54:41 -080064map<uint16_t, string> *Nl80211Message::reason_code_string_ = NULL;
65map<uint16_t, string> *Nl80211Message::status_code_string_ = NULL;
Wade Guthriebdcdaa72013-03-04 12:47:12 -080066uint16_t Nl80211Message::nl80211_message_type_ = kIllegalMessageType;
67
Wade Guthriebee87c22013-03-06 11:00:46 -080068// static
Paul Stewart2ddf2c62013-04-16 09:47:34 -070069uint16_t Nl80211Message::GetMessageType() {
70 return nl80211_message_type_;
71}
72
73// static
Wade Guthriebee87c22013-03-06 11:00:46 -080074void Nl80211Message::SetMessageType(uint16_t message_type) {
75 if (message_type == NetlinkMessage::kIllegalMessageType) {
76 LOG(FATAL) << "Absolutely need a legal message type for Nl80211 messages.";
77 }
78 nl80211_message_type_ = message_type;
79}
80
repo sync0efa9f02012-12-28 13:40:20 -080081bool Nl80211Message::InitFromNlmsg(const nlmsghdr *const_msg) {
82 if (!const_msg) {
83 LOG(ERROR) << "Null |msg| parameter";
Wade Guthrie0d438532012-05-18 14:18:50 -070084 return false;
85 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -080086 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
87 const_msg->nlmsg_len);
Wade Guthrie0d438532012-05-18 14:18:50 -070088
Wade Guthriebdcdaa72013-03-04 12:47:12 -080089 if (!InitAndStripHeader(&message)) {
90 return false;
91 }
repo sync0efa9f02012-12-28 13:40:20 -080092
93 // Attributes.
94 // Parse the attributes from the nl message payload into the 'tb' array.
95 nlattr *tb[NL80211_ATTR_MAX + 1];
Wade Guthriebdcdaa72013-03-04 12:47:12 -080096 nla_parse(tb, NL80211_ATTR_MAX,
97 reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
98 NULL);
repo sync0efa9f02012-12-28 13:40:20 -080099
Wade Guthrie0d438532012-05-18 14:18:50 -0700100 for (int i = 0; i < NL80211_ATTR_MAX + 1; ++i) {
101 if (tb[i]) {
repo sync0efa9f02012-12-28 13:40:20 -0800102 // TODO(wdg): When Nl80211Messages instantiate their own attributes,
103 // this call should, instead, call |SetAttributeFromNlAttr|.
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800104 attributes_->CreateAndInitAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800105 i, tb[i], Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
Wade Guthrie0d438532012-05-18 14:18:50 -0700106 }
107 }
108
109 // Convert integer values provided by libnl (for example, from the
110 // NL80211_ATTR_STATUS_CODE or NL80211_ATTR_REASON_CODE attribute) into
111 // strings describing the status.
Wade Guthried4977f22012-08-22 12:37:54 -0700112 if (!reason_code_string_) {
113 reason_code_string_ = new map<uint16_t, string>;
114 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecified] =
115 "Unspecified reason";
116 (*reason_code_string_)[
117 IEEE_80211::kReasonCodePreviousAuthenticationInvalid] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700118 "Previous authentication no longer valid";
Wade Guthried4977f22012-08-22 12:37:54 -0700119 (*reason_code_string_)[IEEE_80211::kReasonCodeSenderHasLeft] =
120 "Deauthentcated because sending STA is leaving (or has left) IBSS or "
121 "ESS";
122 (*reason_code_string_)[IEEE_80211::kReasonCodeInactivity] =
123 "Disassociated due to inactivity";
124 (*reason_code_string_)[IEEE_80211::kReasonCodeTooManySTAs] =
125 "Disassociated because AP is unable to handle all currently associated "
126 "STAs";
127 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAuthenticated] =
128 "Class 2 frame received from nonauthenticated STA";
129 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAssociated] =
130 "Class 3 frame received from nonassociated STA";
131 (*reason_code_string_)[IEEE_80211::kReasonCodeDisassociatedHasLeft] =
132 "Disassociated because sending STA is leaving (or has left) BSS";
133 (*reason_code_string_)[
134 IEEE_80211::kReasonCodeReassociationNotAuthenticated] =
135 "STA requesting (re)association is not authenticated with responding "
136 "STA";
137 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptablePowerCapability] =
138 "Disassociated because the information in the Power Capability "
139 "element is unacceptable";
140 (*reason_code_string_)[
141 IEEE_80211::kReasonCodeUnacceptableSupportedChannelInfo] =
142 "Disassociated because the information in the Supported Channels "
143 "element is unacceptable";
144 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidInfoElement] =
145 "Invalid information element, i.e., an information element defined in "
146 "this standard for which the content does not meet the specifications "
147 "in Clause 7";
148 (*reason_code_string_)[IEEE_80211::kReasonCodeMICFailure] =
149 "Message integrity code (MIC) failure";
150 (*reason_code_string_)[IEEE_80211::kReasonCode4WayTimeout] =
151 "4-Way Handshake timeout";
152 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupKeyHandshakeTimeout] =
153 "Group Key Handshake timeout";
154 (*reason_code_string_)[IEEE_80211::kReasonCodeDifferenIE] =
155 "Information element in 4-Way Handshake different from "
156 "(Re)Association Request/Probe Response/Beacon frame";
157 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupCipherInvalid] =
158 "Invalid group cipher";
159 (*reason_code_string_)[IEEE_80211::kReasonCodePairwiseCipherInvalid] =
160 "Invalid pairwise cipher";
161 (*reason_code_string_)[IEEE_80211::kReasonCodeAkmpInvalid] =
162 "Invalid AKMP";
163 (*reason_code_string_)[IEEE_80211::kReasonCodeUnsupportedRsnIeVersion] =
164 "Unsupported RSN information element version";
165 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidRsnIeCaps] =
166 "Invalid RSN information element capabilities";
167 (*reason_code_string_)[IEEE_80211::kReasonCode8021XAuth] =
168 "IEEE 802.1X authentication failed";
169 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteRejected] =
170 "Cipher suite rejected because of the security policy";
171 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecifiedQoS] =
172 "Disassociated for unspecified, QoS-related reason";
173 (*reason_code_string_)[IEEE_80211::kReasonCodeQoSBandwidth] =
174 "Disassociated because QoS AP lacks sufficient bandwidth for this "
175 "QoS STA";
176 (*reason_code_string_)[IEEE_80211::kReasonCodeiPoorConditions] =
177 "Disassociated because excessive number of frames need to be "
178 "acknowledged, but are not acknowledged due to AP transmissions "
179 "and/or poor channel conditions";
180 (*reason_code_string_)[IEEE_80211::kReasonCodeOutsideTxop] =
181 "Disassociated because STA is transmitting outside the limits of its "
182 "TXOPs";
183 (*reason_code_string_)[IEEE_80211::kReasonCodeStaLeaving] =
184 "Requested from peer STA as the STA is leaving the BSS (or resetting)";
185 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptableMechanism] =
186 "Requested from peer STA as it does not want to use the mechanism";
187 (*reason_code_string_)[IEEE_80211::kReasonCodeSetupRequired] =
188 "Requested from peer STA as the STA received frames using the "
189 "mechanism for which a setup is required";
190 (*reason_code_string_)[IEEE_80211::kReasonCodeTimeout] =
191 "Requested from peer STA due to timeout";
192 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteNotSupported] =
193 "Peer STA does not support the requested cipher suite";
194 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalid] = "<INVALID REASON>";
195 }
196
197 if (!status_code_string_) {
198 status_code_string_ = new map<uint16_t, string>;
199 (*status_code_string_)[IEEE_80211::kStatusCodeSuccessful] = "Successful";
200 (*status_code_string_)[IEEE_80211::kStatusCodeFailure] =
201 "Unspecified failure";
202 (*status_code_string_)[IEEE_80211::kStatusCodeAllCapabilitiesNotSupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700203 "Cannot support all requested capabilities in the capability "
204 "information field";
Wade Guthried4977f22012-08-22 12:37:54 -0700205 (*status_code_string_)[IEEE_80211::kStatusCodeCantConfirmAssociation] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700206 "Reassociation denied due to inability to confirm that association "
207 "exists";
Wade Guthried4977f22012-08-22 12:37:54 -0700208 (*status_code_string_)[IEEE_80211::kStatusCodeAssociationDenied] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700209 "Association denied due to reason outside the scope of this standard";
Wade Guthried4977f22012-08-22 12:37:54 -0700210 (*status_code_string_)[
211 IEEE_80211::kStatusCodeAuthenticationUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700212 "Responding station does not support the specified authentication "
213 "algorithm";
Wade Guthried4977f22012-08-22 12:37:54 -0700214 (*status_code_string_)[IEEE_80211::kStatusCodeOutOfSequence] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700215 "Received an authentication frame with authentication transaction "
216 "sequence number out of expected sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700217 (*status_code_string_)[IEEE_80211::kStatusCodeChallengeFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700218 "Authentication rejected because of challenge failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700219 (*status_code_string_)[IEEE_80211::kStatusCodeFrameTimeout] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700220 "Authentication rejected due to timeout waiting for next frame in "
221 "sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700222 (*status_code_string_)[IEEE_80211::kStatusCodeMaxSta] =
223 "Association denied because AP is unable to handle additional "
224 "associated STA";
225 (*status_code_string_)[IEEE_80211::kStatusCodeDataRateUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700226 "Association denied due to requesting station not supporting all of "
227 "the data rates in the BSSBasicRateSet parameter";
Wade Guthried4977f22012-08-22 12:37:54 -0700228 (*status_code_string_)[IEEE_80211::kStatusCodeShortPreambleUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700229 "Association denied due to requesting station not supporting the "
230 "short preamble option";
Wade Guthried4977f22012-08-22 12:37:54 -0700231 (*status_code_string_)[IEEE_80211::kStatusCodePbccUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700232 "Association denied due to requesting station not supporting the PBCC "
233 "modulation option";
Wade Guthried4977f22012-08-22 12:37:54 -0700234 (*status_code_string_)[
235 IEEE_80211::kStatusCodeChannelAgilityUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700236 "Association denied due to requesting station not supporting the "
237 "channel agility option";
Wade Guthried4977f22012-08-22 12:37:54 -0700238 (*status_code_string_)[IEEE_80211::kStatusCodeNeedSpectrumManagement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700239 "Association request rejected because Spectrum Management capability "
240 "is required";
Wade Guthried4977f22012-08-22 12:37:54 -0700241 (*status_code_string_)[
242 IEEE_80211::kStatusCodeUnacceptablePowerCapability] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700243 "Association request rejected because the information in the Power "
244 "Capability element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700245 (*status_code_string_)[
246 IEEE_80211::kStatusCodeUnacceptableSupportedChannelInfo] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700247 "Association request rejected because the information in the "
248 "Supported Channels element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700249 (*status_code_string_)[IEEE_80211::kStatusCodeShortTimeSlotRequired] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700250 "Association request rejected due to requesting station not "
Wade Guthried4977f22012-08-22 12:37:54 -0700251 "supporting the Short Slot Time option";
252 (*status_code_string_)[IEEE_80211::kStatusCodeDssOfdmRequired] =
253 "Association request rejected due to requesting station not "
254 "supporting the DSSS-OFDM option";
255 (*status_code_string_)[IEEE_80211::kStatusCodeQosFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700256 "Unspecified, QoS related failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700257 (*status_code_string_)[
258 IEEE_80211::kStatusCodeInsufficientBandwithForQsta] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700259 "Association denied due to QAP having insufficient bandwidth to handle "
260 "another QSTA";
Wade Guthried4977f22012-08-22 12:37:54 -0700261 (*status_code_string_)[IEEE_80211::kStatusCodePoorConditions] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700262 "Association denied due to poor channel conditions";
Wade Guthried4977f22012-08-22 12:37:54 -0700263 (*status_code_string_)[IEEE_80211::kStatusCodeQosNotSupported] =
264 "Association (with QoS BSS) denied due to requesting station not "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700265 "supporting the QoS facility";
Wade Guthried4977f22012-08-22 12:37:54 -0700266 (*status_code_string_)[IEEE_80211::kStatusCodeDeclined] =
267 "The request has been declined";
268 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidParameterValues] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700269 "The request has not been successful as one or more parameters have "
270 "invalid values";
Wade Guthried4977f22012-08-22 12:37:54 -0700271 (*status_code_string_)[IEEE_80211::kStatusCodeCannotBeHonored] =
272 "The TS has not been created because the request cannot be honored. "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700273 "However, a suggested Tspec is provided so that the initiating QSTA "
274 "may attempt to send another TS with the suggested changes to the "
275 "TSpec";
Wade Guthried4977f22012-08-22 12:37:54 -0700276 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidInfoElement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700277 "Invalid Information Element";
Wade Guthried4977f22012-08-22 12:37:54 -0700278 (*status_code_string_)[IEEE_80211::kStatusCodeGroupCipherInvalid] =
279 "Invalid Group Cipher";
280 (*status_code_string_)[IEEE_80211::kStatusCodePairwiseCipherInvalid] =
281 "Invalid Pairwise Cipher";
282 (*status_code_string_)[IEEE_80211::kStatusCodeAkmpInvalid] = "Invalid AKMP";
283 (*status_code_string_)[IEEE_80211::kStatusCodeUnsupportedRsnIeVersion] =
284 "Unsupported RSN Information Element version";
285 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidRsnIeCaps] =
286 "Invalid RSN Information Element Capabilities";
287 (*status_code_string_)[IEEE_80211::kStatusCodeCipherSuiteRejected] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700288 "Cipher suite is rejected per security policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700289 (*status_code_string_)[IEEE_80211::kStatusCodeTsDelayNotMet] =
290 "The TS has not been created. However, the HC may be capable of "
291 "creating a TS, in response to a request, after the time indicated in "
292 "the TS Delay element";
293 (*status_code_string_)[IEEE_80211::kStatusCodeDirectLinkIllegal] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700294 "Direct link is not allowed in the BSS by policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700295 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInBss] =
296 "Destination STA is not present within this BSS";
297 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInQsta] =
298 "The destination STA is not a QoS STA";
299 (*status_code_string_)[IEEE_80211::kStatusCodeExcessiveListenInterval] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700300 "Association denied because Listen Interval is too large";
Wade Guthried4977f22012-08-22 12:37:54 -0700301 (*status_code_string_)[IEEE_80211::kStatusCodeInvalid] = "<INVALID STATUS>";
Wade Guthrie0d438532012-05-18 14:18:50 -0700302 }
303
304 return true;
305}
306
Wade Guthrie0d438532012-05-18 14:18:50 -0700307// Helper function to provide a string for a MAC address.
Wade Guthrie68da97c2013-02-26 13:09:35 -0800308bool Nl80211Message::GetMacAttributeString(int id, string *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700309 if (!value) {
310 LOG(ERROR) << "Null |value| parameter";
311 return false;
312 }
313
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800314 ByteString data;
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800315 if (!const_attributes()->GetRawAttributeValue(id, &data)) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700316 value->assign(kBogusMacAddress);
317 return false;
318 }
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800319 value->assign(StringFromMacAddress(data.GetConstData()));
Wade Guthrie0d438532012-05-18 14:18:50 -0700320
321 return true;
322}
323
324// Helper function to provide a string for NL80211_ATTR_SCAN_FREQUENCIES.
repo syncdc085c82012-12-28 08:54:41 -0800325bool Nl80211Message::GetScanFrequenciesAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800326 int id, vector<uint32_t> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700327 if (!value) {
328 LOG(ERROR) << "Null |value| parameter";
329 return false;
330 }
331
332 value->clear();
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800333
334 AttributeListConstRefPtr frequency_list;
335 if (!const_attributes()->ConstGetNestedAttributeList(
336 NL80211_ATTR_SCAN_FREQUENCIES, &frequency_list) || !frequency_list) {
337 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_FREQUENCIES attribute";
repo syncd316eb72012-12-10 15:48:47 -0800338 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800339 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700340
Wade Guthrie480aada2013-04-25 15:16:34 -0700341 AttributeIdIterator freq_iter(*frequency_list);
342 for (; !freq_iter.AtEnd(); freq_iter.Advance()) {
343 uint32_t freq = 0;
344 if (frequency_list->GetU32AttributeValue(freq_iter.GetId(), &freq)) {
345 value->push_back(freq);
346 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700347 }
repo syncd316eb72012-12-10 15:48:47 -0800348 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700349}
350
351// Helper function to provide a string for NL80211_ATTR_SCAN_SSIDS.
repo syncdc085c82012-12-28 08:54:41 -0800352bool Nl80211Message::GetScanSsidsAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800353 int id, vector<string> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700354 if (!value) {
355 LOG(ERROR) << "Null |value| parameter";
356 return false;
357 }
358
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800359 AttributeListConstRefPtr ssid_list;
360 if (!const_attributes()->ConstGetNestedAttributeList(
361 NL80211_ATTR_SCAN_SSIDS, &ssid_list) || !ssid_list) {
362 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_SSIDS attribute";
repo sync90ee0fa2012-12-18 10:08:08 -0800363 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800364 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700365
Wade Guthrie480aada2013-04-25 15:16:34 -0700366 AttributeIdIterator ssid_iter(*ssid_list);
367 for (; !ssid_iter.AtEnd(); ssid_iter.Advance()) {
368 string ssid;
369 if (ssid_list->GetStringAttributeValue(ssid_iter.GetId(), &ssid)) {
370 value->push_back(ssid);
371 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700372 }
repo sync90ee0fa2012-12-18 10:08:08 -0800373 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700374}
375
Wade Guthrie0d438532012-05-18 14:18:50 -0700376// static
repo syncdc085c82012-12-28 08:54:41 -0800377string Nl80211Message::StringFromMacAddress(const uint8_t *arg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700378 string output;
379
380 if (!arg) {
381 output = kBogusMacAddress;
382 LOG(ERROR) << "|arg| parameter is NULL.";
383 } else {
384 StringAppendF(&output, "%02x", arg[0]);
385
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800386 for (unsigned int i = 1; i < kEthernetAddressBytes ; ++i) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700387 StringAppendF(&output, ":%02x", arg[i]);
388 }
389 }
390 return output;
391}
392
393// static
repo syncdc085c82012-12-28 08:54:41 -0800394string Nl80211Message::StringFromReason(uint16_t status) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700395 map<uint16_t, string>::const_iterator match;
Wade Guthried4977f22012-08-22 12:37:54 -0700396 match = reason_code_string_->find(status);
397 if (match == reason_code_string_->end()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700398 string output;
Wade Guthried4977f22012-08-22 12:37:54 -0700399 if (status < IEEE_80211::kReasonCodeMax) {
400 StringAppendF(&output, "<Reserved Reason:%u>", status);
401 } else {
402 StringAppendF(&output, "<Unknown Reason:%u>", status);
403 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700404 return output;
405 }
406 return match->second;
407}
408
Wade Guthried4977f22012-08-22 12:37:54 -0700409// static
repo syncdc085c82012-12-28 08:54:41 -0800410string Nl80211Message::StringFromStatus(uint16_t status) {
Wade Guthried4977f22012-08-22 12:37:54 -0700411 map<uint16_t, string>::const_iterator match;
412 match = status_code_string_->find(status);
413 if (match == status_code_string_->end()) {
414 string output;
415 if (status < IEEE_80211::kStatusCodeMax) {
416 StringAppendF(&output, "<Reserved Status:%u>", status);
417 } else {
418 StringAppendF(&output, "<Unknown Status:%u>", status);
419 }
420 return output;
421 }
422 return match->second;
423}
424
Wade Guthrie71872472013-03-05 10:33:38 -0800425// Nl80211Frame
426
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800427Nl80211Frame::Nl80211Frame(const ByteString &raw_frame)
Wade Guthrie92d06362013-04-25 15:41:30 -0700428 : frame_type_(kIllegalFrameType),
429 reason_(std::numeric_limits<uint16_t>::max()),
430 status_(std::numeric_limits<uint16_t>::max()),
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800431 frame_(raw_frame) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700432 const IEEE_80211::ieee80211_frame *frame =
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800433 reinterpret_cast<const IEEE_80211::ieee80211_frame *>(
434 frame_.GetConstData());
Wade Guthrie0d438532012-05-18 14:18:50 -0700435
436 // Now, let's populate the other stuff.
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800437 if (frame_.GetLength() >= kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700438 mac_from_ =
repo syncdc085c82012-12-28 08:54:41 -0800439 Nl80211Message::StringFromMacAddress(&frame->destination_mac[0]);
440 mac_to_ = Nl80211Message::StringFromMacAddress(&frame->source_mac[0]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700441 frame_type_ = frame->frame_control & kFrameTypeMask;
442
443 switch (frame_type_) {
444 case kAssocResponseFrameType:
445 case kReassocResponseFrameType:
446 status_ = le16toh(frame->u.associate_response.status_code);
447 break;
448
449 case kAuthFrameType:
450 status_ = le16toh(frame->u.authentiate_message.status_code);
451 break;
452
453 case kDisassocFrameType:
454 case kDeauthFrameType:
Wade Guthried4977f22012-08-22 12:37:54 -0700455 reason_ = le16toh(frame->u.deauthentiate_message.reason_code);
Wade Guthrie0d438532012-05-18 14:18:50 -0700456 break;
457
458 default:
459 break;
460 }
461 }
462}
463
Wade Guthried4977f22012-08-22 12:37:54 -0700464bool Nl80211Frame::ToString(string *output) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700465 if (!output) {
466 LOG(ERROR) << "NULL |output|";
467 return false;
468 }
469
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800470 if (frame_.IsEmpty()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700471 output->append(" [no frame]");
472 return true;
473 }
474
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800475 if (frame_.GetLength() < kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700476 output->append(" [invalid frame: ");
477 } else {
478 StringAppendF(output, " %s -> %s", mac_from_.c_str(), mac_to_.c_str());
479
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800480 switch (frame_.GetConstData()[0] & kFrameTypeMask) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700481 case kAssocResponseFrameType:
482 StringAppendF(output, "; AssocResponse status: %u: %s",
483 status_,
repo syncdc085c82012-12-28 08:54:41 -0800484 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700485 break;
486 case kReassocResponseFrameType:
487 StringAppendF(output, "; ReassocResponse status: %u: %s",
488 status_,
repo syncdc085c82012-12-28 08:54:41 -0800489 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700490 break;
491 case kAuthFrameType:
492 StringAppendF(output, "; Auth status: %u: %s",
493 status_,
repo syncdc085c82012-12-28 08:54:41 -0800494 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700495 break;
496
497 case kDisassocFrameType:
498 StringAppendF(output, "; Disassoc reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700499 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800500 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700501 break;
502 case kDeauthFrameType:
503 StringAppendF(output, "; Deauth reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700504 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800505 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700506 break;
507
508 default:
509 break;
510 }
511 output->append(" [frame: ");
512 }
513
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800514 const unsigned char *frame = frame_.GetConstData();
515 for (size_t i = 0; i < frame_.GetLength(); ++i) {
516 StringAppendF(output, "%02x, ", frame[i]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700517 }
518 output->append("]");
519
520 return true;
521}
522
Wade Guthried4977f22012-08-22 12:37:54 -0700523bool Nl80211Frame::IsEqual(const Nl80211Frame &other) const {
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800524 return frame_.Equals(other.frame_);
Wade Guthrie0d438532012-05-18 14:18:50 -0700525}
526
527//
repo syncdc085c82012-12-28 08:54:41 -0800528// Specific Nl80211Message types.
Wade Guthrie0d438532012-05-18 14:18:50 -0700529//
530
531const uint8_t AssociateMessage::kCommand = NL80211_CMD_ASSOCIATE;
532const char AssociateMessage::kCommandString[] = "NL80211_CMD_ASSOCIATE";
533
Wade Guthrie0d438532012-05-18 14:18:50 -0700534const uint8_t AuthenticateMessage::kCommand = NL80211_CMD_AUTHENTICATE;
535const char AuthenticateMessage::kCommandString[] = "NL80211_CMD_AUTHENTICATE";
536
Wade Guthrie0d438532012-05-18 14:18:50 -0700537const uint8_t CancelRemainOnChannelMessage::kCommand =
538 NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL;
539const char CancelRemainOnChannelMessage::kCommandString[] =
540 "NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL";
541
Wade Guthrie0d438532012-05-18 14:18:50 -0700542const uint8_t ConnectMessage::kCommand = NL80211_CMD_CONNECT;
543const char ConnectMessage::kCommandString[] = "NL80211_CMD_CONNECT";
544
Wade Guthrie0d438532012-05-18 14:18:50 -0700545const uint8_t DeauthenticateMessage::kCommand = NL80211_CMD_DEAUTHENTICATE;
546const char DeauthenticateMessage::kCommandString[] =
547 "NL80211_CMD_DEAUTHENTICATE";
548
Wade Guthrie0d438532012-05-18 14:18:50 -0700549const uint8_t DeleteStationMessage::kCommand = NL80211_CMD_DEL_STATION;
550const char DeleteStationMessage::kCommandString[] = "NL80211_CMD_DEL_STATION";
551
Wade Guthrie0d438532012-05-18 14:18:50 -0700552const uint8_t DisassociateMessage::kCommand = NL80211_CMD_DISASSOCIATE;
553const char DisassociateMessage::kCommandString[] = "NL80211_CMD_DISASSOCIATE";
554
Wade Guthrie0d438532012-05-18 14:18:50 -0700555const uint8_t DisconnectMessage::kCommand = NL80211_CMD_DISCONNECT;
556const char DisconnectMessage::kCommandString[] = "NL80211_CMD_DISCONNECT";
557
Wade Guthrie0d438532012-05-18 14:18:50 -0700558const uint8_t FrameTxStatusMessage::kCommand = NL80211_CMD_FRAME_TX_STATUS;
559const char FrameTxStatusMessage::kCommandString[] =
560 "NL80211_CMD_FRAME_TX_STATUS";
561
repo sync0efa9f02012-12-28 13:40:20 -0800562const uint8_t GetRegMessage::kCommand = NL80211_CMD_GET_REG;
563const char GetRegMessage::kCommandString[] = "NL80211_CMD_GET_REG";
564
Wade Guthrie1f355e82013-04-11 15:46:12 -0700565const uint8_t GetWiphyMessage::kCommand = NL80211_CMD_GET_WIPHY;
566const char GetWiphyMessage::kCommandString[] = "NL80211_CMD_GET_WIPHY";
567
Wade Guthrie92d06362013-04-25 15:41:30 -0700568GetWiphyMessage::GetWiphyMessage() : Nl80211Message(kCommand, kCommandString) {
569 attributes()->CreateAttribute(
570 NL80211_ATTR_IFINDEX, Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
571}
572
Wade Guthrie0d438532012-05-18 14:18:50 -0700573const uint8_t JoinIbssMessage::kCommand = NL80211_CMD_JOIN_IBSS;
574const char JoinIbssMessage::kCommandString[] = "NL80211_CMD_JOIN_IBSS";
575
Wade Guthrie0d438532012-05-18 14:18:50 -0700576const uint8_t MichaelMicFailureMessage::kCommand =
577 NL80211_CMD_MICHAEL_MIC_FAILURE;
578const char MichaelMicFailureMessage::kCommandString[] =
579 "NL80211_CMD_MICHAEL_MIC_FAILURE";
580
Wade Guthrie0d438532012-05-18 14:18:50 -0700581const uint8_t NewScanResultsMessage::kCommand = NL80211_CMD_NEW_SCAN_RESULTS;
582const char NewScanResultsMessage::kCommandString[] =
583 "NL80211_CMD_NEW_SCAN_RESULTS";
584
Wade Guthrie0d438532012-05-18 14:18:50 -0700585const uint8_t NewStationMessage::kCommand = NL80211_CMD_NEW_STATION;
586const char NewStationMessage::kCommandString[] = "NL80211_CMD_NEW_STATION";
587
Wade Guthrie1f355e82013-04-11 15:46:12 -0700588const uint8_t NewWiphyMessage::kCommand = NL80211_CMD_NEW_WIPHY;
589const char NewWiphyMessage::kCommandString[] = "NL80211_CMD_NEW_WIPHY";
Wade Guthrie0d438532012-05-18 14:18:50 -0700590
Wade Guthrie0d438532012-05-18 14:18:50 -0700591const uint8_t NotifyCqmMessage::kCommand = NL80211_CMD_NOTIFY_CQM;
592const char NotifyCqmMessage::kCommandString[] = "NL80211_CMD_NOTIFY_CQM";
593
Wade Guthrie0d438532012-05-18 14:18:50 -0700594const uint8_t PmksaCandidateMessage::kCommand = NL80211_ATTR_PMKSA_CANDIDATE;
595const char PmksaCandidateMessage::kCommandString[] =
596 "NL80211_ATTR_PMKSA_CANDIDATE";
597
Wade Guthrie0d438532012-05-18 14:18:50 -0700598const uint8_t RegBeaconHintMessage::kCommand = NL80211_CMD_REG_BEACON_HINT;
599const char RegBeaconHintMessage::kCommandString[] =
600 "NL80211_CMD_REG_BEACON_HINT";
601
Wade Guthrie0d438532012-05-18 14:18:50 -0700602const uint8_t RegChangeMessage::kCommand = NL80211_CMD_REG_CHANGE;
603const char RegChangeMessage::kCommandString[] = "NL80211_CMD_REG_CHANGE";
604
Wade Guthrie0d438532012-05-18 14:18:50 -0700605const uint8_t RemainOnChannelMessage::kCommand = NL80211_CMD_REMAIN_ON_CHANNEL;
606const char RemainOnChannelMessage::kCommandString[] =
607 "NL80211_CMD_REMAIN_ON_CHANNEL";
608
Wade Guthrie0d438532012-05-18 14:18:50 -0700609const uint8_t RoamMessage::kCommand = NL80211_CMD_ROAM;
610const char RoamMessage::kCommandString[] = "NL80211_CMD_ROAM";
611
Wade Guthrie0d438532012-05-18 14:18:50 -0700612const uint8_t ScanAbortedMessage::kCommand = NL80211_CMD_SCAN_ABORTED;
613const char ScanAbortedMessage::kCommandString[] = "NL80211_CMD_SCAN_ABORTED";
614
Wade Guthrie71872472013-03-05 10:33:38 -0800615const uint8_t GetScanMessage::kCommand = NL80211_CMD_GET_SCAN;
616const char GetScanMessage::kCommandString[] = "NL80211_CMD_GET_SCAN";
617
Wade Guthrie0d438532012-05-18 14:18:50 -0700618const uint8_t TriggerScanMessage::kCommand = NL80211_CMD_TRIGGER_SCAN;
619const char TriggerScanMessage::kCommandString[] = "NL80211_CMD_TRIGGER_SCAN";
620
Wade Guthrieb9c3feb2013-04-25 16:31:19 -0700621TriggerScanMessage::TriggerScanMessage()
622 : Nl80211Message(kCommand, kCommandString) {
623 attributes()->CreateAttribute(
624 NL80211_ATTR_IFINDEX, Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
625 attributes()->CreateAttribute(
626 NL80211_ATTR_SCAN_FREQUENCIES,
627 Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
628 attributes()->CreateAttribute(
629 NL80211_ATTR_SCAN_SSIDS,
630 Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
631}
632
Wade Guthrie0d438532012-05-18 14:18:50 -0700633const uint8_t UnprotDeauthenticateMessage::kCommand =
634 NL80211_CMD_UNPROT_DEAUTHENTICATE;
635const char UnprotDeauthenticateMessage::kCommandString[] =
636 "NL80211_CMD_UNPROT_DEAUTHENTICATE";
637
Wade Guthrie0d438532012-05-18 14:18:50 -0700638const uint8_t UnprotDisassociateMessage::kCommand =
639 NL80211_CMD_UNPROT_DISASSOCIATE;
640const char UnprotDisassociateMessage::kCommandString[] =
641 "NL80211_CMD_UNPROT_DISASSOCIATE";
642
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700643GetInterfaceMessage::GetInterfaceMessage()
644 : Nl80211Message(kCommand, kCommandString) {
645 attributes()->CreateAttribute(
646 NL80211_ATTR_IFINDEX, Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
647}
648
649const uint8_t GetInterfaceMessage::kCommand = NL80211_CMD_GET_INTERFACE;
650const char GetInterfaceMessage::kCommandString[] = "NL80211_CMD_GET_INTERFACE";
651
652const uint8_t NewInterfaceMessage::kCommand = NL80211_CMD_NEW_INTERFACE;
653const char NewInterfaceMessage::kCommandString[] = "NL80211_CMD_NEW_INTERFACE";
654
Wade Guthrie12f113a2013-03-12 17:15:46 -0700655// static
656NetlinkMessage *Nl80211Message::CreateMessage(const nlmsghdr *const_msg) {
657 if (!const_msg) {
658 LOG(ERROR) << "NULL |const_msg| parameter";
659 return NULL;
660 }
661 // Casting away constness since, while nlmsg_data doesn't change its
662 // parameter, it also doesn't declare its paramenter as const.
663 nlmsghdr *msg = const_cast<nlmsghdr *>(const_msg);
664 void *payload = nlmsg_data(msg);
665 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);
666 scoped_ptr<NetlinkMessage> message;
667
668 switch (gnlh->cmd) {
669 case AssociateMessage::kCommand:
670 return new AssociateMessage();
671 case AuthenticateMessage::kCommand:
672 return new AuthenticateMessage();
673 case CancelRemainOnChannelMessage::kCommand:
674 return new CancelRemainOnChannelMessage();
675 case ConnectMessage::kCommand:
676 return new ConnectMessage();
677 case DeauthenticateMessage::kCommand:
678 return new DeauthenticateMessage();
679 case DeleteStationMessage::kCommand:
680 return new DeleteStationMessage();
681 case DisassociateMessage::kCommand:
682 return new DisassociateMessage();
683 case DisconnectMessage::kCommand:
684 return new DisconnectMessage();
685 case FrameTxStatusMessage::kCommand:
686 return new FrameTxStatusMessage();
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700687 case GetInterfaceMessage::kCommand:
688 return new GetInterfaceMessage();
Wade Guthrie12f113a2013-03-12 17:15:46 -0700689 case GetRegMessage::kCommand:
690 return new GetRegMessage();
Wade Guthrie1f355e82013-04-11 15:46:12 -0700691 case GetWiphyMessage::kCommand:
692 return new GetWiphyMessage();
Wade Guthrie12f113a2013-03-12 17:15:46 -0700693 case JoinIbssMessage::kCommand:
694 return new JoinIbssMessage();
695 case MichaelMicFailureMessage::kCommand:
696 return new MichaelMicFailureMessage();
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700697 case NewInterfaceMessage::kCommand:
698 return new NewInterfaceMessage();
Wade Guthrie12f113a2013-03-12 17:15:46 -0700699 case NewScanResultsMessage::kCommand:
700 return new NewScanResultsMessage();
701 case NewStationMessage::kCommand:
702 return new NewStationMessage();
Wade Guthrie1f355e82013-04-11 15:46:12 -0700703 case NewWiphyMessage::kCommand:
704 return new NewWiphyMessage();
Wade Guthrie12f113a2013-03-12 17:15:46 -0700705 case NotifyCqmMessage::kCommand:
706 return new NotifyCqmMessage();
707 case PmksaCandidateMessage::kCommand:
708 return new PmksaCandidateMessage();
709 case RegBeaconHintMessage::kCommand:
710 return new RegBeaconHintMessage();
711 case RegChangeMessage::kCommand:
712 return new RegChangeMessage();
713 case RemainOnChannelMessage::kCommand:
714 return new RemainOnChannelMessage();
715 case RoamMessage::kCommand:
716 return new RoamMessage();
717 case ScanAbortedMessage::kCommand:
718 return new ScanAbortedMessage();
719 case TriggerScanMessage::kCommand:
720 return new TriggerScanMessage();
721 case UnprotDeauthenticateMessage::kCommand:
722 return new UnprotDeauthenticateMessage();
723 case UnprotDisassociateMessage::kCommand:
724 return new UnprotDisassociateMessage();
725 default:
726 LOG(WARNING) << "Unknown/unhandled netlink nl80211 message " << gnlh->cmd;
727 break;
728 }
729 return NULL;
730}
731
Wade Guthrie0d438532012-05-18 14:18:50 -0700732//
Wade Guthrie12f113a2013-03-12 17:15:46 -0700733// Data Collector
734//
735
repo syncdc085c82012-12-28 08:54:41 -0800736Nl80211MessageDataCollector *
737 Nl80211MessageDataCollector::GetInstance() {
Wade Guthrie0d438532012-05-18 14:18:50 -0700738 return g_datacollector.Pointer();
739}
740
repo syncdc085c82012-12-28 08:54:41 -0800741Nl80211MessageDataCollector::Nl80211MessageDataCollector() {
Wade Guthrie0d438532012-05-18 14:18:50 -0700742 need_to_print[NL80211_ATTR_PMKSA_CANDIDATE] = true;
743 need_to_print[NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL] = true;
744 need_to_print[NL80211_CMD_DEL_STATION] = true;
745 need_to_print[NL80211_CMD_FRAME_TX_STATUS] = true;
746 need_to_print[NL80211_CMD_JOIN_IBSS] = true;
747 need_to_print[NL80211_CMD_MICHAEL_MIC_FAILURE] = true;
748 need_to_print[NL80211_CMD_NEW_WIPHY] = true;
749 need_to_print[NL80211_CMD_REG_BEACON_HINT] = true;
750 need_to_print[NL80211_CMD_REG_CHANGE] = true;
751 need_to_print[NL80211_CMD_REMAIN_ON_CHANNEL] = true;
752 need_to_print[NL80211_CMD_ROAM] = true;
753 need_to_print[NL80211_CMD_SCAN_ABORTED] = true;
754 need_to_print[NL80211_CMD_UNPROT_DEAUTHENTICATE] = true;
755 need_to_print[NL80211_CMD_UNPROT_DISASSOCIATE] = true;
756}
757
repo syncdc085c82012-12-28 08:54:41 -0800758void Nl80211MessageDataCollector::CollectDebugData(
759 const Nl80211Message &message, nlmsghdr *msg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700760 if (!msg) {
761 LOG(ERROR) << "NULL |msg| parameter";
762 return;
763 }
764
765 bool doit = false;
766
767 map<uint8_t, bool>::const_iterator node;
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800768 node = need_to_print.find(message.command());
Wade Guthrie0d438532012-05-18 14:18:50 -0700769 if (node != need_to_print.end())
770 doit = node->second;
771
772 if (doit) {
Wade Guthried6153612012-08-23 11:36:14 -0700773 LOG(INFO) << "@@const unsigned char "
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800774 << "k" << message.command_string()
Wade Guthried6153612012-08-23 11:36:14 -0700775 << "[] = {";
Wade Guthrie0d438532012-05-18 14:18:50 -0700776
Christopher Wileyefd521f2012-11-07 17:32:46 -0800777 int payload_bytes = nlmsg_datalen(msg);
Wade Guthrie0d438532012-05-18 14:18:50 -0700778
779 size_t bytes = nlmsg_total_size(payload_bytes);
780 unsigned char *rawdata = reinterpret_cast<unsigned char *>(msg);
Wade Guthried4977f22012-08-22 12:37:54 -0700781 for (size_t i = 0; i < bytes; ++i) {
Wade Guthried6153612012-08-23 11:36:14 -0700782 LOG(INFO) << " 0x"
Wade Guthrie0d438532012-05-18 14:18:50 -0700783 << std::hex << std::setfill('0') << std::setw(2)
784 << + rawdata[i] << ",";
785 }
Wade Guthried6153612012-08-23 11:36:14 -0700786 LOG(INFO) << "};";
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800787 need_to_print[message.command()] = false;
Wade Guthrie0d438532012-05-18 14:18:50 -0700788 }
789}
790
791} // namespace shill.