1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/net/netlink_attribute.h"
18
19 #include <linux/genetlink.h>
20
21 #include <cctype>
22 #include <map>
23 #include <memory>
24 #include <string>
25
26 #include <base/format_macros.h>
27 #include <base/logging.h>
28 #include <base/strings/stringprintf.h>
29
30 #include "shill/net/attribute_list.h"
31 #include "shill/net/control_netlink_attribute.h"
32 #include "shill/net/netlink_message.h"
33 #include "shill/net/nl80211_attribute.h"
34
35 using std::map;
36 using std::string;
37 using std::unique_ptr;
38
39 using base::StringAppendF;
40 using base::StringPrintf;
41
42 namespace shill {
43
NetlinkAttribute(int id,const char * id_string,Type datatype,const char * datatype_string)44 NetlinkAttribute::NetlinkAttribute(int id,
45 const char* id_string,
46 Type datatype,
47 const char* datatype_string)
48 : has_a_value_(false), id_(id), id_string_(id_string), datatype_(datatype),
49 datatype_string_(datatype_string) {}
50
51 // static
NewNl80211AttributeFromId(NetlinkMessage::MessageContext context,int id)52 NetlinkAttribute* NetlinkAttribute::NewNl80211AttributeFromId(
53 NetlinkMessage::MessageContext context, int id) {
54 unique_ptr<NetlinkAttribute> attr;
55 switch (id) {
56 case NL80211_ATTR_BSS:
57 attr.reset(new Nl80211AttributeBss());
58 break;
59 case NL80211_ATTR_CIPHER_SUITES:
60 attr.reset(new Nl80211AttributeCipherSuites());
61 break;
62 case NL80211_ATTR_CONTROL_PORT_ETHERTYPE:
63 attr.reset(new Nl80211AttributeControlPortEthertype());
64 break;
65 case NL80211_ATTR_COOKIE:
66 attr.reset(new Nl80211AttributeCookie());
67 break;
68 case NL80211_ATTR_CQM:
69 attr.reset(new Nl80211AttributeCqm());
70 break;
71 case NL80211_ATTR_DEVICE_AP_SME:
72 attr.reset(new Nl80211AttributeDeviceApSme());
73 break;
74 case NL80211_ATTR_DFS_REGION:
75 attr.reset(new Nl80211AttributeDfsRegion());
76 break;
77 case NL80211_ATTR_DISCONNECTED_BY_AP:
78 attr.reset(new Nl80211AttributeDisconnectedByAp());
79 break;
80 case NL80211_ATTR_DURATION:
81 attr.reset(new Nl80211AttributeDuration());
82 break;
83 case NL80211_ATTR_FEATURE_FLAGS:
84 attr.reset(new Nl80211AttributeFeatureFlags());
85 break;
86 case NL80211_ATTR_FRAME:
87 attr.reset(new Nl80211AttributeFrame());
88 break;
89 case NL80211_ATTR_GENERATION:
90 attr.reset(new Nl80211AttributeGeneration());
91 break;
92 case NL80211_ATTR_HT_CAPABILITY_MASK:
93 attr.reset(new Nl80211AttributeHtCapabilityMask());
94 break;
95 case NL80211_ATTR_IFINDEX:
96 attr.reset(new Nl80211AttributeIfindex());
97 break;
98 case NL80211_ATTR_IFTYPE:
99 attr.reset(new Nl80211AttributeIftype());
100 break;
101 case NL80211_ATTR_KEY_IDX:
102 attr.reset(new Nl80211AttributeKeyIdx());
103 break;
104 case NL80211_ATTR_KEY_SEQ:
105 attr.reset(new Nl80211AttributeKeySeq());
106 break;
107 case NL80211_ATTR_KEY_TYPE:
108 attr.reset(new Nl80211AttributeKeyType());
109 break;
110 case NL80211_ATTR_MAC:
111 attr.reset(new Nl80211AttributeMac());
112 break;
113 case NL80211_ATTR_MAX_MATCH_SETS:
114 attr.reset(new Nl80211AttributeMaxMatchSets());
115 break;
116 case NL80211_ATTR_MAX_NUM_PMKIDS:
117 attr.reset(new Nl80211AttributeMaxNumPmkids());
118 break;
119 case NL80211_ATTR_MAX_NUM_SCAN_SSIDS:
120 attr.reset(new Nl80211AttributeMaxNumScanSsids());
121 break;
122 case NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS:
123 attr.reset(new Nl80211AttributeMaxNumSchedScanSsids());
124 break;
125 case NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION:
126 attr.reset(new Nl80211AttributeMaxRemainOnChannelDuration());
127 break;
128 case NL80211_ATTR_MAX_SCAN_IE_LEN:
129 attr.reset(new Nl80211AttributeMaxScanIeLen());
130 break;
131 case NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN:
132 attr.reset(new Nl80211AttributeMaxSchedScanIeLen());
133 break;
134 case NL80211_ATTR_OFFCHANNEL_TX_OK:
135 attr.reset(new Nl80211AttributeOffchannelTxOk());
136 break;
137 case NL80211_ATTR_PROBE_RESP_OFFLOAD:
138 attr.reset(new Nl80211AttributeProbeRespOffload());
139 break;
140 case NL80211_ATTR_REASON_CODE:
141 attr.reset(new Nl80211AttributeReasonCode());
142 break;
143 case NL80211_ATTR_REG_ALPHA2:
144 attr.reset(new Nl80211AttributeRegAlpha2());
145 break;
146 case NL80211_ATTR_REG_INITIATOR:
147 attr.reset(new Nl80211AttributeRegInitiator());
148 break;
149 case NL80211_ATTR_REG_RULES:
150 attr.reset(new Nl80211AttributeRegRules());
151 break;
152 case NL80211_ATTR_REG_TYPE:
153 attr.reset(new Nl80211AttributeRegType());
154 break;
155 case NL80211_ATTR_RESP_IE:
156 attr.reset(new Nl80211AttributeRespIe());
157 break;
158 case NL80211_ATTR_ROAM_SUPPORT:
159 attr.reset(new Nl80211AttributeRoamSupport());
160 break;
161 case NL80211_ATTR_SCAN_FREQUENCIES:
162 attr.reset(new Nl80211AttributeScanFrequencies());
163 break;
164 case NL80211_ATTR_SCAN_SSIDS:
165 attr.reset(new Nl80211AttributeScanSsids());
166 break;
167 case NL80211_ATTR_STA_INFO:
168 attr.reset(new Nl80211AttributeStaInfo());
169 break;
170 case NL80211_ATTR_STATUS_CODE:
171 attr.reset(new Nl80211AttributeStatusCode());
172 break;
173 case NL80211_ATTR_SUPPORT_AP_UAPSD:
174 attr.reset(new Nl80211AttributeSupportApUapsd());
175 break;
176 case NL80211_ATTR_SUPPORT_IBSS_RSN:
177 attr.reset(new Nl80211AttributeSupportIbssRsn());
178 break;
179 case NL80211_ATTR_SUPPORT_MESH_AUTH:
180 attr.reset(new Nl80211AttributeSupportMeshAuth());
181 break;
182 case NL80211_ATTR_SUPPORTED_IFTYPES:
183 attr.reset(new Nl80211AttributeSupportedIftypes());
184 break;
185 case NL80211_ATTR_TDLS_EXTERNAL_SETUP:
186 attr.reset(new Nl80211AttributeTdlsExternalSetup());
187 break;
188 case NL80211_ATTR_TDLS_SUPPORT:
189 attr.reset(new Nl80211AttributeTdlsSupport());
190 break;
191 case NL80211_ATTR_TIMED_OUT:
192 attr.reset(new Nl80211AttributeTimedOut());
193 break;
194 case NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX:
195 attr.reset(new Nl80211AttributeWiphyAntennaAvailRx());
196 break;
197 case NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX:
198 attr.reset(new Nl80211AttributeWiphyAntennaAvailTx());
199 break;
200 case NL80211_ATTR_WIPHY_ANTENNA_RX:
201 attr.reset(new Nl80211AttributeWiphyAntennaRx());
202 break;
203 case NL80211_ATTR_WIPHY_ANTENNA_TX:
204 attr.reset(new Nl80211AttributeWiphyAntennaTx());
205 break;
206 case NL80211_ATTR_WIPHY_BANDS:
207 attr.reset(new Nl80211AttributeWiphyBands());
208 break;
209 case NL80211_ATTR_WIPHY_COVERAGE_CLASS:
210 attr.reset(new Nl80211AttributeWiphyCoverageClass());
211 break;
212 case NL80211_ATTR_WIPHY_FRAG_THRESHOLD:
213 attr.reset(new Nl80211AttributeWiphyFragThreshold());
214 break;
215 case NL80211_ATTR_WIPHY_FREQ:
216 attr.reset(new Nl80211AttributeWiphyFreq());
217 break;
218 case NL80211_ATTR_WIPHY_CHANNEL_TYPE:
219 attr.reset(new Nl80211AttributeChannelType());
220 break;
221 case NL80211_ATTR_CHANNEL_WIDTH:
222 attr.reset(new Nl80211AttributeChannelWidth());
223 break;
224 case NL80211_ATTR_CENTER_FREQ1:
225 attr.reset(new Nl80211AttributeCenterFreq1());
226 break;
227 case NL80211_ATTR_CENTER_FREQ2:
228 attr.reset(new Nl80211AttributeCenterFreq2());
229 break;
230 case NL80211_ATTR_WIPHY:
231 attr.reset(new Nl80211AttributeWiphy());
232 break;
233 case NL80211_ATTR_WIPHY_NAME:
234 attr.reset(new Nl80211AttributeWiphyName());
235 break;
236 case NL80211_ATTR_WIPHY_RETRY_LONG:
237 attr.reset(new Nl80211AttributeWiphyRetryLong());
238 break;
239 case NL80211_ATTR_WIPHY_RETRY_SHORT:
240 attr.reset(new Nl80211AttributeWiphyRetryShort());
241 break;
242 case NL80211_ATTR_WIPHY_RTS_THRESHOLD:
243 attr.reset(new Nl80211AttributeWiphyRtsThreshold());
244 break;
245 #if !defined(DISABLE_WAKE_ON_WIFI)
246 case NL80211_ATTR_WOWLAN_TRIGGERS:
247 attr.reset(new Nl80211AttributeWowlanTriggers(context));
248 break;
249 case NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED:
250 attr.reset(new Nl80211AttributeWowlanTriggersSupported());
251 break;
252 #endif // DISABLE_WAKE_ON_WIFI
253 case NL80211_ATTR_SURVEY_INFO:
254 attr.reset(new Nl80211AttributeSurveyInfo());
255 break;
256 default:
257 attr.reset(new NetlinkAttributeGeneric(id));
258 break;
259 }
260 return attr.release();
261 }
262
263 // static
NewControlAttributeFromId(int id)264 NetlinkAttribute* NetlinkAttribute::NewControlAttributeFromId(int id) {
265 unique_ptr<NetlinkAttribute> attr;
266 switch (id) {
267 case CTRL_ATTR_FAMILY_ID:
268 attr.reset(new ControlAttributeFamilyId());
269 break;
270 case CTRL_ATTR_FAMILY_NAME:
271 attr.reset(new ControlAttributeFamilyName());
272 break;
273 case CTRL_ATTR_VERSION:
274 attr.reset(new ControlAttributeVersion());
275 break;
276 case CTRL_ATTR_HDRSIZE:
277 attr.reset(new ControlAttributeHdrSize());
278 break;
279 case CTRL_ATTR_MAXATTR:
280 attr.reset(new ControlAttributeMaxAttr());
281 break;
282 case CTRL_ATTR_OPS:
283 attr.reset(new ControlAttributeAttrOps());
284 break;
285 case CTRL_ATTR_MCAST_GROUPS:
286 attr.reset(new ControlAttributeMcastGroups());
287 break;
288 default:
289 attr.reset(new NetlinkAttributeGeneric(id));
290 break;
291 }
292 return attr.release();
293 }
294
295 // Duplicate attribute data, store in map indexed on |id|.
InitFromValue(const ByteString & input)296 bool NetlinkAttribute::InitFromValue(const ByteString& input) {
297 data_ = input;
298 return true;
299 }
300
GetU8Value(uint8_t * value) const301 bool NetlinkAttribute::GetU8Value(uint8_t* value) const {
302 LOG(ERROR) << "Attribute is not of type 'U8'";
303 return false;
304 }
305
SetU8Value(uint8_t value)306 bool NetlinkAttribute::SetU8Value(uint8_t value) {
307 LOG(ERROR) << "Attribute is not of type 'U8'";
308 return false;
309 }
310
GetU16Value(uint16_t * value) const311 bool NetlinkAttribute::GetU16Value(uint16_t* value) const {
312 LOG(ERROR) << "Attribute is not of type 'U16'";
313 return false;
314 }
315
SetU16Value(uint16_t value)316 bool NetlinkAttribute::SetU16Value(uint16_t value) {
317 LOG(ERROR) << "Attribute is not of type 'U16'";
318 return false;
319 }
320
GetU32Value(uint32_t * value) const321 bool NetlinkAttribute::GetU32Value(uint32_t* value) const {
322 LOG(ERROR) << "Attribute is not of type 'U32'";
323 return false;
324 }
325
SetU32Value(uint32_t value)326 bool NetlinkAttribute::SetU32Value(uint32_t value) {
327 LOG(ERROR) << "Attribute is not of type 'U32'";
328 return false;
329 }
330
GetU64Value(uint64_t * value) const331 bool NetlinkAttribute::GetU64Value(uint64_t* value) const {
332 LOG(ERROR) << "Attribute is not of type 'U64'";
333 return false;
334 }
335
SetU64Value(uint64_t value)336 bool NetlinkAttribute::SetU64Value(uint64_t value) {
337 LOG(ERROR) << "Attribute is not of type 'U64'";
338 return false;
339 }
340
GetFlagValue(bool * value) const341 bool NetlinkAttribute::GetFlagValue(bool* value) const {
342 LOG(ERROR) << "Attribute is not of type 'Flag'";
343 return false;
344 }
345
SetFlagValue(bool value)346 bool NetlinkAttribute::SetFlagValue(bool value) {
347 LOG(ERROR) << "Attribute is not of type 'Flag'";
348 return false;
349 }
350
GetStringValue(string * value) const351 bool NetlinkAttribute::GetStringValue(string* value) const {
352 LOG(ERROR) << "Attribute is not of type 'String'";
353 return false;
354 }
355
SetStringValue(string value)356 bool NetlinkAttribute::SetStringValue(string value) {
357 LOG(ERROR) << "Attribute is not of type 'String'";
358 return false;
359 }
360
GetNestedAttributeList(AttributeListRefPtr * value)361 bool NetlinkAttribute::GetNestedAttributeList(AttributeListRefPtr* value) {
362 LOG(ERROR) << "Attribute is not of type 'Nested'";
363 return false;
364 }
365
ConstGetNestedAttributeList(AttributeListConstRefPtr * value) const366 bool NetlinkAttribute::ConstGetNestedAttributeList(
367 AttributeListConstRefPtr* value) const {
368 LOG(ERROR) << "Attribute is not of type 'Nested'";
369 return false;
370 }
371
SetNestedHasAValue()372 bool NetlinkAttribute::SetNestedHasAValue() {
373 LOG(ERROR) << "Attribute is not of type 'Nested'";
374 return false;
375 }
376
GetRawValue(ByteString * value) const377 bool NetlinkAttribute::GetRawValue(ByteString* value) const {
378 LOG(ERROR) << "Attribute is not of type 'Raw'";
379 return false;
380 }
381
SetRawValue(const ByteString new_value)382 bool NetlinkAttribute::SetRawValue(const ByteString new_value) {
383 LOG(ERROR) << "Attribute is not of type 'Raw'";
384 return false;
385 }
386
Print(int log_level,int indent) const387 void NetlinkAttribute::Print(int log_level, int indent) const {
388 string attribute_value;
389 VLOG(log_level) << HeaderToPrint(indent) << " "
390 << (ToString(&attribute_value) ? attribute_value :
391 "<DOES NOT EXIST>");
392 }
393
RawToString() const394 string NetlinkAttribute::RawToString() const {
395 string output = " === RAW: ";
396
397 if (!has_a_value_) {
398 StringAppendF(&output, "(empty)");
399 return output;
400 }
401
402 uint16_t length = data_.GetLength();
403 const uint8_t* const_data = data_.GetConstData();
404
405 StringAppendF(&output, "len=%u", length);
406 output.append(" DATA: ");
407 for (int i =0 ; i < length; ++i) {
408 StringAppendF(&output, "[%d]=%02x ", i, *(const_data)+i);
409 }
410 output.append(" ==== ");
411 return output;
412 }
413
HeaderToPrint(int indent) const414 string NetlinkAttribute::HeaderToPrint(int indent) const {
415 static const int kSpacesPerIndent = 2;
416 return StringPrintf("%*s%s(%d) %s %s=",
417 indent * kSpacesPerIndent, "",
418 id_string(),
419 id(),
420 datatype_string(),
421 ((has_a_value()) ? "": "UNINITIALIZED "));
422 }
423
EncodeGeneric(const unsigned char * data,size_t num_bytes) const424 ByteString NetlinkAttribute::EncodeGeneric(const unsigned char* data,
425 size_t num_bytes) const {
426 ByteString result;
427 if (has_a_value_) {
428 nlattr header;
429 header.nla_type = id();
430 header.nla_len = NLA_HDRLEN + num_bytes;
431 result = ByteString(reinterpret_cast<unsigned char*>(&header),
432 sizeof(header));
433 result.Resize(NLA_HDRLEN); // Add padding after the header.
434 if (data && (num_bytes != 0)) {
435 result.Append(ByteString(data, num_bytes));
436 }
437 result.Resize(NLA_ALIGN(result.GetLength())); // Add padding.
438 }
439 return result;
440 }
441
442 // NetlinkU8Attribute
443
444 const char NetlinkU8Attribute::kMyTypeString[] = "uint8_t";
445 const NetlinkAttribute::Type NetlinkU8Attribute::kType =
446 NetlinkAttribute::kTypeU8;
447
InitFromValue(const ByteString & input)448 bool NetlinkU8Attribute::InitFromValue(const ByteString& input) {
449 uint8_t data;
450 if (!input.CopyData(sizeof(data), &data)) {
451 LOG(ERROR) << "Invalid |input| for " << id_string() << " of type "
452 << datatype_string() << ": expected " << sizeof(data)
453 << " bytes but only had " << input.GetLength() << ".";
454 return false;
455 }
456 SetU8Value(data);
457 return NetlinkAttribute::InitFromValue(input);
458 }
459
GetU8Value(uint8_t * output) const460 bool NetlinkU8Attribute::GetU8Value(uint8_t* output) const {
461 if (!has_a_value_) {
462 VLOG(7) << "U8 attribute " << id_string()
463 << " hasn't been set to any value.";
464 return false;
465 }
466 if (output) {
467 *output = value_;
468 }
469 return true;
470 }
471
SetU8Value(uint8_t new_value)472 bool NetlinkU8Attribute::SetU8Value(uint8_t new_value) {
473 value_ = new_value;
474 has_a_value_ = true;
475 return true;
476 }
477
ToString(string * output) const478 bool NetlinkU8Attribute::ToString(string* output) const {
479 if (!output) {
480 LOG(ERROR) << "Null |output| parameter";
481 return false;
482 }
483 uint8_t value;
484 if (!GetU8Value(&value))
485 return false;
486 *output = StringPrintf("%u", value);
487 return true;
488 }
489
Encode() const490 ByteString NetlinkU8Attribute::Encode() const {
491 return NetlinkAttribute::EncodeGeneric(
492 reinterpret_cast<const unsigned char*>(&value_), sizeof(value_));
493 }
494
495 // NetlinkU16Attribute
496
497 const char NetlinkU16Attribute::kMyTypeString[] = "uint16_t";
498 const NetlinkAttribute::Type NetlinkU16Attribute::kType =
499 NetlinkAttribute::kTypeU16;
500
InitFromValue(const ByteString & input)501 bool NetlinkU16Attribute::InitFromValue(const ByteString& input) {
502 uint16_t data;
503 if (!input.CopyData(sizeof(data), &data)) {
504 LOG(ERROR) << "Invalid |input| for " << id_string() << " of type "
505 << datatype_string() << ": expected " << sizeof(data)
506 << " bytes but only had " << input.GetLength() << ".";
507 return false;
508 }
509
510 SetU16Value(data);
511 return NetlinkAttribute::InitFromValue(input);
512 }
513
GetU16Value(uint16_t * output) const514 bool NetlinkU16Attribute::GetU16Value(uint16_t* output) const {
515 if (!has_a_value_) {
516 VLOG(7) << "U16 attribute " << id_string()
517 << " hasn't been set to any value.";
518 return false;
519 }
520 if (output) {
521 *output = value_;
522 }
523 return true;
524 }
525
SetU16Value(uint16_t new_value)526 bool NetlinkU16Attribute::SetU16Value(uint16_t new_value) {
527 value_ = new_value;
528 has_a_value_ = true;
529 return true;
530 }
531
ToString(string * output) const532 bool NetlinkU16Attribute::ToString(string* output) const {
533 if (!output) {
534 LOG(ERROR) << "Null |output| parameter";
535 return false;
536 }
537 uint16_t value;
538 if (!GetU16Value(&value))
539 return false;
540 *output = StringPrintf("%u", value);
541 return true;
542 }
543
Encode() const544 ByteString NetlinkU16Attribute::Encode() const {
545 return NetlinkAttribute::EncodeGeneric(
546 reinterpret_cast<const unsigned char*>(&value_), sizeof(value_));
547 }
548
549 // NetlinkU32Attribute::
550
551 const char NetlinkU32Attribute::kMyTypeString[] = "uint32_t";
552 const NetlinkAttribute::Type NetlinkU32Attribute::kType =
553 NetlinkAttribute::kTypeU32;
554
InitFromValue(const ByteString & input)555 bool NetlinkU32Attribute::InitFromValue(const ByteString& input) {
556 uint32_t data;
557 if (!input.CopyData(sizeof(data), &data)) {
558 LOG(ERROR) << "Invalid |input| for " << id_string() << " of type "
559 << datatype_string() << ": expected " << sizeof(data)
560 << " bytes but only had " << input.GetLength() << ".";
561 return false;
562 }
563
564 SetU32Value(data);
565 return NetlinkAttribute::InitFromValue(input);
566 }
567
GetU32Value(uint32_t * output) const568 bool NetlinkU32Attribute::GetU32Value(uint32_t* output) const {
569 if (!has_a_value_) {
570 VLOG(7) << "U32 attribute " << id_string()
571 << " hasn't been set to any value.";
572 return false;
573 }
574 if (output) {
575 *output = value_;
576 }
577 return true;
578 }
579
SetU32Value(uint32_t new_value)580 bool NetlinkU32Attribute::SetU32Value(uint32_t new_value) {
581 value_ = new_value;
582 has_a_value_ = true;
583 return true;
584 }
585
ToString(string * output) const586 bool NetlinkU32Attribute::ToString(string* output) const {
587 if (!output) {
588 LOG(ERROR) << "Null |output| parameter";
589 return false;
590 }
591 uint32_t value;
592 if (!GetU32Value(&value))
593 return false;
594 *output = StringPrintf("%" PRIu32, value);
595 return true;
596 }
597
Encode() const598 ByteString NetlinkU32Attribute::Encode() const {
599 return NetlinkAttribute::EncodeGeneric(
600 reinterpret_cast<const unsigned char*>(&value_), sizeof(value_));
601 }
602
603 // NetlinkU64Attribute
604
605 const char NetlinkU64Attribute::kMyTypeString[] = "uint64_t";
606 const NetlinkAttribute::Type NetlinkU64Attribute::kType =
607 NetlinkAttribute::kTypeU64;
608
InitFromValue(const ByteString & input)609 bool NetlinkU64Attribute::InitFromValue(const ByteString& input) {
610 uint64_t data;
611 if (!input.CopyData(sizeof(data), &data)) {
612 LOG(ERROR) << "Invalid |input| for " << id_string() << " of type "
613 << datatype_string() << ": expected " << sizeof(data)
614 << " bytes but only had " << input.GetLength() << ".";
615 return false;
616 }
617 SetU64Value(data);
618 return NetlinkAttribute::InitFromValue(input);
619 }
620
GetU64Value(uint64_t * output) const621 bool NetlinkU64Attribute::GetU64Value(uint64_t* output) const {
622 if (!has_a_value_) {
623 VLOG(7) << "U64 attribute " << id_string()
624 << " hasn't been set to any value.";
625 return false;
626 }
627 if (output) {
628 *output = value_;
629 }
630 return true;
631 }
632
SetU64Value(uint64_t new_value)633 bool NetlinkU64Attribute::SetU64Value(uint64_t new_value) {
634 value_ = new_value;
635 has_a_value_ = true;
636 return true;
637 }
638
ToString(string * output) const639 bool NetlinkU64Attribute::ToString(string* output) const {
640 if (!output) {
641 LOG(ERROR) << "Null |output| parameter";
642 return false;
643 }
644 uint64_t value;
645 if (!GetU64Value(&value))
646 return false;
647 *output = StringPrintf("%" PRIu64, value);
648 return true;
649 }
650
Encode() const651 ByteString NetlinkU64Attribute::Encode() const {
652 return NetlinkAttribute::EncodeGeneric(
653 reinterpret_cast<const unsigned char*>(&value_), sizeof(value_));
654 }
655
656 // NetlinkFlagAttribute
657
658 const char NetlinkFlagAttribute::kMyTypeString[] = "flag";
659 const NetlinkAttribute::Type NetlinkFlagAttribute::kType =
660 NetlinkAttribute::kTypeFlag;
661
InitFromValue(const ByteString & input)662 bool NetlinkFlagAttribute::InitFromValue(const ByteString& input) {
663 // The existence of the parameter means it's true
664 SetFlagValue(true);
665 return NetlinkAttribute::InitFromValue(input);
666 }
667
668
GetFlagValue(bool * output) const669 bool NetlinkFlagAttribute::GetFlagValue(bool* output) const {
670 if (output) {
671 // The lack of the existence of the attribute implies 'false'.
672 *output = (has_a_value_) ? value_ : false;
673 }
674 return true;
675 }
676
SetFlagValue(bool new_value)677 bool NetlinkFlagAttribute::SetFlagValue(bool new_value) {
678 value_ = new_value;
679 has_a_value_ = true;
680 return true;
681 }
682
ToString(string * output) const683 bool NetlinkFlagAttribute::ToString(string* output) const {
684 if (!output) {
685 LOG(ERROR) << "Null |output| parameter";
686 return false;
687 }
688 bool value;
689 if (!GetFlagValue(&value))
690 return false;
691 *output = StringPrintf("%s", value ? "true" : "false");
692 return true;
693 }
694
Encode() const695 ByteString NetlinkFlagAttribute::Encode() const {
696 if (has_a_value_ && value_) {
697 return NetlinkAttribute::EncodeGeneric(nullptr, 0);
698 }
699 return ByteString(); // Encoding of nothing implies 'false'.
700 }
701
702 // NetlinkStringAttribute
703
704 const char NetlinkStringAttribute::kMyTypeString[] = "string";
705 const NetlinkAttribute::Type NetlinkStringAttribute::kType =
706 NetlinkAttribute::kTypeString;
707
InitFromValue(const ByteString & input)708 bool NetlinkStringAttribute::InitFromValue(const ByteString& input) {
709 if (!input.GetLength()) {
710 // Assume an empty string.
711 SetStringValue("");
712 } else {
713 const char* string_ptr =
714 reinterpret_cast<const char*>(input.GetConstData());
715 const char* first_null_pos = reinterpret_cast<const char*>(
716 memchr(string_ptr, '\0', input.GetLength()));
717 if (first_null_pos == string_ptr + input.GetLength() - 1) {
718 SetStringValue(string_ptr);
719 } else if (first_null_pos) {
720 LOG(WARNING) << "String appears to be terminated "
721 << (input.GetLength() - 1) - (first_null_pos - string_ptr)
722 << " bytes early.";
723 SetStringValue(string_ptr);
724 } else {
725 VLOG(1) << "String is unterminated.";
726 SetStringValue(string(string_ptr, input.GetLength()));
727 }
728 }
729
730 return NetlinkAttribute::InitFromValue(input);
731 }
732
GetStringValue(string * output) const733 bool NetlinkStringAttribute::GetStringValue(string* output) const {
734 if (!has_a_value_) {
735 VLOG(7) << "String attribute " << id_string()
736 << " hasn't been set to any value.";
737 return false;
738 }
739 if (output) {
740 *output = value_;
741 }
742 return true;
743 }
744
SetStringValue(const string new_value)745 bool NetlinkStringAttribute::SetStringValue(const string new_value) {
746 value_ = new_value;
747 has_a_value_ = true;
748 return true;
749 }
750
ToString(string * output) const751 bool NetlinkStringAttribute::ToString(string* output) const {
752 if (!output) {
753 LOG(ERROR) << "Null |output| parameter";
754 return false;
755 }
756 string value;
757 if (!GetStringValue(&value))
758 return false;
759
760 *output = StringPrintf("'%s'", value.c_str());
761 return true;
762 }
763
Encode() const764 ByteString NetlinkStringAttribute::Encode() const {
765 return NetlinkAttribute::EncodeGeneric(
766 reinterpret_cast<const unsigned char*>(value_.c_str()),
767 value_.size() + 1);
768 }
769
770 // SSID attribute.
771
ToString(string * output) const772 bool NetlinkSsidAttribute::ToString(string* output) const {
773 if (!output) {
774 LOG(ERROR) << "Null |output| parameter";
775 return false;
776 }
777 string value;
778 if (!GetStringValue(&value))
779 return false;
780
781 string temp;
782 for (const auto& chr : value) {
783 // Replace '[' and ']' (in addition to non-printable characters) so that
784 // it's easy to match the right substring through a non-greedy regex.
785 if (chr == '[' || chr == ']' || !std::isprint(chr)) {
786 base::StringAppendF(&temp, "\\x%02x", chr);
787 } else {
788 temp += chr;
789 }
790 }
791 *output = StringPrintf("[SSID=%s]", temp.c_str());
792
793 return true;
794 }
795
796 // NetlinkNestedAttribute
797
798 const char NetlinkNestedAttribute::kMyTypeString[] = "nested";
799 const NetlinkAttribute::Type NetlinkNestedAttribute::kType =
800 NetlinkAttribute::kTypeNested;
801 const size_t NetlinkNestedAttribute::kArrayAttrEnumVal = 0;
802
NetlinkNestedAttribute(int id,const char * id_string)803 NetlinkNestedAttribute::NetlinkNestedAttribute(int id,
804 const char* id_string) :
805 NetlinkAttribute(id, id_string, kType, kMyTypeString),
806 value_(new AttributeList) {}
807
Encode() const808 ByteString NetlinkNestedAttribute::Encode() const {
809 // Encode attribute header.
810 nlattr header;
811 header.nla_type = id();
812 header.nla_len = 0; // Filled in at the end.
813 ByteString result(reinterpret_cast<unsigned char*>(&header), sizeof(header));
814 result.Resize(NLA_HDRLEN); // Add padding after the header.
815
816 // Encode all nested attributes.
817 map<int, AttributeList::AttributePointer>::const_iterator attribute;
818 for (attribute = value_->attributes_.begin();
819 attribute != value_->attributes_.end();
820 ++attribute) {
821 // Each attribute appends appropriate padding so it's not necessary to
822 // re-add padding.
823 result.Append(attribute->second->Encode());
824 }
825
826 // Go back and fill-in the size.
827 nlattr* new_header = reinterpret_cast<nlattr*>(result.GetData());
828 new_header->nla_len = result.GetLength();
829
830 return result;
831 }
832
Print(int log_level,int indent) const833 void NetlinkNestedAttribute::Print(int log_level, int indent) const {
834 VLOG(log_level) << HeaderToPrint(indent);
835 value_->Print(log_level, indent + 1);
836 }
837
ToString(string * output) const838 bool NetlinkNestedAttribute::ToString(string* output) const {
839 if (!output) {
840 LOG(ERROR) << "Null |output| parameter";
841 return false;
842 }
843
844 // This should never be called (attribute->ToString is only called
845 // from attribute->Print but NetlinkNestedAttribute::Print doesn't call
846 // |ToString|. Still, we should print something in case we got here
847 // accidentally.
848 LOG(WARNING) << "It is unexpected for this method to be called.";
849 output->append("<Nested Attribute>");
850 return true;
851 }
852
InitFromValue(const ByteString & input)853 bool NetlinkNestedAttribute::InitFromValue(const ByteString& input) {
854 if (!InitNestedFromValue(value_, nested_template_, input)) {
855 LOG(ERROR) << "InitNestedFromValue() failed";
856 return false;
857 }
858 has_a_value_ = true;
859 return true;
860 }
861
GetNestedAttributeList(AttributeListRefPtr * output)862 bool NetlinkNestedAttribute::GetNestedAttributeList(
863 AttributeListRefPtr* output) {
864 // Not checking |has_a_value| since GetNestedAttributeList is called to get
865 // a newly created AttributeList in order to have something to which to add
866 // attributes.
867 if (output) {
868 *output = value_;
869 }
870 return true;
871 }
872
ConstGetNestedAttributeList(AttributeListConstRefPtr * output) const873 bool NetlinkNestedAttribute::ConstGetNestedAttributeList(
874 AttributeListConstRefPtr* output) const {
875 if (!has_a_value_) {
876 LOG(ERROR) << "Attribute does not exist.";
877 return false;
878 }
879 if (output) {
880 *output = value_;
881 }
882 return true;
883 }
884
SetNestedHasAValue()885 bool NetlinkNestedAttribute::SetNestedHasAValue() {
886 has_a_value_ = true;
887 return true;
888 }
889
InitNestedFromValue(const AttributeListRefPtr & list,const NetlinkNestedAttribute::NestedData::NestedDataMap & templates,const ByteString & value)890 bool NetlinkNestedAttribute::InitNestedFromValue(
891 const AttributeListRefPtr& list,
892 const NetlinkNestedAttribute::NestedData::NestedDataMap& templates,
893 const ByteString& value) {
894 if (templates.empty()) {
895 LOG(ERROR) << "|templates| size is zero";
896 return false;
897 }
898 if (templates.size() == 1 && templates.cbegin()->second.is_array) {
899 return AttributeList::IterateAttributes(
900 value, 0, base::Bind(
901 &NetlinkNestedAttribute::AddAttributeToNestedArray,
902 templates.cbegin()->second, list));
903 } else {
904 return AttributeList::IterateAttributes(
905 value, 0, base::Bind(
906 &NetlinkNestedAttribute::AddAttributeToNestedMap,
907 templates, list));
908 }
909 }
910
911 // static
AddAttributeToNestedArray(const NetlinkNestedAttribute::NestedData & array_template,const AttributeListRefPtr & list,int id,const ByteString & value)912 bool NetlinkNestedAttribute::AddAttributeToNestedArray(
913 const NetlinkNestedAttribute::NestedData& array_template,
914 const AttributeListRefPtr& list, int id, const ByteString& value) {
915 string attribute_name = StringPrintf(
916 "%s_%d", array_template.attribute_name.c_str(), id);
917 return AddAttributeToNestedInner(
918 array_template, attribute_name, list, id, value);
919 }
920
921 // static
AddAttributeToNestedMap(const NetlinkNestedAttribute::NestedData::NestedDataMap & templates,const AttributeListRefPtr & list,int id,const ByteString & value)922 bool NetlinkNestedAttribute::AddAttributeToNestedMap(
923 const NetlinkNestedAttribute::NestedData::NestedDataMap& templates,
924 const AttributeListRefPtr& list, int id, const ByteString& value) {
925 auto template_it = templates.find(id);
926 if (template_it == templates.end()) {
927 // No interest in this value.
928 return true;
929 }
930 const NestedData& nested_template = template_it->second;
931 return AddAttributeToNestedInner(
932 nested_template, nested_template.attribute_name, list, id, value);
933 }
934
935 // static
AddAttributeToNestedInner(const NetlinkNestedAttribute::NestedData & nested_template,const string & attribute_name,const AttributeListRefPtr & list,int id,const ByteString & value)936 bool NetlinkNestedAttribute::AddAttributeToNestedInner(
937 const NetlinkNestedAttribute::NestedData& nested_template,
938 const string& attribute_name, const AttributeListRefPtr& list,
939 int id, const ByteString& value) {
940 CHECK(list);
941 if (!nested_template.parse_attribute.is_null()) {
942 if (!nested_template.parse_attribute.Run(
943 list.get(), id, attribute_name, value)) {
944 LOG(WARNING) << "Custom attribute parser returned |false| for "
945 << attribute_name << "(" << id << ").";
946 return false;
947 }
948 return true;
949 }
950 switch (nested_template.type) {
951 case kTypeRaw:
952 list->CreateRawAttribute(id, attribute_name.c_str());
953 return list->SetRawAttributeValue(id, value);
954 case kTypeU8:
955 list->CreateU8Attribute(id, attribute_name.c_str());
956 return list->InitAttributeFromValue(id, value);
957 case kTypeU16:
958 list->CreateU16Attribute(id, attribute_name.c_str());
959 return list->InitAttributeFromValue(id, value);
960 case kTypeU32:
961 list->CreateU32Attribute(id, attribute_name.c_str());
962 return list->InitAttributeFromValue(id, value);
963 break;
964 case kTypeU64:
965 list->CreateU64Attribute(id, attribute_name.c_str());
966 return list->InitAttributeFromValue(id, value);
967 case kTypeFlag:
968 list->CreateFlagAttribute(id, attribute_name.c_str());
969 return list->SetFlagAttributeValue(id, true);
970 case kTypeString:
971 list->CreateStringAttribute(id, attribute_name.c_str());
972 return list->InitAttributeFromValue(id, value);
973 case kTypeNested:
974 {
975 if (nested_template.deeper_nesting.empty()) {
976 LOG(ERROR) << "No rules for nesting " << attribute_name
977 << ". Ignoring.";
978 break;
979 }
980 list->CreateNestedAttribute(id, attribute_name.c_str());
981
982 // Now, handle the nested data.
983 AttributeListRefPtr nested_attribute;
984 if (!list->GetNestedAttributeList(id, &nested_attribute) ||
985 !nested_attribute) {
986 LOG(FATAL) << "Couldn't get attribute " << attribute_name
987 << " which we just created.";
988 return false;
989 }
990
991 if (!InitNestedFromValue(nested_attribute,
992 nested_template.deeper_nesting,
993 value)) {
994 LOG(ERROR) << "Couldn't parse attribute " << attribute_name;
995 return false;
996 }
997 list->SetNestedAttributeHasAValue(id);
998 }
999 break;
1000 default:
1001 LOG(ERROR) << "Discarding " << attribute_name
1002 << ". Attribute has unhandled type "
1003 << nested_template.type << ".";
1004 break;
1005 }
1006 return true;
1007 }
1008
NestedData()1009 NetlinkNestedAttribute::NestedData::NestedData()
1010 : type(kTypeRaw), attribute_name("<UNKNOWN>"), is_array(false) {}
NestedData(NetlinkAttribute::Type type_arg,string attribute_name_arg,bool is_array_arg)1011 NetlinkNestedAttribute::NestedData::NestedData(
1012 NetlinkAttribute::Type type_arg, string attribute_name_arg,
1013 bool is_array_arg)
1014 : type(type_arg), attribute_name(attribute_name_arg),
1015 is_array(is_array_arg) {}
1016
NestedData(NetlinkAttribute::Type type_arg,string attribute_name_arg,bool is_array_arg,const AttributeParser & parse_attribute_arg)1017 NetlinkNestedAttribute::NestedData::NestedData(
1018 NetlinkAttribute::Type type_arg, string attribute_name_arg,
1019 bool is_array_arg, const AttributeParser& parse_attribute_arg)
1020 : type(type_arg), attribute_name(attribute_name_arg),
1021 is_array(is_array_arg), parse_attribute(parse_attribute_arg) {}
1022
1023 // NetlinkRawAttribute
1024
1025 const char NetlinkRawAttribute::kMyTypeString[] = "<raw>";
1026 const NetlinkAttribute::Type NetlinkRawAttribute::kType =
1027 NetlinkAttribute::kTypeRaw;
1028
InitFromValue(const ByteString & input)1029 bool NetlinkRawAttribute::InitFromValue(const ByteString& input) {
1030 if (!NetlinkAttribute::InitFromValue(input)) {
1031 return false;
1032 }
1033 has_a_value_ = true;
1034 return true;
1035 }
1036
GetRawValue(ByteString * output) const1037 bool NetlinkRawAttribute::GetRawValue(ByteString* output) const {
1038 if (!has_a_value_) {
1039 VLOG(7) << "Raw attribute " << id_string()
1040 << " hasn't been set to any value.";
1041 return false;
1042 }
1043 if (output) {
1044 *output = data_;
1045 }
1046 return true;
1047 }
1048
SetRawValue(const ByteString new_value)1049 bool NetlinkRawAttribute::SetRawValue(const ByteString new_value) {
1050 data_ = new_value;
1051 has_a_value_ = true;
1052 return true;
1053 }
1054
ToString(string * output) const1055 bool NetlinkRawAttribute::ToString(string* output) const {
1056 if (!output) {
1057 LOG(ERROR) << "Null |output| parameter";
1058 return false;
1059 }
1060 if (!has_a_value_) {
1061 VLOG(7) << "Raw attribute " << id_string()
1062 << " hasn't been set to any value.";
1063 return false;
1064 }
1065 int total_bytes = data_.GetLength();
1066 const uint8_t* const_data = data_.GetConstData();
1067
1068 *output = StringPrintf("%d bytes:", total_bytes);
1069 for (int i = 0; i < total_bytes; ++i) {
1070 StringAppendF(output, " 0x%02x", const_data[i]);
1071 }
1072 return true;
1073 }
1074
Encode() const1075 ByteString NetlinkRawAttribute::Encode() const {
1076 return NetlinkAttribute::EncodeGeneric(data_.GetConstData(),
1077 data_.GetLength());
1078 }
1079
NetlinkAttributeGeneric(int id)1080 NetlinkAttributeGeneric::NetlinkAttributeGeneric(int id)
1081 : NetlinkRawAttribute(id, "unused-string") {
1082 StringAppendF(&id_string_, "<UNKNOWN ATTRIBUTE %d>", id);
1083 }
1084
id_string() const1085 const char* NetlinkAttributeGeneric::id_string() const {
1086 return id_string_.c_str();
1087 }
1088
1089 } // namespace shill
1090