Home | History | Annotate | Download | only in net
      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 
     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
     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
    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|.
    296 bool NetlinkAttribute::InitFromValue(const ByteString& input) {
    297   data_ = input;
    298   return true;
    299 }
    300 
    301 bool NetlinkAttribute::GetU8Value(uint8_t* value) const {
    302   LOG(ERROR) << "Attribute is not of type 'U8'";
    303   return false;
    304 }
    305 
    306 bool NetlinkAttribute::SetU8Value(uint8_t value) {
    307   LOG(ERROR) << "Attribute is not of type 'U8'";
    308   return false;
    309 }
    310 
    311 bool NetlinkAttribute::GetU16Value(uint16_t* value) const {
    312   LOG(ERROR) << "Attribute is not of type 'U16'";
    313   return false;
    314 }
    315 
    316 bool NetlinkAttribute::SetU16Value(uint16_t value) {
    317   LOG(ERROR) << "Attribute is not of type 'U16'";
    318   return false;
    319 }
    320 
    321 bool NetlinkAttribute::GetU32Value(uint32_t* value) const {
    322   LOG(ERROR) << "Attribute is not of type 'U32'";
    323   return false;
    324 }
    325 
    326 bool NetlinkAttribute::SetU32Value(uint32_t value) {
    327   LOG(ERROR) << "Attribute is not of type 'U32'";
    328   return false;
    329 }
    330 
    331 bool NetlinkAttribute::GetU64Value(uint64_t* value) const {
    332   LOG(ERROR) << "Attribute is not of type 'U64'";
    333   return false;
    334 }
    335 
    336 bool NetlinkAttribute::SetU64Value(uint64_t value) {
    337   LOG(ERROR) << "Attribute is not of type 'U64'";
    338   return false;
    339 }
    340 
    341 bool NetlinkAttribute::GetFlagValue(bool* value) const {
    342   LOG(ERROR) << "Attribute is not of type 'Flag'";
    343   return false;
    344 }
    345 
    346 bool NetlinkAttribute::SetFlagValue(bool value) {
    347   LOG(ERROR) << "Attribute is not of type 'Flag'";
    348   return false;
    349 }
    350 
    351 bool NetlinkAttribute::GetStringValue(string* value) const {
    352   LOG(ERROR) << "Attribute is not of type 'String'";
    353   return false;
    354 }
    355 
    356 bool NetlinkAttribute::SetStringValue(string value) {
    357   LOG(ERROR) << "Attribute is not of type 'String'";
    358   return false;
    359 }
    360 
    361 bool NetlinkAttribute::GetNestedAttributeList(AttributeListRefPtr* value) {
    362   LOG(ERROR) << "Attribute is not of type 'Nested'";
    363   return false;
    364 }
    365 
    366 bool NetlinkAttribute::ConstGetNestedAttributeList(
    367     AttributeListConstRefPtr* value) const {
    368   LOG(ERROR) << "Attribute is not of type 'Nested'";
    369   return false;
    370 }
    371 
    372 bool NetlinkAttribute::SetNestedHasAValue() {
    373   LOG(ERROR) << "Attribute is not of type 'Nested'";
    374   return false;
    375 }
    376 
    377 bool NetlinkAttribute::GetRawValue(ByteString* value) const {
    378   LOG(ERROR) << "Attribute is not of type 'Raw'";
    379   return false;
    380 }
    381 
    382 bool NetlinkAttribute::SetRawValue(const ByteString new_value) {
    383   LOG(ERROR) << "Attribute is not of type 'Raw'";
    384   return false;
    385 }
    386 
    387 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 
    394 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 
    414 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 
    424 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 
    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 
    460 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 
    472 bool NetlinkU8Attribute::SetU8Value(uint8_t new_value) {
    473   value_ = new_value;
    474   has_a_value_ = true;
    475   return true;
    476 }
    477 
    478 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 
    490 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 
    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 
    514 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 
    526 bool NetlinkU16Attribute::SetU16Value(uint16_t new_value) {
    527   value_ = new_value;
    528   has_a_value_ = true;
    529   return true;
    530 }
    531 
    532 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 
    544 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 
    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 
    568 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 
    580 bool NetlinkU32Attribute::SetU32Value(uint32_t new_value) {
    581   value_ = new_value;
    582   has_a_value_ = true;
    583   return true;
    584 }
    585 
    586 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 
    598 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 
    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 
    621 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 
    633 bool NetlinkU64Attribute::SetU64Value(uint64_t new_value) {
    634   value_ = new_value;
    635   has_a_value_ = true;
    636   return true;
    637 }
    638 
    639 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 
    651 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 
    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 
    669 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 
    677 bool NetlinkFlagAttribute::SetFlagValue(bool new_value) {
    678   value_ = new_value;
    679   has_a_value_ = true;
    680   return true;
    681 }
    682 
    683 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 
    695 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 
    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 
    733 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 
    745 bool NetlinkStringAttribute::SetStringValue(const string new_value) {
    746   value_ = new_value;
    747   has_a_value_ = true;
    748   return true;
    749 }
    750 
    751 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 
    764 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 
    772 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 
    803 NetlinkNestedAttribute::NetlinkNestedAttribute(int id,
    804                                                const char* id_string) :
    805     NetlinkAttribute(id, id_string, kType, kMyTypeString),
    806     value_(new AttributeList) {}
    807 
    808 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 
    833 void NetlinkNestedAttribute::Print(int log_level, int indent) const {
    834   VLOG(log_level) << HeaderToPrint(indent);
    835   value_->Print(log_level, indent + 1);
    836 }
    837 
    838 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 
    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 
    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 
    873 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 
    885 bool NetlinkNestedAttribute::SetNestedHasAValue() {
    886   has_a_value_ = true;
    887   return true;
    888 }
    889 
    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
    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
    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
    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 
   1009 NetlinkNestedAttribute::NestedData::NestedData()
   1010     : type(kTypeRaw), attribute_name("<UNKNOWN>"), is_array(false) {}
   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 
   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 
   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 
   1037 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 
   1049 bool NetlinkRawAttribute::SetRawValue(const ByteString new_value) {
   1050   data_ = new_value;
   1051   has_a_value_ = true;
   1052   return true;
   1053 }
   1054 
   1055 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 
   1075 ByteString NetlinkRawAttribute::Encode() const {
   1076   return NetlinkAttribute::EncodeGeneric(data_.GetConstData(),
   1077                                          data_.GetLength());
   1078 }
   1079 
   1080 NetlinkAttributeGeneric::NetlinkAttributeGeneric(int id)
   1081     : NetlinkRawAttribute(id, "unused-string") {
   1082   StringAppendF(&id_string_, "<UNKNOWN ATTRIBUTE %d>", id);
   1083 }
   1084 
   1085 const char* NetlinkAttributeGeneric::id_string() const {
   1086   return id_string_.c_str();
   1087 }
   1088 
   1089 }  // namespace shill
   1090