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/nl80211_attribute.h"
     18 
     19 #include <string>
     20 #include <utility>
     21 
     22 #include <base/bind.h>
     23 #include <base/format_macros.h>
     24 #include <base/logging.h>
     25 #include <base/strings/stringprintf.h>
     26 
     27 #include "shill/net/ieee80211.h"
     28 #include "shill/net/netlink_message.h"
     29 
     30 using base::Bind;
     31 using base::StringAppendF;
     32 using base::StringPrintf;
     33 using std::string;
     34 
     35 namespace shill {
     36 
     37 const int Nl80211AttributeCookie::kName = NL80211_ATTR_COOKIE;
     38 const char Nl80211AttributeCookie::kNameString[] = "NL80211_ATTR_COOKIE";
     39 
     40 const int Nl80211AttributeBss::kName = NL80211_ATTR_BSS;
     41 const char Nl80211AttributeBss::kNameString[] = "NL80211_ATTR_BSS";
     42 const int Nl80211AttributeBss::kChannelsAttributeId =
     43     IEEE_80211::kElemIdChannels;
     44 const int Nl80211AttributeBss::kChallengeTextAttributeId =
     45     IEEE_80211::kElemIdChallengeText;
     46 const int Nl80211AttributeBss::kCountryInfoAttributeId =
     47     IEEE_80211::kElemIdCountry;
     48 const int Nl80211AttributeBss::kDSParameterSetAttributeId =
     49     IEEE_80211::kElemIdDSParameterSet;
     50 const int Nl80211AttributeBss::kErpAttributeId =
     51     IEEE_80211::kElemIdErp;
     52 const int Nl80211AttributeBss::kExtendedRatesAttributeId =
     53     IEEE_80211::kElemIdExtendedRates;
     54 const int Nl80211AttributeBss::kHtCapAttributeId =
     55     IEEE_80211::kElemIdHTCap;
     56 const int Nl80211AttributeBss::kHtInfoAttributeId =
     57     IEEE_80211::kElemIdHTInfo;
     58 const int Nl80211AttributeBss::kPowerCapabilityAttributeId =
     59     IEEE_80211::kElemIdPowerCapability;
     60 const int Nl80211AttributeBss::kPowerConstraintAttributeId =
     61     IEEE_80211::kElemIdPowerConstraint;
     62 const int Nl80211AttributeBss::kRequestAttributeId =
     63     IEEE_80211::kElemIdRequest;
     64 const int Nl80211AttributeBss::kRsnAttributeId =
     65     IEEE_80211::kElemIdRSN;
     66 const int Nl80211AttributeBss::kSsidAttributeId =
     67     IEEE_80211::kElemIdSsid;
     68 const int Nl80211AttributeBss::kSupportedRatesAttributeId =
     69     IEEE_80211::kElemIdSupportedRates;
     70 const int Nl80211AttributeBss::kTpcReportAttributeId =
     71     IEEE_80211::kElemIdTpcReport;
     72 const int Nl80211AttributeBss::kVendorSpecificAttributeId =
     73     IEEE_80211::kElemIdVendor;
     74 const int Nl80211AttributeBss::kVhtCapAttributeId =
     75     IEEE_80211::kElemIdVHTCap;
     76 const int Nl80211AttributeBss::kVhtInfoAttributeId =
     77     IEEE_80211::kElemIdVHTOperation;
     78 
     79 static const char kSsidString[] = "SSID";
     80 static const char kRatesString[] = "Rates";
     81 static const char kHtCapString[] = "HTCapabilities";
     82 static const char kHtOperString[] = "HTOperation";
     83 static const char kVhtCapString[] = "VHTCapabilities";
     84 static const char kVhtOperString[] = "VHTOperation";
     85 
     86 Nl80211AttributeBss::Nl80211AttributeBss()
     87     : NetlinkNestedAttribute(kName, kNameString) {
     88   nested_template_.insert(
     89       AttrDataPair(__NL80211_BSS_INVALID,
     90                    NestedData(kTypeU32, "__NL80211_BSS_INVALID", false)));
     91   nested_template_.insert(AttrDataPair(
     92       NL80211_BSS_BSSID, NestedData(kTypeRaw, "NL80211_BSS_BSSID", false)));
     93   nested_template_.insert(
     94       AttrDataPair(NL80211_BSS_FREQUENCY,
     95                    NestedData(kTypeU32, "NL80211_BSS_FREQUENCY", false)));
     96   nested_template_.insert(AttrDataPair(
     97       NL80211_BSS_TSF, NestedData(kTypeU64, "NL80211_BSS_TSF", false)));
     98   nested_template_.insert(
     99       AttrDataPair(NL80211_BSS_BEACON_INTERVAL,
    100                    NestedData(kTypeU16, "NL80211_BSS_BEACON_INTERVAL", false)));
    101   nested_template_.insert(
    102       AttrDataPair(NL80211_BSS_CAPABILITY,
    103                    NestedData(kTypeU16, "NL80211_BSS_CAPABILITY", false)));
    104   nested_template_.insert(AttrDataPair(
    105       NL80211_BSS_INFORMATION_ELEMENTS,
    106       NestedData(kTypeRaw, "NL80211_BSS_INFORMATION_ELEMENTS", false,
    107                  Bind(&Nl80211AttributeBss::ParseInformationElements))));
    108   nested_template_.insert(
    109       AttrDataPair(NL80211_BSS_SIGNAL_MBM,
    110                    NestedData(kTypeU32, "NL80211_BSS_SIGNAL_MBM", false)));
    111   nested_template_.insert(
    112       AttrDataPair(NL80211_BSS_SIGNAL_UNSPEC,
    113                    NestedData(kTypeU8, "NL80211_BSS_SIGNAL_UNSPEC", false)));
    114   nested_template_.insert(AttrDataPair(
    115       NL80211_BSS_STATUS, NestedData(kTypeU32, "NL80211_BSS_STATUS", false)));
    116   nested_template_.insert(
    117       AttrDataPair(NL80211_BSS_SEEN_MS_AGO,
    118                    NestedData(kTypeU32, "NL80211_BSS_SEEN_MS_AGO", false)));
    119 }
    120 
    121 bool Nl80211AttributeBss::ParseInformationElements(
    122     AttributeList* attribute_list, size_t id, const string& attribute_name,
    123     ByteString data) {
    124   if (!attribute_list) {
    125     LOG(ERROR) << "NULL |attribute_list| parameter";
    126     return false;
    127   }
    128   attribute_list->CreateNestedAttribute(id, attribute_name.c_str());
    129 
    130   // Now, handle the nested data.
    131   AttributeListRefPtr ie_attribute;
    132   if (!attribute_list->GetNestedAttributeList(id, &ie_attribute) ||
    133       !ie_attribute) {
    134     LOG(ERROR) << "Couldn't get attribute " << attribute_name
    135                << " which we just created.";
    136     return false;
    137   }
    138   const uint8_t* sub_attribute = data.GetConstData();
    139   const uint8_t* end = sub_attribute + data.GetLength();
    140   const int kHeaderBytes = 2;
    141   while (end - sub_attribute > kHeaderBytes) {
    142     uint8_t type = sub_attribute[0];
    143     uint8_t payload_bytes = sub_attribute[1];
    144     const uint8_t* payload = &sub_attribute[kHeaderBytes];
    145     if (payload + payload_bytes > end) {
    146       LOG(ERROR) << "Found malformed IE data.";
    147       return false;
    148     }
    149     // See http://dox.ipxe.org/ieee80211_8h_source.html for more info on types
    150     // and data inside information elements.
    151     switch (type) {
    152       case kSsidAttributeId: {
    153         ie_attribute->CreateSsidAttribute(type, kSsidString);
    154         if (payload_bytes == 0) {
    155           ie_attribute->SetStringAttributeValue(type, "");
    156         } else {
    157           ie_attribute->SetStringAttributeValue(
    158               type,
    159               string(reinterpret_cast<const char*>(payload), payload_bytes));
    160         }
    161         break;
    162       }
    163       case kSupportedRatesAttributeId:
    164       case kExtendedRatesAttributeId: {
    165         ie_attribute->CreateNestedAttribute(type, kRatesString);
    166         AttributeListRefPtr rates_attribute;
    167         if (!ie_attribute->GetNestedAttributeList(type, &rates_attribute) ||
    168             !rates_attribute) {
    169           LOG(ERROR) << "Couldn't get attribute " << attribute_name
    170                      << " which we just created.";
    171           break;
    172         }
    173         // Extract each rate, add it to the list.
    174         for (size_t i = 0; i < payload_bytes; ++i) {
    175           string rate_name = StringPrintf("Rate-%zu", i);
    176           rates_attribute->CreateU8Attribute(i, rate_name.c_str());
    177           rates_attribute->SetU8AttributeValue(i, payload[i]);
    178         }
    179         ie_attribute->SetNestedAttributeHasAValue(type);
    180         break;
    181       }
    182       case kHtCapAttributeId: {
    183         ie_attribute->CreateRawAttribute(type, kHtCapString);
    184         ie_attribute->SetRawAttributeValue(
    185             type,
    186             ByteString(
    187                 reinterpret_cast<const char*>(payload), payload_bytes));
    188         break;
    189       }
    190       case kHtInfoAttributeId: {
    191         ie_attribute->CreateRawAttribute(type, kHtOperString);
    192         ie_attribute->SetRawAttributeValue(
    193             type,
    194             ByteString(
    195                 reinterpret_cast<const char*>(payload), payload_bytes));
    196         break;
    197       }
    198       case kVhtCapAttributeId: {
    199         ie_attribute->CreateRawAttribute(type, kVhtCapString);
    200         ie_attribute->SetRawAttributeValue(
    201             type,
    202             ByteString(
    203                 reinterpret_cast<const char*>(payload), payload_bytes));
    204         break;
    205       }
    206       case kVhtInfoAttributeId: {
    207         ie_attribute->CreateRawAttribute(type, kVhtOperString);
    208         ie_attribute->SetRawAttributeValue(
    209             type,
    210             ByteString(
    211                 reinterpret_cast<const char*>(payload), payload_bytes));
    212         break;
    213       }
    214       case kDSParameterSetAttributeId:
    215       case kCountryInfoAttributeId:
    216       case kRequestAttributeId:
    217       case kChallengeTextAttributeId:
    218       case kPowerConstraintAttributeId:
    219       case kPowerCapabilityAttributeId:
    220       case kTpcReportAttributeId:
    221       case kChannelsAttributeId:
    222       case kErpAttributeId:
    223       case kRsnAttributeId:
    224       case kVendorSpecificAttributeId:
    225       default:
    226         break;
    227     }
    228     sub_attribute += kHeaderBytes + payload_bytes;
    229   }
    230   attribute_list->SetNestedAttributeHasAValue(id);
    231   return true;
    232 }
    233 
    234 const int Nl80211AttributeWiphyBands::kName = NL80211_ATTR_WIPHY_BANDS;
    235 const char Nl80211AttributeWiphyBands::kNameString[] =
    236     "NL80211_ATTR_WIPHY_BANDS";
    237 
    238 Nl80211AttributeWiphyBands::Nl80211AttributeWiphyBands()
    239     : NetlinkNestedAttribute(kName, kNameString) {
    240   // Frequencies
    241   NestedData freq(kTypeNested, "NL80211_BAND_ATTR_FREQ", true);
    242   freq.deeper_nesting.insert(AttrDataPair(
    243       __NL80211_FREQUENCY_ATTR_INVALID,
    244       NestedData(kTypeU32, "__NL80211_FREQUENCY_ATTR_INVALID", false)));
    245   freq.deeper_nesting.insert(
    246       AttrDataPair(NL80211_FREQUENCY_ATTR_FREQ,
    247                    NestedData(kTypeU32, "NL80211_FREQUENCY_ATTR_FREQ", false)));
    248   freq.deeper_nesting.insert(AttrDataPair(
    249       NL80211_FREQUENCY_ATTR_DISABLED,
    250       NestedData(kTypeFlag, "NL80211_FREQUENCY_ATTR_DISABLED", false)));
    251   freq.deeper_nesting.insert(AttrDataPair(
    252       NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
    253       NestedData(kTypeFlag, "NL80211_FREQUENCY_ATTR_PASSIVE_SCAN", false)));
    254   freq.deeper_nesting.insert(AttrDataPair(
    255       NL80211_FREQUENCY_ATTR_NO_IBSS,
    256       NestedData(kTypeFlag, "NL80211_FREQUENCY_ATTR_NO_IBSS", false)));
    257   freq.deeper_nesting.insert(AttrDataPair(
    258       NL80211_FREQUENCY_ATTR_RADAR,
    259       NestedData(kTypeFlag, "NL80211_FREQUENCY_ATTR_RADAR", false)));
    260   freq.deeper_nesting.insert(AttrDataPair(
    261       NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
    262       NestedData(kTypeU32, "NL80211_FREQUENCY_ATTR_MAX_TX_POWER", false)));
    263 
    264   NestedData freqs(kTypeNested, "NL80211_BAND_ATTR_FREQS", false);
    265   freqs.deeper_nesting.insert(AttrDataPair(kArrayAttrEnumVal, freq));
    266 
    267   // Rates
    268   NestedData rate(kTypeNested, "NL80211_BAND_ATTR_RATE", true);
    269   rate.deeper_nesting.insert(AttrDataPair(
    270       __NL80211_BITRATE_ATTR_INVALID,
    271       NestedData(kTypeU32, "__NL80211_BITRATE_ATTR_INVALID", false)));
    272   rate.deeper_nesting.insert(
    273       AttrDataPair(NL80211_BITRATE_ATTR_RATE,
    274                    NestedData(kTypeU32, "NL80211_BITRATE_ATTR_RATE", false)));
    275   rate.deeper_nesting.insert(AttrDataPair(
    276       NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE,
    277       NestedData(kTypeFlag, "NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE", false)));
    278 
    279   NestedData rates(kTypeNested, "NL80211_BAND_ATTR_RATES", true);
    280   rates.deeper_nesting.insert(AttrDataPair(kArrayAttrEnumVal, rate));
    281 
    282   // Main body of attribute
    283   NestedData bands(kTypeNested, "NL80211_ATTR_BANDS", true);
    284   bands.deeper_nesting.insert(
    285       AttrDataPair(
    286           __NL80211_BAND_ATTR_INVALID,
    287           NestedData(kTypeU32, "__NL80211_BAND_ATTR_INVALID,", false)));
    288   bands.deeper_nesting.insert(AttrDataPair(NL80211_BAND_ATTR_FREQS, freqs));
    289   bands.deeper_nesting.insert(AttrDataPair(NL80211_BAND_ATTR_RATES, rates));
    290   bands.deeper_nesting.insert(AttrDataPair(
    291       NL80211_BAND_ATTR_HT_MCS_SET,
    292       NestedData(kTypeRaw, "NL80211_BAND_ATTR_HT_MCS_SET", false)));
    293   bands.deeper_nesting.insert(
    294       AttrDataPair(NL80211_BAND_ATTR_HT_CAPA,
    295                    NestedData(kTypeU16, "NL80211_BAND_ATTR_HT_CAPA", false)));
    296   bands.deeper_nesting.insert(AttrDataPair(
    297       NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
    298       NestedData(kTypeU8, "NL80211_BAND_ATTR_HT_AMPDU_FACTOR", false)));
    299   bands.deeper_nesting.insert(AttrDataPair(
    300       NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
    301       NestedData(kTypeU8, "NL80211_BAND_ATTR_HT_AMPDU_DENSITY", false)));
    302 
    303   nested_template_.insert(AttrDataPair(kArrayAttrEnumVal, bands));
    304 }
    305 
    306 #if !defined(DISABLE_WAKE_ON_WIFI)
    307 const int Nl80211AttributeWowlanTriggers::kName = NL80211_ATTR_WOWLAN_TRIGGERS;
    308 const char Nl80211AttributeWowlanTriggers::kNameString[] =
    309     "NL80211_ATTR_WOWLAN_TRIGGERS";
    310 
    311 Nl80211AttributeWowlanTriggers::Nl80211AttributeWowlanTriggers(
    312     NetlinkMessage::MessageContext context)
    313     : NetlinkNestedAttribute(kName, kNameString) {
    314   // Pattern matching trigger attribute.
    315   if (context.nl80211_cmd == NL80211_CMD_SET_WOWLAN && context.is_broadcast) {
    316     // If this attribute occurs in a wakeup report, parse
    317     // NL80211_WOWLAN_TRIG_PKT_PATTERN as a U32 reporting the index of the
    318     // pattern that caused the wake.
    319     nested_template_.insert(AttrDataPair(
    320         NL80211_WOWLAN_TRIG_PKT_PATTERN,
    321         NestedData(kTypeU32, "NL80211_WOWLAN_TRIG_PKT_PATTERN", false)));
    322   } else {
    323     // Otherwise, this attribute is meant to program the NIC, so parse it as
    324     // a nested attribute.
    325     NestedData patterns(kTypeNested, "NL80211_WOWLAN_TRIG_PKT_PATTERN", false);
    326     NestedData individual_pattern(kTypeNested, "Pattern Match Info", true);
    327     individual_pattern.deeper_nesting.insert(
    328         AttrDataPair(NL80211_PKTPAT_MASK,
    329                      NestedData(kTypeRaw, "NL80211_PKTPAT_MASK", false)));
    330     individual_pattern.deeper_nesting.insert(
    331         AttrDataPair(NL80211_PKTPAT_PATTERN,
    332                      NestedData(kTypeRaw, "NL80211_PKTPAT_PATTERN", false)));
    333     individual_pattern.deeper_nesting.insert(
    334         AttrDataPair(NL80211_PKTPAT_OFFSET,
    335                      NestedData(kTypeU32, "NL80211_PKTPAT_OFFSET", false)));
    336     patterns.deeper_nesting.insert(
    337         AttrDataPair(kArrayAttrEnumVal, individual_pattern));
    338     nested_template_.insert(
    339         AttrDataPair(NL80211_WOWLAN_TRIG_PKT_PATTERN, patterns));
    340   }
    341 
    342   // Net detect SSID matching trigger attribute.
    343   NestedData net_detect(kTypeNested, "NL80211_WOWLAN_TRIG_NET_DETECT", false);
    344   NestedData scan_freqs(kTypeNested, "NL80211_ATTR_SCAN_FREQUENCIES", true);
    345   scan_freqs.deeper_nesting.insert(
    346       AttrDataPair(kArrayAttrEnumVal,
    347                    NestedData(kTypeU32, "Frequency match", false)));
    348   net_detect.deeper_nesting.insert(
    349       AttrDataPair(NL80211_ATTR_SCAN_FREQUENCIES, scan_freqs));
    350   net_detect.deeper_nesting.insert(AttrDataPair(
    351       NL80211_ATTR_SCHED_SCAN_INTERVAL,
    352       NestedData(kTypeU32, "NL80211_ATTR_SCHED_SCAN_INTERVAL", false)));
    353   NestedData scan_matches(kTypeNested, "NL80211_ATTR_SCHED_SCAN_MATCH", false);
    354   NestedData individual_scan_match(
    355       kTypeNested, "NL80211_ATTR_SCHED_SCAN_MATCH_SINGLE", true);
    356   individual_scan_match.deeper_nesting.insert(AttrDataPair(
    357       NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
    358       NestedData(kTypeRaw, "NL80211_SCHED_SCAN_MATCH_ATTR_SSID", false)));
    359   scan_matches.deeper_nesting.insert(
    360       AttrDataPair(kArrayAttrEnumVal, individual_scan_match));
    361   net_detect.deeper_nesting.insert(
    362       AttrDataPair(NL80211_ATTR_SCHED_SCAN_MATCH, scan_matches));
    363 
    364   // Net detect results attribute
    365   NestedData net_detect_results(
    366       kTypeNested, "NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS", false);
    367   NestedData single_result(kTypeNested, "NL80211_WOWLAN_TRIG_NET_DETECT_RESULT",
    368                            true);
    369   NestedData freq_list(kTypeNested, "NL80211_ATTR_SCAN_FREQUENCIES", false);
    370   freq_list.deeper_nesting.insert(
    371       AttrDataPair(kArrayAttrEnumVal,
    372                    NestedData(kTypeU32, "Frequency match", true)));
    373   single_result.deeper_nesting.insert(
    374       AttrDataPair(NL80211_ATTR_SCAN_FREQUENCIES, freq_list));
    375   single_result.deeper_nesting.insert(AttrDataPair(
    376       NL80211_ATTR_SSID, NestedData(kTypeRaw, "NL80211_ATTR_SSID", false)));
    377   net_detect_results.deeper_nesting.insert(
    378       AttrDataPair(kArrayAttrEnumVal, single_result));
    379 
    380   // Main body of the triggers attribute.
    381   nested_template_.insert(AttrDataPair(
    382       NL80211_WOWLAN_TRIG_DISCONNECT,
    383       NestedData(kTypeFlag, "NL80211_WOWLAN_TRIG_DISCONNECT", false)));
    384   nested_template_.insert(
    385       AttrDataPair(NL80211_WOWLAN_TRIG_NET_DETECT, net_detect));
    386   nested_template_.insert(
    387       AttrDataPair(NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS, net_detect_results));
    388 }
    389 
    390 const int Nl80211AttributeWowlanTriggersSupported::kName =
    391     NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED;
    392 const char Nl80211AttributeWowlanTriggersSupported::kNameString[] =
    393     "NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED";
    394 
    395 Nl80211AttributeWowlanTriggersSupported::
    396     Nl80211AttributeWowlanTriggersSupported()
    397     : NetlinkNestedAttribute(kName, kNameString) {
    398   nested_template_.insert(AttrDataPair(
    399       NL80211_WOWLAN_TRIG_DISCONNECT,
    400       NestedData(kTypeFlag, "NL80211_WOWLAN_TRIG_DISCONNECT", false)));
    401   nested_template_.insert(AttrDataPair(
    402       NL80211_WOWLAN_TRIG_PKT_PATTERN,
    403       NestedData(kTypeRaw, "NL80211_WOWLAN_TRIG_PKT_PATTERN", false)));
    404   nested_template_.insert(AttrDataPair(
    405       NL80211_WOWLAN_TRIG_NET_DETECT,
    406       NestedData(kTypeU32, "NL80211_WOWLAN_TRIG_NET_DETECT", false)));
    407 }
    408 #endif  // DISABLE_WAKE_ON_WIFI
    409 
    410 const int Nl80211AttributeCipherSuites::kName = NL80211_ATTR_CIPHER_SUITES;
    411 const char Nl80211AttributeCipherSuites::kNameString[] =
    412     "NL80211_ATTR_CIPHER_SUITES";
    413 
    414 const int Nl80211AttributeControlPortEthertype::kName =
    415     NL80211_ATTR_CONTROL_PORT_ETHERTYPE;
    416 const char Nl80211AttributeControlPortEthertype::kNameString[] =
    417     "NL80211_ATTR_CONTROL_PORT_ETHERTYPE";
    418 
    419 const int Nl80211AttributeCqm::kName = NL80211_ATTR_CQM;
    420 const char Nl80211AttributeCqm::kNameString[] = "NL80211_ATTR_CQM";
    421 
    422 Nl80211AttributeCqm::Nl80211AttributeCqm()
    423     : NetlinkNestedAttribute(kName, kNameString) {
    424   nested_template_.insert(
    425       AttrDataPair(__NL80211_ATTR_CQM_INVALID,
    426                    NestedData(kTypeU32, "__NL80211_ATTR_CQM_INVALID", false)));
    427   nested_template_.insert(
    428       AttrDataPair(NL80211_ATTR_CQM_RSSI_THOLD,
    429                    NestedData(kTypeU32, "NL80211_ATTR_CQM_RSSI_THOLD", false)));
    430   nested_template_.insert(
    431       AttrDataPair(NL80211_ATTR_CQM_RSSI_HYST,
    432                    NestedData(kTypeU32, "NL80211_ATTR_CQM_RSSI_HYST", false)));
    433   nested_template_.insert(AttrDataPair(
    434       NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
    435       NestedData(kTypeU32, "NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT", false)));
    436   nested_template_.insert(AttrDataPair(
    437       NL80211_ATTR_CQM_PKT_LOSS_EVENT,
    438       NestedData(kTypeU32, "NL80211_ATTR_CQM_PKT_LOSS_EVENT", false)));
    439 }
    440 
    441 const int Nl80211AttributeDeviceApSme::kName = NL80211_ATTR_DEVICE_AP_SME;
    442 const char Nl80211AttributeDeviceApSme::kNameString[] =
    443     "NL80211_ATTR_DEVICE_AP_SME";
    444 
    445 const int Nl80211AttributeDfsRegion::kName = NL80211_ATTR_DFS_REGION;
    446 const char Nl80211AttributeDfsRegion::kNameString[] = "NL80211_ATTR_DFS_REGION";
    447 
    448 const int Nl80211AttributeDisconnectedByAp::kName =
    449     NL80211_ATTR_DISCONNECTED_BY_AP;
    450 const char Nl80211AttributeDisconnectedByAp::kNameString[] =
    451     "NL80211_ATTR_DISCONNECTED_BY_AP";
    452 
    453 const int Nl80211AttributeDuration::kName = NL80211_ATTR_DURATION;
    454 const char Nl80211AttributeDuration::kNameString[] = "NL80211_ATTR_DURATION";
    455 
    456 const int Nl80211AttributeFeatureFlags::kName = NL80211_ATTR_FEATURE_FLAGS;
    457 const char Nl80211AttributeFeatureFlags::kNameString[] =
    458     "NL80211_ATTR_FEATURE_FLAGS";
    459 
    460 const int Nl80211AttributeFrame::kName = NL80211_ATTR_FRAME;
    461 const char Nl80211AttributeFrame::kNameString[] = "NL80211_ATTR_FRAME";
    462 
    463 const int Nl80211AttributeGeneration::kName = NL80211_ATTR_GENERATION;
    464 const char Nl80211AttributeGeneration::kNameString[] =
    465     "NL80211_ATTR_GENERATION";
    466 
    467 const int Nl80211AttributeHtCapabilityMask::kName =
    468     NL80211_ATTR_HT_CAPABILITY_MASK;
    469 const char Nl80211AttributeHtCapabilityMask::kNameString[] =
    470     "NL80211_ATTR_HT_CAPABILITY_MASK";
    471 
    472 const int Nl80211AttributeIfindex::kName = NL80211_ATTR_IFINDEX;
    473 const char Nl80211AttributeIfindex::kNameString[] = "NL80211_ATTR_IFINDEX";
    474 
    475 const int Nl80211AttributeIftype::kName = NL80211_ATTR_IFTYPE;
    476 const char Nl80211AttributeIftype::kNameString[] = "NL80211_ATTR_IFTYPE";
    477 
    478 const int Nl80211AttributeKeyIdx::kName = NL80211_ATTR_KEY_IDX;
    479 const char Nl80211AttributeKeyIdx::kNameString[] = "NL80211_ATTR_KEY_IDX";
    480 
    481 const int Nl80211AttributeKeySeq::kName = NL80211_ATTR_KEY_SEQ;
    482 const char Nl80211AttributeKeySeq::kNameString[] = "NL80211_ATTR_KEY_SEQ";
    483 
    484 const int Nl80211AttributeKeyType::kName = NL80211_ATTR_KEY_TYPE;
    485 const char Nl80211AttributeKeyType::kNameString[] = "NL80211_ATTR_KEY_TYPE";
    486 
    487 const int Nl80211AttributeMac::kName = NL80211_ATTR_MAC;
    488 const char Nl80211AttributeMac::kNameString[] = "NL80211_ATTR_MAC";
    489 
    490 bool Nl80211AttributeMac::ToString(std::string* value) const {
    491   if (!value) {
    492     LOG(ERROR) << "Null |value| parameter";
    493     return false;
    494   }
    495   *value = StringFromMacAddress(data_.GetConstData());
    496   return true;
    497 }
    498 
    499 // static
    500 string Nl80211AttributeMac::StringFromMacAddress(const uint8_t* arg) {
    501   string output;
    502 
    503   if (!arg) {
    504     static const char kBogusMacAddress[] = "XX:XX:XX:XX:XX:XX";
    505     output = kBogusMacAddress;
    506     LOG(ERROR) << "|arg| parameter is NULL.";
    507   } else {
    508     output = StringPrintf("%02x:%02x:%02x:%02x:%02x:%02x", arg[0], arg[1],
    509                           arg[2], arg[3], arg[4], arg[5]);
    510   }
    511   return output;
    512 }
    513 
    514 const int Nl80211AttributeMaxMatchSets::kName = NL80211_ATTR_MAX_MATCH_SETS;
    515 const char Nl80211AttributeMaxMatchSets::kNameString[] =
    516     "NL80211_ATTR_MAX_MATCH_SETS";
    517 
    518 const int Nl80211AttributeMaxNumPmkids::kName = NL80211_ATTR_MAX_NUM_PMKIDS;
    519 const char Nl80211AttributeMaxNumPmkids::kNameString[] =
    520     "NL80211_ATTR_MAX_NUM_PMKIDS";
    521 
    522 const int Nl80211AttributeMaxNumScanSsids::kName =
    523     NL80211_ATTR_MAX_NUM_SCAN_SSIDS;
    524 const char Nl80211AttributeMaxNumScanSsids::kNameString[] =
    525     "NL80211_ATTR_MAX_NUM_SCAN_SSIDS";
    526 
    527 const int Nl80211AttributeMaxNumSchedScanSsids::kName =
    528     NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS;
    529 const char Nl80211AttributeMaxNumSchedScanSsids::kNameString[] =
    530     "NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS";
    531 
    532 const int Nl80211AttributeMaxRemainOnChannelDuration::kName =
    533     NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION;
    534 const char Nl80211AttributeMaxRemainOnChannelDuration::kNameString[] =
    535     "NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION";
    536 
    537 const int Nl80211AttributeMaxScanIeLen::kName = NL80211_ATTR_MAX_SCAN_IE_LEN;
    538 const char Nl80211AttributeMaxScanIeLen::kNameString[] =
    539     "NL80211_ATTR_MAX_SCAN_IE_LEN";
    540 
    541 const int Nl80211AttributeMaxSchedScanIeLen::kName =
    542     NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN;
    543 const char Nl80211AttributeMaxSchedScanIeLen::kNameString[] =
    544     "NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN";
    545 
    546 const int Nl80211AttributeOffchannelTxOk::kName = NL80211_ATTR_OFFCHANNEL_TX_OK;
    547 const char Nl80211AttributeOffchannelTxOk::kNameString[] =
    548     "NL80211_ATTR_OFFCHANNEL_TX_OK";
    549 
    550 const int Nl80211AttributeProbeRespOffload::kName =
    551     NL80211_ATTR_PROBE_RESP_OFFLOAD;
    552 const char Nl80211AttributeProbeRespOffload::kNameString[] =
    553     "NL80211_ATTR_PROBE_RESP_OFFLOAD";
    554 
    555 const int Nl80211AttributeReasonCode::kName = NL80211_ATTR_REASON_CODE;
    556 const char Nl80211AttributeReasonCode::kNameString[] =
    557     "NL80211_ATTR_REASON_CODE";
    558 
    559 const int Nl80211AttributeRegAlpha2::kName = NL80211_ATTR_REG_ALPHA2;
    560 const char Nl80211AttributeRegAlpha2::kNameString[] = "NL80211_ATTR_REG_ALPHA2";
    561 
    562 const int Nl80211AttributeRegInitiator::kName = NL80211_ATTR_REG_INITIATOR;
    563 const char Nl80211AttributeRegInitiator::kNameString[] =
    564     "NL80211_ATTR_REG_INITIATOR";
    565 
    566 // The RegInitiator type can be interpreted as either a U8 or U32 depending
    567 // on context.  Override the default InitFromValue implementation to be
    568 // flexible to either encoding.
    569 bool Nl80211AttributeRegInitiator::InitFromValue(const ByteString& input) {
    570   uint8_t u8_data;
    571   if (input.GetLength() != sizeof(u8_data))
    572     return NetlinkU32Attribute::InitFromValue(input);
    573 
    574   if (!input.CopyData(sizeof(u8_data), &u8_data)) {
    575     LOG(ERROR) << "Invalid |input| parameter.";
    576     return false;
    577   }
    578 
    579   SetU32Value(static_cast<uint32_t>(u8_data));
    580   return NetlinkAttribute::InitFromValue(input);
    581 }
    582 
    583 const int Nl80211AttributeRegRules::kName = NL80211_ATTR_REG_RULES;
    584 const char Nl80211AttributeRegRules::kNameString[] = "NL80211_ATTR_REG_RULES";
    585 
    586 Nl80211AttributeRegRules::Nl80211AttributeRegRules()
    587     : NetlinkNestedAttribute(kName, kNameString) {
    588   NestedData reg_rules(kTypeNested, "NL80211_REG_RULES", true);
    589   reg_rules.deeper_nesting.insert(
    590       AttrDataPair(__NL80211_REG_RULE_ATTR_INVALID,
    591                    NestedData(kTypeU32, "__NL80211_ATTR_REG_RULE_INVALID",
    592                               false)));
    593   reg_rules.deeper_nesting.insert(
    594       AttrDataPair(NL80211_ATTR_REG_RULE_FLAGS,
    595                    NestedData(kTypeU32, "NL80211_ATTR_REG_RULE_FLAGS",
    596                               false)));
    597   reg_rules.deeper_nesting.insert(
    598       AttrDataPair(NL80211_ATTR_FREQ_RANGE_START,
    599                    NestedData(kTypeU32, "NL80211_ATTR_FREQ_RANGE_START",
    600                               false)));
    601   reg_rules.deeper_nesting.insert(
    602       AttrDataPair(NL80211_ATTR_FREQ_RANGE_END,
    603                    NestedData(kTypeU32, "NL80211_ATTR_FREQ_RANGE_END",
    604                               false)));
    605   reg_rules.deeper_nesting.insert(
    606       AttrDataPair(NL80211_ATTR_FREQ_RANGE_MAX_BW,
    607                    NestedData(kTypeU32, "NL80211_ATTR_FREQ_RANGE_MAX_BW",
    608                               false)));
    609   reg_rules.deeper_nesting.insert(
    610       AttrDataPair(NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
    611                    NestedData(kTypeU32, "NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN",
    612                               false)));
    613   reg_rules.deeper_nesting.insert(
    614       AttrDataPair(NL80211_ATTR_POWER_RULE_MAX_EIRP,
    615                    NestedData(kTypeU32, "NL80211_ATTR_POWER_RULE_MAX_EIRP",
    616                               false)));
    617 
    618   nested_template_.insert(AttrDataPair(kArrayAttrEnumVal, reg_rules));
    619 }
    620 
    621 const int Nl80211AttributeRegType::kName = NL80211_ATTR_REG_TYPE;
    622 const char Nl80211AttributeRegType::kNameString[] = "NL80211_ATTR_REG_TYPE";
    623 
    624 const int Nl80211AttributeRespIe::kName = NL80211_ATTR_RESP_IE;
    625 const char Nl80211AttributeRespIe::kNameString[] = "NL80211_ATTR_RESP_IE";
    626 
    627 const int Nl80211AttributeRoamSupport::kName = NL80211_ATTR_ROAM_SUPPORT;
    628 const char Nl80211AttributeRoamSupport::kNameString[] =
    629     "NL80211_ATTR_ROAM_SUPPORT";
    630 
    631 const int Nl80211AttributeScanFrequencies::kName =
    632     NL80211_ATTR_SCAN_FREQUENCIES;
    633 const char Nl80211AttributeScanFrequencies::kNameString[] =
    634     "NL80211_ATTR_SCAN_FREQUENCIES";
    635 
    636 Nl80211AttributeScanFrequencies::Nl80211AttributeScanFrequencies()
    637     : NetlinkNestedAttribute(kName, kNameString) {
    638   nested_template_.insert(AttrDataPair(
    639       kArrayAttrEnumVal, NestedData(kTypeU32, "NL80211_SCAN_FREQ", true)));
    640 }
    641 
    642 const int Nl80211AttributeScanSsids::kName = NL80211_ATTR_SCAN_SSIDS;
    643 const char Nl80211AttributeScanSsids::kNameString[] = "NL80211_ATTR_SCAN_SSIDS";
    644 
    645 Nl80211AttributeScanSsids::Nl80211AttributeScanSsids()
    646     : NetlinkNestedAttribute(kName, kNameString) {
    647   nested_template_.insert(AttrDataPair(
    648       kArrayAttrEnumVal, NestedData(kTypeString, "NL80211_SCAN_SSID", true)));
    649 }
    650 
    651 const int Nl80211AttributeStaInfo::kName = NL80211_ATTR_STA_INFO;
    652 const char Nl80211AttributeStaInfo::kNameString[] = "NL80211_ATTR_STA_INFO";
    653 
    654 Nl80211AttributeStaInfo::Nl80211AttributeStaInfo()
    655     : NetlinkNestedAttribute(kName, kNameString) {
    656   NestedData tx_rates(kTypeNested, "NL80211_STA_INFO_TX_BITRATE", false);
    657   tx_rates.deeper_nesting.insert(
    658       AttrDataPair(__NL80211_RATE_INFO_INVALID,
    659                    NestedData(kTypeU32, "__NL80211_RATE_INFO_INVALID", false)));
    660   tx_rates.deeper_nesting.insert(
    661       AttrDataPair(NL80211_RATE_INFO_BITRATE,
    662                    NestedData(kTypeU16, "NL80211_RATE_INFO_BITRATE", false)));
    663   tx_rates.deeper_nesting.insert(
    664       AttrDataPair(NL80211_RATE_INFO_MCS,
    665                    NestedData(kTypeU8, "NL80211_RATE_INFO_MCS", false)));
    666   tx_rates.deeper_nesting.insert(AttrDataPair(
    667       NL80211_RATE_INFO_40_MHZ_WIDTH,
    668       NestedData(kTypeFlag, "NL80211_RATE_INFO_40_MHZ_WIDTH", false)));
    669   tx_rates.deeper_nesting.insert(
    670       AttrDataPair(NL80211_RATE_INFO_SHORT_GI,
    671                    NestedData(kTypeFlag, "NL80211_RATE_INFO_SHORT_GI", false)));
    672   tx_rates.deeper_nesting.insert(
    673       AttrDataPair(NL80211_RATE_INFO_BITRATE32,
    674                    NestedData(kTypeU32, "NL80211_RATE_INFO_BITRATE32", false)));
    675   tx_rates.deeper_nesting.insert(
    676       AttrDataPair(NL80211_RATE_INFO_VHT_MCS,
    677                    NestedData(kTypeU8, "NL80211_RATE_INFO_VHT_MCS", false)));
    678   tx_rates.deeper_nesting.insert(
    679       AttrDataPair(NL80211_RATE_INFO_VHT_NSS,
    680                    NestedData(kTypeU8, "NL80211_RATE_INFO_VHT_NSS", false)));
    681   tx_rates.deeper_nesting.insert(AttrDataPair(
    682       NL80211_RATE_INFO_80_MHZ_WIDTH,
    683       NestedData(kTypeFlag, "NL80211_RATE_INFO_80_MHZ_WIDTH", false)));
    684   tx_rates.deeper_nesting.insert(AttrDataPair(
    685       NL80211_RATE_INFO_80P80_MHZ_WIDTH,
    686       NestedData(kTypeFlag, "NL80211_RATE_INFO_80P80_MHZ_WIDTH", false)));
    687   tx_rates.deeper_nesting.insert(AttrDataPair(
    688       NL80211_RATE_INFO_160_MHZ_WIDTH,
    689       NestedData(kTypeFlag, "NL80211_RATE_INFO_160_MHZ_WIDTH", false)));
    690 
    691   NestedData rx_rates(kTypeNested, "NL80211_STA_INFO_RX_BITRATE", false);
    692   rx_rates.deeper_nesting = tx_rates.deeper_nesting;
    693 
    694   NestedData bss(kTypeNested, "NL80211_STA_INFO_BSS_PARAM", false);
    695   bss.deeper_nesting.insert(AttrDataPair(
    696       __NL80211_STA_BSS_PARAM_INVALID,
    697       NestedData(kTypeU32, "__NL80211_STA_BSS_PARAM_INVALID", false)));
    698   bss.deeper_nesting.insert(AttrDataPair(
    699       NL80211_STA_BSS_PARAM_CTS_PROT,
    700       NestedData(kTypeFlag, "NL80211_STA_BSS_PARAM_CTS_PROT", false)));
    701   bss.deeper_nesting.insert(AttrDataPair(
    702       NL80211_STA_BSS_PARAM_SHORT_PREAMBLE,
    703       NestedData(kTypeFlag, "NL80211_STA_BSS_PARAM_SHORT_PREAMBLE", false)));
    704   bss.deeper_nesting.insert(AttrDataPair(
    705       NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME,
    706       NestedData(kTypeFlag, "NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME", false)));
    707   bss.deeper_nesting.insert(AttrDataPair(
    708       NL80211_STA_BSS_PARAM_DTIM_PERIOD,
    709       NestedData(kTypeU8, "NL80211_STA_BSS_PARAM_DTIM_PERIOD", false)));
    710   bss.deeper_nesting.insert(AttrDataPair(
    711       NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
    712       NestedData(kTypeU16, "NL80211_STA_BSS_PARAM_BEACON_INTERVAL", false)));
    713 
    714   nested_template_.insert(
    715       AttrDataPair(__NL80211_STA_INFO_INVALID,
    716                    NestedData(kTypeU32, "__NL80211_STA_INFO_INVALID", false)));
    717   nested_template_.insert(AttrDataPair(
    718       NL80211_STA_INFO_INACTIVE_TIME,
    719       NestedData(kTypeU32, "NL80211_STA_INFO_INACTIVE_TIME", false)));
    720   nested_template_.insert(
    721       AttrDataPair(NL80211_STA_INFO_RX_BYTES,
    722                    NestedData(kTypeU32, "NL80211_STA_INFO_RX_BYTES", false)));
    723   nested_template_.insert(
    724       AttrDataPair(NL80211_STA_INFO_TX_BYTES,
    725                    NestedData(kTypeU32, "NL80211_STA_INFO_TX_BYTES", false)));
    726   nested_template_.insert(
    727       AttrDataPair(NL80211_STA_INFO_RX_BYTES64,
    728                    NestedData(kTypeU64, "NL80211_STA_INFO_RX_BYTES64", false)));
    729   nested_template_.insert(
    730       AttrDataPair(NL80211_STA_INFO_TX_BYTES64,
    731                    NestedData(kTypeU64, "NL80211_STA_INFO_TX_BYTES64", false)));
    732   nested_template_.insert(
    733       AttrDataPair(NL80211_STA_INFO_LLID,
    734                    NestedData(kTypeU16, "NL80211_STA_INFO_LLID", false)));
    735   nested_template_.insert(
    736       AttrDataPair(NL80211_STA_INFO_PLID,
    737                    NestedData(kTypeU16, "NL80211_STA_INFO_PLID", false)));
    738   nested_template_.insert(
    739       AttrDataPair(NL80211_STA_INFO_PLINK_STATE,
    740                    NestedData(kTypeU8, "NL80211_STA_INFO_PLINK_STATE", false)));
    741   nested_template_.insert(
    742       AttrDataPair(NL80211_STA_INFO_SIGNAL,
    743                    NestedData(kTypeU8, "NL80211_STA_INFO_SIGNAL", false)));
    744   nested_template_.insert(AttrDataPair(NL80211_STA_INFO_TX_BITRATE, tx_rates));
    745   nested_template_.insert(
    746       AttrDataPair(NL80211_STA_INFO_RX_PACKETS,
    747                    NestedData(kTypeU32, "NL80211_STA_INFO_RX_PACKETS", false)));
    748   nested_template_.insert(
    749       AttrDataPair(NL80211_STA_INFO_TX_PACKETS,
    750                    NestedData(kTypeU32, "NL80211_STA_INFO_TX_PACKETS", false)));
    751   nested_template_.insert(
    752       AttrDataPair(NL80211_STA_INFO_TX_RETRIES,
    753                    NestedData(kTypeU32, "NL80211_STA_INFO_TX_RETRIES", false)));
    754   nested_template_.insert(
    755       AttrDataPair(NL80211_STA_INFO_TX_FAILED,
    756                    NestedData(kTypeU32, "NL80211_STA_INFO_TX_FAILED", false)));
    757   nested_template_.insert(
    758       AttrDataPair(NL80211_STA_INFO_SIGNAL_AVG,
    759                    NestedData(kTypeU8, "NL80211_STA_INFO_SIGNAL_AVG", false)));
    760   nested_template_.insert(AttrDataPair(NL80211_STA_INFO_RX_BITRATE, rx_rates));
    761   nested_template_.insert(AttrDataPair(NL80211_STA_INFO_BSS_PARAM, bss));
    762   nested_template_.insert(AttrDataPair(
    763       NL80211_STA_INFO_CONNECTED_TIME,
    764       NestedData(kTypeU32, "NL80211_STA_INFO_CONNECTED_TIME", false)));
    765   nested_template_.insert(
    766       AttrDataPair(NL80211_STA_INFO_STA_FLAGS,
    767                    NestedData(kTypeU64, "NL80211_STA_INFO_STA_FLAGS", false)));
    768   nested_template_.insert(
    769       AttrDataPair(NL80211_STA_INFO_BEACON_LOSS,
    770                    NestedData(kTypeU32, "NL80211_STA_INFO_BEACON_LOSS",
    771                    false)));
    772 }
    773 
    774 const int Nl80211AttributeSurveyInfo::kName = NL80211_ATTR_SURVEY_INFO;
    775 const char Nl80211AttributeSurveyInfo::kNameString[] =
    776                                  "NL80211_ATTR_SURVEY_INFO";
    777 
    778 Nl80211AttributeSurveyInfo::Nl80211AttributeSurveyInfo()
    779     : NetlinkNestedAttribute(kName, kNameString) {
    780   nested_template_.insert(
    781       AttrDataPair(NL80211_SURVEY_INFO_FREQUENCY,
    782          NestedData(kTypeU32, "NL80211_SURVEY_INFO_FREQUENCY", false)));
    783   nested_template_.insert(
    784       AttrDataPair(NL80211_SURVEY_INFO_NOISE,
    785          NestedData(kTypeU8, "NL80211_SURVEY_INFO_NOISE", false)));
    786   nested_template_.insert(
    787       AttrDataPair(NL80211_SURVEY_INFO_IN_USE,
    788          NestedData(kTypeFlag, "NL80211_SURVEY_INFO_IN_USE", false)));
    789   nested_template_.insert(
    790       AttrDataPair(NL80211_SURVEY_INFO_CHANNEL_TIME,
    791          NestedData(kTypeU64, "NL80211_SURVEY_INFO_CHANNEL_TIME", false)));
    792   nested_template_.insert(
    793       AttrDataPair(NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
    794          NestedData(kTypeU64, "NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY", false)));
    795   nested_template_.insert(
    796       AttrDataPair(NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
    797          NestedData(kTypeU64,
    798              "NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY", false)));
    799   nested_template_.insert(
    800       AttrDataPair(NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
    801          NestedData(kTypeU64, "NL80211_SURVEY_INFO_CHANNEL_TIME_RX", false)));
    802   nested_template_.insert(
    803       AttrDataPair(NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
    804          NestedData(kTypeU64, "NL80211_SURVEY_INFO_CHANNEL_TIME_TX", false)));
    805 }
    806 
    807 const int Nl80211AttributeSupportedIftypes::kName =
    808     NL80211_ATTR_SUPPORTED_IFTYPES;
    809 const char Nl80211AttributeSupportedIftypes::kNameString[] =
    810     "NL80211_ATTR_SUPPORTED_IFTYPES";
    811 Nl80211AttributeSupportedIftypes::Nl80211AttributeSupportedIftypes()
    812     : NetlinkNestedAttribute(kName, kNameString) {
    813   nested_template_.insert(AttrDataPair(
    814       kArrayAttrEnumVal,
    815       NestedData(kTypeFlag, "NL80211_SUPPORTED_IFTYPES_IFTYPE", true)));
    816 }
    817 
    818 const int Nl80211AttributeStatusCode::kName = NL80211_ATTR_STATUS_CODE;
    819 const char Nl80211AttributeStatusCode::kNameString[] =
    820     "NL80211_ATTR_STATUS_CODE";
    821 
    822 const int Nl80211AttributeSupportApUapsd::kName = NL80211_ATTR_SUPPORT_AP_UAPSD;
    823 const char Nl80211AttributeSupportApUapsd::kNameString[] =
    824     "NL80211_ATTR_SUPPORT_AP_UAPSD";
    825 
    826 const int Nl80211AttributeSupportIbssRsn::kName = NL80211_ATTR_SUPPORT_IBSS_RSN;
    827 const char Nl80211AttributeSupportIbssRsn::kNameString[] =
    828     "NL80211_ATTR_SUPPORT_IBSS_RSN";
    829 
    830 const int Nl80211AttributeSupportMeshAuth::kName =
    831     NL80211_ATTR_SUPPORT_MESH_AUTH;
    832 const char Nl80211AttributeSupportMeshAuth::kNameString[] =
    833     "NL80211_ATTR_SUPPORT_MESH_AUTH";
    834 
    835 const int Nl80211AttributeTdlsExternalSetup::kName =
    836     NL80211_ATTR_TDLS_EXTERNAL_SETUP;
    837 const char Nl80211AttributeTdlsExternalSetup::kNameString[] =
    838     "NL80211_ATTR_TDLS_EXTERNAL_SETUP";
    839 
    840 const int Nl80211AttributeTdlsSupport::kName = NL80211_ATTR_TDLS_SUPPORT;
    841 const char Nl80211AttributeTdlsSupport::kNameString[] =
    842     "NL80211_ATTR_TDLS_SUPPORT";
    843 
    844 const int Nl80211AttributeTimedOut::kName = NL80211_ATTR_TIMED_OUT;
    845 const char Nl80211AttributeTimedOut::kNameString[] = "NL80211_ATTR_TIMED_OUT";
    846 
    847 const int Nl80211AttributeWiphyAntennaAvailRx::kName =
    848     NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX;
    849 const char Nl80211AttributeWiphyAntennaAvailRx::kNameString[] =
    850     "NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX";
    851 
    852 const int Nl80211AttributeWiphyAntennaAvailTx::kName =
    853     NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX;
    854 const char Nl80211AttributeWiphyAntennaAvailTx::kNameString[] =
    855     "NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX";
    856 
    857 const int Nl80211AttributeWiphyAntennaRx::kName = NL80211_ATTR_WIPHY_ANTENNA_RX;
    858 const char Nl80211AttributeWiphyAntennaRx::kNameString[] =
    859     "NL80211_ATTR_WIPHY_ANTENNA_RX";
    860 
    861 const int Nl80211AttributeWiphyAntennaTx::kName = NL80211_ATTR_WIPHY_ANTENNA_TX;
    862 const char Nl80211AttributeWiphyAntennaTx::kNameString[] =
    863     "NL80211_ATTR_WIPHY_ANTENNA_TX";
    864 
    865 const int Nl80211AttributeWiphyCoverageClass::kName =
    866     NL80211_ATTR_WIPHY_COVERAGE_CLASS;
    867 const char Nl80211AttributeWiphyCoverageClass::kNameString[] =
    868     "NL80211_ATTR_WIPHY_COVERAGE_CLASS";
    869 
    870 const int Nl80211AttributeWiphyFragThreshold::kName =
    871     NL80211_ATTR_WIPHY_FRAG_THRESHOLD;
    872 const char Nl80211AttributeWiphyFragThreshold::kNameString[] =
    873     "NL80211_ATTR_WIPHY_FRAG_THRESHOLD";
    874 
    875 const int Nl80211AttributeWiphyFreq::kName = NL80211_ATTR_WIPHY_FREQ;
    876 const char Nl80211AttributeWiphyFreq::kNameString[] = "NL80211_ATTR_WIPHY_FREQ";
    877 
    878 const int Nl80211AttributeChannelType::kName = NL80211_ATTR_WIPHY_CHANNEL_TYPE;
    879 const char Nl80211AttributeChannelType::kNameString[] =
    880     "NL80211_ATTR_WIPHY_CHANNEL_TYPE";
    881 
    882 const int Nl80211AttributeChannelWidth::kName = NL80211_ATTR_CHANNEL_WIDTH;
    883 const char Nl80211AttributeChannelWidth::kNameString[] =
    884     "NL80211_ATTR_CHANNEL_WIDTH";
    885 
    886 const int Nl80211AttributeCenterFreq1::kName = NL80211_ATTR_CENTER_FREQ1;
    887 const char Nl80211AttributeCenterFreq1::kNameString[] =
    888     "NL80211_ATTR_CENTER_FREQ1";
    889 
    890 const int Nl80211AttributeCenterFreq2::kName = NL80211_ATTR_CENTER_FREQ2;
    891 const char Nl80211AttributeCenterFreq2::kNameString[] =
    892     "NL80211_ATTR_CENTER_FREQ2";
    893 
    894 const int Nl80211AttributeWiphy::kName = NL80211_ATTR_WIPHY;
    895 const char Nl80211AttributeWiphy::kNameString[] = "NL80211_ATTR_WIPHY";
    896 
    897 const int Nl80211AttributeWiphyName::kName = NL80211_ATTR_WIPHY_NAME;
    898 const char Nl80211AttributeWiphyName::kNameString[] = "NL80211_ATTR_WIPHY_NAME";
    899 
    900 const int Nl80211AttributeWiphyRetryLong::kName = NL80211_ATTR_WIPHY_RETRY_LONG;
    901 const char Nl80211AttributeWiphyRetryLong::kNameString[] =
    902     "NL80211_ATTR_WIPHY_RETRY_LONG";
    903 
    904 const int Nl80211AttributeWiphyRetryShort::kName =
    905     NL80211_ATTR_WIPHY_RETRY_SHORT;
    906 const char Nl80211AttributeWiphyRetryShort::kNameString[] =
    907     "NL80211_ATTR_WIPHY_RETRY_SHORT";
    908 
    909 const int Nl80211AttributeWiphyRtsThreshold::kName =
    910     NL80211_ATTR_WIPHY_RTS_THRESHOLD;
    911 const char Nl80211AttributeWiphyRtsThreshold::kNameString[] =
    912     "NL80211_ATTR_WIPHY_RTS_THRESHOLD";
    913 
    914 }  // namespace shill
    915