• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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