shill: Fleshes-out and adds some netlink nested attributes.

Adds some methods (|Encode|, for example) to complete nested attributes.
In addition, some attributes have been added and updated.  Some existing
nested attributes are updated to using methods submitted in previous
CLs; some previously attributes previously mis-labeled as raw (I'm
looking at you Nl80211ScanFrequencies and Nl80211ScanSsid) are updated
to nested (since these attributes are used and tested in the Config80211
unittests, those tests -- which pass -- are now testing the nested
attribute parsing methods); and a new nested attribute is added.

BUG=chromium-os:37742
TEST=unittests

Change-Id: Ibcb8fc9b8882b20e2ec901fb706c17a7304cc347
Reviewed-on: https://gerrit.chromium.org/gerrit/44181
Commit-Queue: Wade Guthrie <wdg@chromium.org>
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
diff --git a/nl80211_message.cc b/nl80211_message.cc
index 1b2583f..e49f65e 100644
--- a/nl80211_message.cc
+++ b/nl80211_message.cc
@@ -420,20 +420,21 @@
   }
 
   value->clear();
-  ByteString rawdata;
-  if (!const_attributes()->GetRawAttributeValue(id, &rawdata) &&
-      !rawdata.IsEmpty())
+
+  AttributeListConstRefPtr frequency_list;
+  if (!const_attributes()->ConstGetNestedAttributeList(
+      NL80211_ATTR_SCAN_FREQUENCIES, &frequency_list) || !frequency_list) {
+    LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_FREQUENCIES attribute";
     return false;
+  }
 
-  nlattr *nst = NULL;
-  // |nla_for_each_attr| requires a non-const parameter even though it
-  // doesn't change the data.
-  nlattr *attr_data = reinterpret_cast<nlattr *>(rawdata.GetData());
-  int rem_nst;
-  int len = rawdata.GetLength();
-
-  nla_for_each_attr(nst, attr_data, len, rem_nst) {
-    value->push_back(NetlinkAttribute::NlaGetU32(nst));
+  // Assume IDs for the nested attribute array are linear starting from 1.
+  // Currently, that is enforced in the input to the nested attribute.
+  uint32_t freq;
+  int i = 1;
+  while (frequency_list->GetU32AttributeValue(i, &freq)) {
+    value->push_back(freq);
+    ++i;
   }
   return true;
 }
@@ -446,22 +447,20 @@
     return false;
   }
 
-  ByteString rawdata;
-  if (!const_attributes()->GetRawAttributeValue(id, &rawdata) ||
-      rawdata.IsEmpty())
+  AttributeListConstRefPtr ssid_list;
+  if (!const_attributes()->ConstGetNestedAttributeList(
+      NL80211_ATTR_SCAN_SSIDS, &ssid_list) || !ssid_list) {
+    LOG(ERROR) << "Couldn't get NL80211_ATTR_SCAN_SSIDS attribute";
     return false;
+  }
 
-  nlattr *nst = NULL;
-  // |nla_for_each_attr| requires a non-const parameter even though it
-  // doesn't change the data.
-  nlattr *data = reinterpret_cast<nlattr *>(rawdata.GetData());
-  int rem_nst;
-  int len = rawdata.GetLength();
-
-  nla_for_each_attr(nst, data, len, rem_nst) {
-    value->push_back(StringFromSsid(nla_len(nst),
-                                    reinterpret_cast<const uint8_t *>(
-                                      nla_data(nst))).c_str());
+  // Assume IDs for the nested attribute array are linear starting from 1.
+  // Currently, that is enforced in the input to the nested attribute.
+  string ssid;
+  int i = 1;
+  while (ssid_list->GetStringAttributeValue(i, &ssid)) {
+    value->push_back(ssid);
+    ++i;
   }
   return true;
 }