blob: 97d5419beb03b3d9ceb37b0b93fca774e23311fb [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 Guthrie2193b232013-06-05 17:09:07 -070042#include "shill/nl80211_attribute.h" // For Nl80211AttributeMac
Wade Guthrie89e6cb32013-03-07 08:03:45 -080043#include "shill/refptr_types.h"
Wade Guthrie0d438532012-05-18 14:18:50 -070044
Wade Guthrie68da97c2013-02-26 13:09:35 -080045using base::Bind;
Wade Guthrie0d438532012-05-18 14:18:50 -070046using base::LazyInstance;
47using base::StringAppendF;
Wade Guthrie0d438532012-05-18 14:18:50 -070048using std::map;
49using std::string;
50using std::vector;
51
52namespace shill {
53
54namespace {
repo syncdc085c82012-12-28 08:54:41 -080055LazyInstance<Nl80211MessageDataCollector> g_datacollector =
Wade Guthrie0d438532012-05-18 14:18:50 -070056 LAZY_INSTANCE_INITIALIZER;
57} // namespace
58
Wade Guthrie0d438532012-05-18 14:18:50 -070059const uint8_t Nl80211Frame::kMinimumFrameByteCount = 26;
60const uint8_t Nl80211Frame::kFrameTypeMask = 0xfc;
61
Wade Guthriebee87c22013-03-06 11:00:46 -080062const char Nl80211Message::kMessageTypeString[] = "nl80211";
repo syncdc085c82012-12-28 08:54:41 -080063map<uint16_t, string> *Nl80211Message::reason_code_string_ = NULL;
64map<uint16_t, string> *Nl80211Message::status_code_string_ = NULL;
Wade Guthriebdcdaa72013-03-04 12:47:12 -080065uint16_t Nl80211Message::nl80211_message_type_ = kIllegalMessageType;
66
Wade Guthriebee87c22013-03-06 11:00:46 -080067// static
Paul Stewart2ddf2c62013-04-16 09:47:34 -070068uint16_t Nl80211Message::GetMessageType() {
69 return nl80211_message_type_;
70}
71
72// static
Wade Guthriebee87c22013-03-06 11:00:46 -080073void Nl80211Message::SetMessageType(uint16_t message_type) {
74 if (message_type == NetlinkMessage::kIllegalMessageType) {
75 LOG(FATAL) << "Absolutely need a legal message type for Nl80211 messages.";
76 }
77 nl80211_message_type_ = message_type;
78}
79
repo sync0efa9f02012-12-28 13:40:20 -080080bool Nl80211Message::InitFromNlmsg(const nlmsghdr *const_msg) {
81 if (!const_msg) {
82 LOG(ERROR) << "Null |msg| parameter";
Wade Guthrie0d438532012-05-18 14:18:50 -070083 return false;
84 }
Wade Guthriebdcdaa72013-03-04 12:47:12 -080085 ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
86 const_msg->nlmsg_len);
Wade Guthrie0d438532012-05-18 14:18:50 -070087
Wade Guthriebdcdaa72013-03-04 12:47:12 -080088 if (!InitAndStripHeader(&message)) {
89 return false;
90 }
repo sync0efa9f02012-12-28 13:40:20 -080091
92 // Attributes.
93 // Parse the attributes from the nl message payload into the 'tb' array.
94 nlattr *tb[NL80211_ATTR_MAX + 1];
Wade Guthriebdcdaa72013-03-04 12:47:12 -080095 nla_parse(tb, NL80211_ATTR_MAX,
96 reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
97 NULL);
repo sync0efa9f02012-12-28 13:40:20 -080098
Wade Guthrie0d438532012-05-18 14:18:50 -070099 for (int i = 0; i < NL80211_ATTR_MAX + 1; ++i) {
100 if (tb[i]) {
repo sync0efa9f02012-12-28 13:40:20 -0800101 // TODO(wdg): When Nl80211Messages instantiate their own attributes,
102 // this call should, instead, call |SetAttributeFromNlAttr|.
Wade Guthrieefe1f0c2013-02-26 17:42:01 -0800103 attributes_->CreateAndInitAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800104 i, tb[i], Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
Wade Guthrie0d438532012-05-18 14:18:50 -0700105 }
106 }
107
108 // Convert integer values provided by libnl (for example, from the
109 // NL80211_ATTR_STATUS_CODE or NL80211_ATTR_REASON_CODE attribute) into
110 // strings describing the status.
Wade Guthried4977f22012-08-22 12:37:54 -0700111 if (!reason_code_string_) {
112 reason_code_string_ = new map<uint16_t, string>;
113 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecified] =
114 "Unspecified reason";
115 (*reason_code_string_)[
116 IEEE_80211::kReasonCodePreviousAuthenticationInvalid] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700117 "Previous authentication no longer valid";
Wade Guthried4977f22012-08-22 12:37:54 -0700118 (*reason_code_string_)[IEEE_80211::kReasonCodeSenderHasLeft] =
119 "Deauthentcated because sending STA is leaving (or has left) IBSS or "
120 "ESS";
121 (*reason_code_string_)[IEEE_80211::kReasonCodeInactivity] =
122 "Disassociated due to inactivity";
123 (*reason_code_string_)[IEEE_80211::kReasonCodeTooManySTAs] =
124 "Disassociated because AP is unable to handle all currently associated "
125 "STAs";
126 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAuthenticated] =
127 "Class 2 frame received from nonauthenticated STA";
128 (*reason_code_string_)[IEEE_80211::kReasonCodeNonAssociated] =
129 "Class 3 frame received from nonassociated STA";
130 (*reason_code_string_)[IEEE_80211::kReasonCodeDisassociatedHasLeft] =
131 "Disassociated because sending STA is leaving (or has left) BSS";
132 (*reason_code_string_)[
133 IEEE_80211::kReasonCodeReassociationNotAuthenticated] =
134 "STA requesting (re)association is not authenticated with responding "
135 "STA";
136 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptablePowerCapability] =
137 "Disassociated because the information in the Power Capability "
138 "element is unacceptable";
139 (*reason_code_string_)[
140 IEEE_80211::kReasonCodeUnacceptableSupportedChannelInfo] =
141 "Disassociated because the information in the Supported Channels "
142 "element is unacceptable";
143 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidInfoElement] =
144 "Invalid information element, i.e., an information element defined in "
145 "this standard for which the content does not meet the specifications "
146 "in Clause 7";
147 (*reason_code_string_)[IEEE_80211::kReasonCodeMICFailure] =
148 "Message integrity code (MIC) failure";
149 (*reason_code_string_)[IEEE_80211::kReasonCode4WayTimeout] =
150 "4-Way Handshake timeout";
151 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupKeyHandshakeTimeout] =
152 "Group Key Handshake timeout";
153 (*reason_code_string_)[IEEE_80211::kReasonCodeDifferenIE] =
154 "Information element in 4-Way Handshake different from "
155 "(Re)Association Request/Probe Response/Beacon frame";
156 (*reason_code_string_)[IEEE_80211::kReasonCodeGroupCipherInvalid] =
157 "Invalid group cipher";
158 (*reason_code_string_)[IEEE_80211::kReasonCodePairwiseCipherInvalid] =
159 "Invalid pairwise cipher";
160 (*reason_code_string_)[IEEE_80211::kReasonCodeAkmpInvalid] =
161 "Invalid AKMP";
162 (*reason_code_string_)[IEEE_80211::kReasonCodeUnsupportedRsnIeVersion] =
163 "Unsupported RSN information element version";
164 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalidRsnIeCaps] =
165 "Invalid RSN information element capabilities";
166 (*reason_code_string_)[IEEE_80211::kReasonCode8021XAuth] =
167 "IEEE 802.1X authentication failed";
168 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteRejected] =
169 "Cipher suite rejected because of the security policy";
170 (*reason_code_string_)[IEEE_80211::kReasonCodeUnspecifiedQoS] =
171 "Disassociated for unspecified, QoS-related reason";
172 (*reason_code_string_)[IEEE_80211::kReasonCodeQoSBandwidth] =
173 "Disassociated because QoS AP lacks sufficient bandwidth for this "
174 "QoS STA";
175 (*reason_code_string_)[IEEE_80211::kReasonCodeiPoorConditions] =
176 "Disassociated because excessive number of frames need to be "
177 "acknowledged, but are not acknowledged due to AP transmissions "
178 "and/or poor channel conditions";
179 (*reason_code_string_)[IEEE_80211::kReasonCodeOutsideTxop] =
180 "Disassociated because STA is transmitting outside the limits of its "
181 "TXOPs";
182 (*reason_code_string_)[IEEE_80211::kReasonCodeStaLeaving] =
183 "Requested from peer STA as the STA is leaving the BSS (or resetting)";
184 (*reason_code_string_)[IEEE_80211::kReasonCodeUnacceptableMechanism] =
185 "Requested from peer STA as it does not want to use the mechanism";
186 (*reason_code_string_)[IEEE_80211::kReasonCodeSetupRequired] =
187 "Requested from peer STA as the STA received frames using the "
188 "mechanism for which a setup is required";
189 (*reason_code_string_)[IEEE_80211::kReasonCodeTimeout] =
190 "Requested from peer STA due to timeout";
191 (*reason_code_string_)[IEEE_80211::kReasonCodeCipherSuiteNotSupported] =
192 "Peer STA does not support the requested cipher suite";
193 (*reason_code_string_)[IEEE_80211::kReasonCodeInvalid] = "<INVALID REASON>";
194 }
195
196 if (!status_code_string_) {
197 status_code_string_ = new map<uint16_t, string>;
198 (*status_code_string_)[IEEE_80211::kStatusCodeSuccessful] = "Successful";
199 (*status_code_string_)[IEEE_80211::kStatusCodeFailure] =
200 "Unspecified failure";
201 (*status_code_string_)[IEEE_80211::kStatusCodeAllCapabilitiesNotSupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700202 "Cannot support all requested capabilities in the capability "
203 "information field";
Wade Guthried4977f22012-08-22 12:37:54 -0700204 (*status_code_string_)[IEEE_80211::kStatusCodeCantConfirmAssociation] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700205 "Reassociation denied due to inability to confirm that association "
206 "exists";
Wade Guthried4977f22012-08-22 12:37:54 -0700207 (*status_code_string_)[IEEE_80211::kStatusCodeAssociationDenied] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700208 "Association denied due to reason outside the scope of this standard";
Wade Guthried4977f22012-08-22 12:37:54 -0700209 (*status_code_string_)[
210 IEEE_80211::kStatusCodeAuthenticationUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700211 "Responding station does not support the specified authentication "
212 "algorithm";
Wade Guthried4977f22012-08-22 12:37:54 -0700213 (*status_code_string_)[IEEE_80211::kStatusCodeOutOfSequence] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700214 "Received an authentication frame with authentication transaction "
215 "sequence number out of expected sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700216 (*status_code_string_)[IEEE_80211::kStatusCodeChallengeFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700217 "Authentication rejected because of challenge failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700218 (*status_code_string_)[IEEE_80211::kStatusCodeFrameTimeout] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700219 "Authentication rejected due to timeout waiting for next frame in "
220 "sequence";
Wade Guthried4977f22012-08-22 12:37:54 -0700221 (*status_code_string_)[IEEE_80211::kStatusCodeMaxSta] =
222 "Association denied because AP is unable to handle additional "
223 "associated STA";
224 (*status_code_string_)[IEEE_80211::kStatusCodeDataRateUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700225 "Association denied due to requesting station not supporting all of "
226 "the data rates in the BSSBasicRateSet parameter";
Wade Guthried4977f22012-08-22 12:37:54 -0700227 (*status_code_string_)[IEEE_80211::kStatusCodeShortPreambleUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700228 "Association denied due to requesting station not supporting the "
229 "short preamble option";
Wade Guthried4977f22012-08-22 12:37:54 -0700230 (*status_code_string_)[IEEE_80211::kStatusCodePbccUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700231 "Association denied due to requesting station not supporting the PBCC "
232 "modulation option";
Wade Guthried4977f22012-08-22 12:37:54 -0700233 (*status_code_string_)[
234 IEEE_80211::kStatusCodeChannelAgilityUnsupported] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700235 "Association denied due to requesting station not supporting the "
236 "channel agility option";
Wade Guthried4977f22012-08-22 12:37:54 -0700237 (*status_code_string_)[IEEE_80211::kStatusCodeNeedSpectrumManagement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700238 "Association request rejected because Spectrum Management capability "
239 "is required";
Wade Guthried4977f22012-08-22 12:37:54 -0700240 (*status_code_string_)[
241 IEEE_80211::kStatusCodeUnacceptablePowerCapability] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700242 "Association request rejected because the information in the Power "
243 "Capability element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700244 (*status_code_string_)[
245 IEEE_80211::kStatusCodeUnacceptableSupportedChannelInfo] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700246 "Association request rejected because the information in the "
247 "Supported Channels element is unacceptable";
Wade Guthried4977f22012-08-22 12:37:54 -0700248 (*status_code_string_)[IEEE_80211::kStatusCodeShortTimeSlotRequired] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700249 "Association request rejected due to requesting station not "
Wade Guthried4977f22012-08-22 12:37:54 -0700250 "supporting the Short Slot Time option";
251 (*status_code_string_)[IEEE_80211::kStatusCodeDssOfdmRequired] =
252 "Association request rejected due to requesting station not "
253 "supporting the DSSS-OFDM option";
254 (*status_code_string_)[IEEE_80211::kStatusCodeQosFailure] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700255 "Unspecified, QoS related failure";
Wade Guthried4977f22012-08-22 12:37:54 -0700256 (*status_code_string_)[
257 IEEE_80211::kStatusCodeInsufficientBandwithForQsta] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700258 "Association denied due to QAP having insufficient bandwidth to handle "
259 "another QSTA";
Wade Guthried4977f22012-08-22 12:37:54 -0700260 (*status_code_string_)[IEEE_80211::kStatusCodePoorConditions] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700261 "Association denied due to poor channel conditions";
Wade Guthried4977f22012-08-22 12:37:54 -0700262 (*status_code_string_)[IEEE_80211::kStatusCodeQosNotSupported] =
263 "Association (with QoS BSS) denied due to requesting station not "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700264 "supporting the QoS facility";
Wade Guthried4977f22012-08-22 12:37:54 -0700265 (*status_code_string_)[IEEE_80211::kStatusCodeDeclined] =
266 "The request has been declined";
267 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidParameterValues] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700268 "The request has not been successful as one or more parameters have "
269 "invalid values";
Wade Guthried4977f22012-08-22 12:37:54 -0700270 (*status_code_string_)[IEEE_80211::kStatusCodeCannotBeHonored] =
271 "The TS has not been created because the request cannot be honored. "
Wade Guthrie64b4c142012-08-20 15:21:01 -0700272 "However, a suggested Tspec is provided so that the initiating QSTA "
273 "may attempt to send another TS with the suggested changes to the "
274 "TSpec";
Wade Guthried4977f22012-08-22 12:37:54 -0700275 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidInfoElement] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700276 "Invalid Information Element";
Wade Guthried4977f22012-08-22 12:37:54 -0700277 (*status_code_string_)[IEEE_80211::kStatusCodeGroupCipherInvalid] =
278 "Invalid Group Cipher";
279 (*status_code_string_)[IEEE_80211::kStatusCodePairwiseCipherInvalid] =
280 "Invalid Pairwise Cipher";
281 (*status_code_string_)[IEEE_80211::kStatusCodeAkmpInvalid] = "Invalid AKMP";
282 (*status_code_string_)[IEEE_80211::kStatusCodeUnsupportedRsnIeVersion] =
283 "Unsupported RSN Information Element version";
284 (*status_code_string_)[IEEE_80211::kStatusCodeInvalidRsnIeCaps] =
285 "Invalid RSN Information Element Capabilities";
286 (*status_code_string_)[IEEE_80211::kStatusCodeCipherSuiteRejected] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700287 "Cipher suite is rejected per security policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700288 (*status_code_string_)[IEEE_80211::kStatusCodeTsDelayNotMet] =
289 "The TS has not been created. However, the HC may be capable of "
290 "creating a TS, in response to a request, after the time indicated in "
291 "the TS Delay element";
292 (*status_code_string_)[IEEE_80211::kStatusCodeDirectLinkIllegal] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700293 "Direct link is not allowed in the BSS by policy";
Wade Guthried4977f22012-08-22 12:37:54 -0700294 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInBss] =
295 "Destination STA is not present within this BSS";
296 (*status_code_string_)[IEEE_80211::kStatusCodeStaNotInQsta] =
297 "The destination STA is not a QoS STA";
298 (*status_code_string_)[IEEE_80211::kStatusCodeExcessiveListenInterval] =
Wade Guthrie64b4c142012-08-20 15:21:01 -0700299 "Association denied because Listen Interval is too large";
Wade Guthried4977f22012-08-22 12:37:54 -0700300 (*status_code_string_)[IEEE_80211::kStatusCodeInvalid] = "<INVALID STATUS>";
Wade Guthrie0d438532012-05-18 14:18:50 -0700301 }
302
303 return true;
304}
305
Wade Guthrie0d438532012-05-18 14:18:50 -0700306// Helper function to provide a string for NL80211_ATTR_SCAN_FREQUENCIES.
repo syncdc085c82012-12-28 08:54:41 -0800307bool Nl80211Message::GetScanFrequenciesAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800308 int id, vector<uint32_t> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700309 if (!value) {
310 LOG(ERROR) << "Null |value| parameter";
311 return false;
312 }
313
314 value->clear();
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800315
316 AttributeListConstRefPtr frequency_list;
317 if (!const_attributes()->ConstGetNestedAttributeList(
318 NL80211_ATTR_SCAN_FREQUENCIES, &frequency_list) || !frequency_list) {
319 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_FREQUENCIES attribute";
repo syncd316eb72012-12-10 15:48:47 -0800320 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800321 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700322
Wade Guthrie480aada2013-04-25 15:16:34 -0700323 AttributeIdIterator freq_iter(*frequency_list);
324 for (; !freq_iter.AtEnd(); freq_iter.Advance()) {
325 uint32_t freq = 0;
326 if (frequency_list->GetU32AttributeValue(freq_iter.GetId(), &freq)) {
327 value->push_back(freq);
328 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700329 }
repo syncd316eb72012-12-10 15:48:47 -0800330 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700331}
332
333// Helper function to provide a string for NL80211_ATTR_SCAN_SSIDS.
repo syncdc085c82012-12-28 08:54:41 -0800334bool Nl80211Message::GetScanSsidsAttribute(
Wade Guthrie68da97c2013-02-26 13:09:35 -0800335 int id, vector<string> *value) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700336 if (!value) {
337 LOG(ERROR) << "Null |value| parameter";
338 return false;
339 }
340
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800341 AttributeListConstRefPtr ssid_list;
342 if (!const_attributes()->ConstGetNestedAttributeList(
343 NL80211_ATTR_SCAN_SSIDS, &ssid_list) || !ssid_list) {
344 LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_SSIDS attribute";
repo sync90ee0fa2012-12-18 10:08:08 -0800345 return false;
Wade Guthried3dfd6c2013-02-28 17:40:36 -0800346 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700347
Wade Guthrie480aada2013-04-25 15:16:34 -0700348 AttributeIdIterator ssid_iter(*ssid_list);
349 for (; !ssid_iter.AtEnd(); ssid_iter.Advance()) {
350 string ssid;
351 if (ssid_list->GetStringAttributeValue(ssid_iter.GetId(), &ssid)) {
352 value->push_back(ssid);
353 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700354 }
repo sync90ee0fa2012-12-18 10:08:08 -0800355 return true;
Wade Guthrie0d438532012-05-18 14:18:50 -0700356}
357
Wade Guthrie0d438532012-05-18 14:18:50 -0700358// static
repo syncdc085c82012-12-28 08:54:41 -0800359string Nl80211Message::StringFromReason(uint16_t status) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700360 map<uint16_t, string>::const_iterator match;
Wade Guthried4977f22012-08-22 12:37:54 -0700361 match = reason_code_string_->find(status);
362 if (match == reason_code_string_->end()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700363 string output;
Wade Guthried4977f22012-08-22 12:37:54 -0700364 if (status < IEEE_80211::kReasonCodeMax) {
365 StringAppendF(&output, "<Reserved Reason:%u>", status);
366 } else {
367 StringAppendF(&output, "<Unknown Reason:%u>", status);
368 }
Wade Guthrie0d438532012-05-18 14:18:50 -0700369 return output;
370 }
371 return match->second;
372}
373
Wade Guthried4977f22012-08-22 12:37:54 -0700374// static
repo syncdc085c82012-12-28 08:54:41 -0800375string Nl80211Message::StringFromStatus(uint16_t status) {
Wade Guthried4977f22012-08-22 12:37:54 -0700376 map<uint16_t, string>::const_iterator match;
377 match = status_code_string_->find(status);
378 if (match == status_code_string_->end()) {
379 string output;
380 if (status < IEEE_80211::kStatusCodeMax) {
381 StringAppendF(&output, "<Reserved Status:%u>", status);
382 } else {
383 StringAppendF(&output, "<Unknown Status:%u>", status);
384 }
385 return output;
386 }
387 return match->second;
388}
389
Wade Guthrie71872472013-03-05 10:33:38 -0800390// Nl80211Frame
391
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800392Nl80211Frame::Nl80211Frame(const ByteString &raw_frame)
Wade Guthrie92d06362013-04-25 15:41:30 -0700393 : frame_type_(kIllegalFrameType),
394 reason_(std::numeric_limits<uint16_t>::max()),
395 status_(std::numeric_limits<uint16_t>::max()),
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800396 frame_(raw_frame) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700397 const IEEE_80211::ieee80211_frame *frame =
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800398 reinterpret_cast<const IEEE_80211::ieee80211_frame *>(
399 frame_.GetConstData());
Wade Guthrie0d438532012-05-18 14:18:50 -0700400
401 // Now, let's populate the other stuff.
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800402 if (frame_.GetLength() >= kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700403 mac_from_ =
Wade Guthrie2193b232013-06-05 17:09:07 -0700404 Nl80211AttributeMac::StringFromMacAddress(&frame->destination_mac[0]);
405 mac_to_ = Nl80211AttributeMac::StringFromMacAddress(&frame->source_mac[0]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700406 frame_type_ = frame->frame_control & kFrameTypeMask;
407
408 switch (frame_type_) {
409 case kAssocResponseFrameType:
410 case kReassocResponseFrameType:
411 status_ = le16toh(frame->u.associate_response.status_code);
412 break;
413
414 case kAuthFrameType:
415 status_ = le16toh(frame->u.authentiate_message.status_code);
416 break;
417
418 case kDisassocFrameType:
419 case kDeauthFrameType:
Wade Guthried4977f22012-08-22 12:37:54 -0700420 reason_ = le16toh(frame->u.deauthentiate_message.reason_code);
Wade Guthrie0d438532012-05-18 14:18:50 -0700421 break;
422
423 default:
424 break;
425 }
426 }
427}
428
Wade Guthried4977f22012-08-22 12:37:54 -0700429bool Nl80211Frame::ToString(string *output) const {
Wade Guthrie0d438532012-05-18 14:18:50 -0700430 if (!output) {
431 LOG(ERROR) << "NULL |output|";
432 return false;
433 }
434
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800435 if (frame_.IsEmpty()) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700436 output->append(" [no frame]");
437 return true;
438 }
439
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800440 if (frame_.GetLength() < kMinimumFrameByteCount) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700441 output->append(" [invalid frame: ");
442 } else {
443 StringAppendF(output, " %s -> %s", mac_from_.c_str(), mac_to_.c_str());
444
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800445 switch (frame_.GetConstData()[0] & kFrameTypeMask) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700446 case kAssocResponseFrameType:
447 StringAppendF(output, "; AssocResponse status: %u: %s",
448 status_,
repo syncdc085c82012-12-28 08:54:41 -0800449 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700450 break;
451 case kReassocResponseFrameType:
452 StringAppendF(output, "; ReassocResponse status: %u: %s",
453 status_,
repo syncdc085c82012-12-28 08:54:41 -0800454 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700455 break;
456 case kAuthFrameType:
457 StringAppendF(output, "; Auth status: %u: %s",
458 status_,
repo syncdc085c82012-12-28 08:54:41 -0800459 Nl80211Message::StringFromStatus(status_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700460 break;
461
462 case kDisassocFrameType:
463 StringAppendF(output, "; Disassoc reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700464 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800465 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700466 break;
467 case kDeauthFrameType:
468 StringAppendF(output, "; Deauth reason %u: %s",
Wade Guthried4977f22012-08-22 12:37:54 -0700469 reason_,
repo syncdc085c82012-12-28 08:54:41 -0800470 Nl80211Message::StringFromReason(reason_).c_str());
Wade Guthrie0d438532012-05-18 14:18:50 -0700471 break;
472
473 default:
474 break;
475 }
476 output->append(" [frame: ");
477 }
478
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800479 const unsigned char *frame = frame_.GetConstData();
480 for (size_t i = 0; i < frame_.GetLength(); ++i) {
481 StringAppendF(output, "%02x, ", frame[i]);
Wade Guthrie0d438532012-05-18 14:18:50 -0700482 }
483 output->append("]");
484
485 return true;
486}
487
Wade Guthried4977f22012-08-22 12:37:54 -0700488bool Nl80211Frame::IsEqual(const Nl80211Frame &other) const {
Wade Guthrie8343f7f2012-12-04 13:52:32 -0800489 return frame_.Equals(other.frame_);
Wade Guthrie0d438532012-05-18 14:18:50 -0700490}
491
492//
repo syncdc085c82012-12-28 08:54:41 -0800493// Specific Nl80211Message types.
Wade Guthrie0d438532012-05-18 14:18:50 -0700494//
495
496const uint8_t AssociateMessage::kCommand = NL80211_CMD_ASSOCIATE;
497const char AssociateMessage::kCommandString[] = "NL80211_CMD_ASSOCIATE";
498
Wade Guthrie0d438532012-05-18 14:18:50 -0700499const uint8_t AuthenticateMessage::kCommand = NL80211_CMD_AUTHENTICATE;
500const char AuthenticateMessage::kCommandString[] = "NL80211_CMD_AUTHENTICATE";
501
Wade Guthrie0d438532012-05-18 14:18:50 -0700502const uint8_t CancelRemainOnChannelMessage::kCommand =
503 NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL;
504const char CancelRemainOnChannelMessage::kCommandString[] =
505 "NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL";
506
Wade Guthrie0d438532012-05-18 14:18:50 -0700507const uint8_t ConnectMessage::kCommand = NL80211_CMD_CONNECT;
508const char ConnectMessage::kCommandString[] = "NL80211_CMD_CONNECT";
509
Wade Guthrie0d438532012-05-18 14:18:50 -0700510const uint8_t DeauthenticateMessage::kCommand = NL80211_CMD_DEAUTHENTICATE;
511const char DeauthenticateMessage::kCommandString[] =
512 "NL80211_CMD_DEAUTHENTICATE";
513
Wade Guthrie0d438532012-05-18 14:18:50 -0700514const uint8_t DeleteStationMessage::kCommand = NL80211_CMD_DEL_STATION;
515const char DeleteStationMessage::kCommandString[] = "NL80211_CMD_DEL_STATION";
516
Wade Guthrie0d438532012-05-18 14:18:50 -0700517const uint8_t DisassociateMessage::kCommand = NL80211_CMD_DISASSOCIATE;
518const char DisassociateMessage::kCommandString[] = "NL80211_CMD_DISASSOCIATE";
519
Wade Guthrie0d438532012-05-18 14:18:50 -0700520const uint8_t DisconnectMessage::kCommand = NL80211_CMD_DISCONNECT;
521const char DisconnectMessage::kCommandString[] = "NL80211_CMD_DISCONNECT";
522
Wade Guthrie0d438532012-05-18 14:18:50 -0700523const uint8_t FrameTxStatusMessage::kCommand = NL80211_CMD_FRAME_TX_STATUS;
524const char FrameTxStatusMessage::kCommandString[] =
525 "NL80211_CMD_FRAME_TX_STATUS";
526
repo sync0efa9f02012-12-28 13:40:20 -0800527const uint8_t GetRegMessage::kCommand = NL80211_CMD_GET_REG;
528const char GetRegMessage::kCommandString[] = "NL80211_CMD_GET_REG";
529
Wade Guthrie1f355e82013-04-11 15:46:12 -0700530const uint8_t GetWiphyMessage::kCommand = NL80211_CMD_GET_WIPHY;
531const char GetWiphyMessage::kCommandString[] = "NL80211_CMD_GET_WIPHY";
532
Wade Guthrie92d06362013-04-25 15:41:30 -0700533GetWiphyMessage::GetWiphyMessage() : Nl80211Message(kCommand, kCommandString) {
534 attributes()->CreateAttribute(
535 NL80211_ATTR_IFINDEX, Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
536}
537
Wade Guthrie0d438532012-05-18 14:18:50 -0700538const uint8_t JoinIbssMessage::kCommand = NL80211_CMD_JOIN_IBSS;
539const char JoinIbssMessage::kCommandString[] = "NL80211_CMD_JOIN_IBSS";
540
Wade Guthrie0d438532012-05-18 14:18:50 -0700541const uint8_t MichaelMicFailureMessage::kCommand =
542 NL80211_CMD_MICHAEL_MIC_FAILURE;
543const char MichaelMicFailureMessage::kCommandString[] =
544 "NL80211_CMD_MICHAEL_MIC_FAILURE";
545
Wade Guthrie0d438532012-05-18 14:18:50 -0700546const uint8_t NewScanResultsMessage::kCommand = NL80211_CMD_NEW_SCAN_RESULTS;
547const char NewScanResultsMessage::kCommandString[] =
548 "NL80211_CMD_NEW_SCAN_RESULTS";
549
Wade Guthrie0d438532012-05-18 14:18:50 -0700550const uint8_t NewStationMessage::kCommand = NL80211_CMD_NEW_STATION;
551const char NewStationMessage::kCommandString[] = "NL80211_CMD_NEW_STATION";
552
Wade Guthrie1f355e82013-04-11 15:46:12 -0700553const uint8_t NewWiphyMessage::kCommand = NL80211_CMD_NEW_WIPHY;
554const char NewWiphyMessage::kCommandString[] = "NL80211_CMD_NEW_WIPHY";
Wade Guthrie0d438532012-05-18 14:18:50 -0700555
Wade Guthrie0d438532012-05-18 14:18:50 -0700556const uint8_t NotifyCqmMessage::kCommand = NL80211_CMD_NOTIFY_CQM;
557const char NotifyCqmMessage::kCommandString[] = "NL80211_CMD_NOTIFY_CQM";
558
Wade Guthrie0d438532012-05-18 14:18:50 -0700559const uint8_t PmksaCandidateMessage::kCommand = NL80211_ATTR_PMKSA_CANDIDATE;
560const char PmksaCandidateMessage::kCommandString[] =
561 "NL80211_ATTR_PMKSA_CANDIDATE";
562
Wade Guthrie0d438532012-05-18 14:18:50 -0700563const uint8_t RegBeaconHintMessage::kCommand = NL80211_CMD_REG_BEACON_HINT;
564const char RegBeaconHintMessage::kCommandString[] =
565 "NL80211_CMD_REG_BEACON_HINT";
566
Wade Guthrie0d438532012-05-18 14:18:50 -0700567const uint8_t RegChangeMessage::kCommand = NL80211_CMD_REG_CHANGE;
568const char RegChangeMessage::kCommandString[] = "NL80211_CMD_REG_CHANGE";
569
Wade Guthrie0d438532012-05-18 14:18:50 -0700570const uint8_t RemainOnChannelMessage::kCommand = NL80211_CMD_REMAIN_ON_CHANNEL;
571const char RemainOnChannelMessage::kCommandString[] =
572 "NL80211_CMD_REMAIN_ON_CHANNEL";
573
Wade Guthrie0d438532012-05-18 14:18:50 -0700574const uint8_t RoamMessage::kCommand = NL80211_CMD_ROAM;
575const char RoamMessage::kCommandString[] = "NL80211_CMD_ROAM";
576
Wade Guthrie0d438532012-05-18 14:18:50 -0700577const uint8_t ScanAbortedMessage::kCommand = NL80211_CMD_SCAN_ABORTED;
578const char ScanAbortedMessage::kCommandString[] = "NL80211_CMD_SCAN_ABORTED";
579
Wade Guthrie71872472013-03-05 10:33:38 -0800580const uint8_t GetScanMessage::kCommand = NL80211_CMD_GET_SCAN;
581const char GetScanMessage::kCommandString[] = "NL80211_CMD_GET_SCAN";
582
Wade Guthrie0d438532012-05-18 14:18:50 -0700583const uint8_t TriggerScanMessage::kCommand = NL80211_CMD_TRIGGER_SCAN;
584const char TriggerScanMessage::kCommandString[] = "NL80211_CMD_TRIGGER_SCAN";
585
Wade Guthrieb9c3feb2013-04-25 16:31:19 -0700586TriggerScanMessage::TriggerScanMessage()
Wade Guthrie2623f1a2013-05-14 15:14:54 -0700587 : Nl80211Message(kCommand, kCommandString) {
Wade Guthrieb9c3feb2013-04-25 16:31:19 -0700588 attributes()->CreateAttribute(
589 NL80211_ATTR_IFINDEX, Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
590 attributes()->CreateAttribute(
591 NL80211_ATTR_SCAN_FREQUENCIES,
592 Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
593 attributes()->CreateAttribute(
594 NL80211_ATTR_SCAN_SSIDS,
595 Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
596}
597
Wade Guthrie0d438532012-05-18 14:18:50 -0700598const uint8_t UnprotDeauthenticateMessage::kCommand =
599 NL80211_CMD_UNPROT_DEAUTHENTICATE;
600const char UnprotDeauthenticateMessage::kCommandString[] =
601 "NL80211_CMD_UNPROT_DEAUTHENTICATE";
602
Wade Guthrie0d438532012-05-18 14:18:50 -0700603const uint8_t UnprotDisassociateMessage::kCommand =
604 NL80211_CMD_UNPROT_DISASSOCIATE;
605const char UnprotDisassociateMessage::kCommandString[] =
606 "NL80211_CMD_UNPROT_DISASSOCIATE";
607
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700608GetInterfaceMessage::GetInterfaceMessage()
609 : Nl80211Message(kCommand, kCommandString) {
610 attributes()->CreateAttribute(
611 NL80211_ATTR_IFINDEX, Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
612}
613
614const uint8_t GetInterfaceMessage::kCommand = NL80211_CMD_GET_INTERFACE;
615const char GetInterfaceMessage::kCommandString[] = "NL80211_CMD_GET_INTERFACE";
616
617const uint8_t NewInterfaceMessage::kCommand = NL80211_CMD_NEW_INTERFACE;
618const char NewInterfaceMessage::kCommandString[] = "NL80211_CMD_NEW_INTERFACE";
619
Wade Guthrie12f113a2013-03-12 17:15:46 -0700620// static
621NetlinkMessage *Nl80211Message::CreateMessage(const nlmsghdr *const_msg) {
622 if (!const_msg) {
623 LOG(ERROR) << "NULL |const_msg| parameter";
624 return NULL;
625 }
626 // Casting away constness since, while nlmsg_data doesn't change its
627 // parameter, it also doesn't declare its paramenter as const.
628 nlmsghdr *msg = const_cast<nlmsghdr *>(const_msg);
629 void *payload = nlmsg_data(msg);
630 genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);
631 scoped_ptr<NetlinkMessage> message;
632
633 switch (gnlh->cmd) {
634 case AssociateMessage::kCommand:
635 return new AssociateMessage();
636 case AuthenticateMessage::kCommand:
637 return new AuthenticateMessage();
638 case CancelRemainOnChannelMessage::kCommand:
639 return new CancelRemainOnChannelMessage();
640 case ConnectMessage::kCommand:
641 return new ConnectMessage();
642 case DeauthenticateMessage::kCommand:
643 return new DeauthenticateMessage();
644 case DeleteStationMessage::kCommand:
645 return new DeleteStationMessage();
646 case DisassociateMessage::kCommand:
647 return new DisassociateMessage();
648 case DisconnectMessage::kCommand:
649 return new DisconnectMessage();
650 case FrameTxStatusMessage::kCommand:
651 return new FrameTxStatusMessage();
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700652 case GetInterfaceMessage::kCommand:
653 return new GetInterfaceMessage();
Wade Guthrie12f113a2013-03-12 17:15:46 -0700654 case GetRegMessage::kCommand:
655 return new GetRegMessage();
Wade Guthrie1f355e82013-04-11 15:46:12 -0700656 case GetWiphyMessage::kCommand:
657 return new GetWiphyMessage();
Wade Guthrie12f113a2013-03-12 17:15:46 -0700658 case JoinIbssMessage::kCommand:
659 return new JoinIbssMessage();
660 case MichaelMicFailureMessage::kCommand:
661 return new MichaelMicFailureMessage();
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700662 case NewInterfaceMessage::kCommand:
663 return new NewInterfaceMessage();
Wade Guthrie12f113a2013-03-12 17:15:46 -0700664 case NewScanResultsMessage::kCommand:
665 return new NewScanResultsMessage();
666 case NewStationMessage::kCommand:
667 return new NewStationMessage();
Wade Guthrie1f355e82013-04-11 15:46:12 -0700668 case NewWiphyMessage::kCommand:
669 return new NewWiphyMessage();
Wade Guthrie12f113a2013-03-12 17:15:46 -0700670 case NotifyCqmMessage::kCommand:
671 return new NotifyCqmMessage();
672 case PmksaCandidateMessage::kCommand:
673 return new PmksaCandidateMessage();
674 case RegBeaconHintMessage::kCommand:
675 return new RegBeaconHintMessage();
676 case RegChangeMessage::kCommand:
677 return new RegChangeMessage();
678 case RemainOnChannelMessage::kCommand:
679 return new RemainOnChannelMessage();
680 case RoamMessage::kCommand:
681 return new RoamMessage();
682 case ScanAbortedMessage::kCommand:
683 return new ScanAbortedMessage();
684 case TriggerScanMessage::kCommand:
685 return new TriggerScanMessage();
686 case UnprotDeauthenticateMessage::kCommand:
687 return new UnprotDeauthenticateMessage();
688 case UnprotDisassociateMessage::kCommand:
689 return new UnprotDisassociateMessage();
690 default:
Wade Guthrie40d992c2013-04-19 11:10:11 -0700691 LOG(WARNING) << StringPrintf(
692 "Unknown/unhandled netlink nl80211 message 0x%02x", gnlh->cmd);
693 return new UnknownNl80211Message(gnlh->cmd);
Wade Guthrie12f113a2013-03-12 17:15:46 -0700694 break;
695 }
696 return NULL;
697}
698
Wade Guthrie0d438532012-05-18 14:18:50 -0700699//
Wade Guthrie12f113a2013-03-12 17:15:46 -0700700// Data Collector
701//
702
repo syncdc085c82012-12-28 08:54:41 -0800703Nl80211MessageDataCollector *
704 Nl80211MessageDataCollector::GetInstance() {
Wade Guthrie0d438532012-05-18 14:18:50 -0700705 return g_datacollector.Pointer();
706}
707
repo syncdc085c82012-12-28 08:54:41 -0800708Nl80211MessageDataCollector::Nl80211MessageDataCollector() {
Wade Guthrie0d438532012-05-18 14:18:50 -0700709 need_to_print[NL80211_ATTR_PMKSA_CANDIDATE] = true;
710 need_to_print[NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL] = true;
711 need_to_print[NL80211_CMD_DEL_STATION] = true;
712 need_to_print[NL80211_CMD_FRAME_TX_STATUS] = true;
713 need_to_print[NL80211_CMD_JOIN_IBSS] = true;
714 need_to_print[NL80211_CMD_MICHAEL_MIC_FAILURE] = true;
715 need_to_print[NL80211_CMD_NEW_WIPHY] = true;
716 need_to_print[NL80211_CMD_REG_BEACON_HINT] = true;
717 need_to_print[NL80211_CMD_REG_CHANGE] = true;
718 need_to_print[NL80211_CMD_REMAIN_ON_CHANNEL] = true;
719 need_to_print[NL80211_CMD_ROAM] = true;
720 need_to_print[NL80211_CMD_SCAN_ABORTED] = true;
721 need_to_print[NL80211_CMD_UNPROT_DEAUTHENTICATE] = true;
722 need_to_print[NL80211_CMD_UNPROT_DISASSOCIATE] = true;
723}
724
repo syncdc085c82012-12-28 08:54:41 -0800725void Nl80211MessageDataCollector::CollectDebugData(
726 const Nl80211Message &message, nlmsghdr *msg) {
Wade Guthrie0d438532012-05-18 14:18:50 -0700727 if (!msg) {
728 LOG(ERROR) << "NULL |msg| parameter";
729 return;
730 }
731
732 bool doit = false;
733
734 map<uint8_t, bool>::const_iterator node;
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800735 node = need_to_print.find(message.command());
Wade Guthrie0d438532012-05-18 14:18:50 -0700736 if (node != need_to_print.end())
737 doit = node->second;
738
739 if (doit) {
Wade Guthried6153612012-08-23 11:36:14 -0700740 LOG(INFO) << "@@const unsigned char "
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800741 << "k" << message.command_string()
Wade Guthried6153612012-08-23 11:36:14 -0700742 << "[] = {";
Wade Guthrie0d438532012-05-18 14:18:50 -0700743
Christopher Wileyefd521f2012-11-07 17:32:46 -0800744 int payload_bytes = nlmsg_datalen(msg);
Wade Guthrie0d438532012-05-18 14:18:50 -0700745
746 size_t bytes = nlmsg_total_size(payload_bytes);
747 unsigned char *rawdata = reinterpret_cast<unsigned char *>(msg);
Wade Guthried4977f22012-08-22 12:37:54 -0700748 for (size_t i = 0; i < bytes; ++i) {
Wade Guthried6153612012-08-23 11:36:14 -0700749 LOG(INFO) << " 0x"
Wade Guthrie0d438532012-05-18 14:18:50 -0700750 << std::hex << std::setfill('0') << std::setw(2)
751 << + rawdata[i] << ",";
752 }
Wade Guthried6153612012-08-23 11:36:14 -0700753 LOG(INFO) << "};";
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800754 need_to_print[message.command()] = false;
Wade Guthrie0d438532012-05-18 14:18:50 -0700755 }
756}
757
758} // namespace shill.