shill: Adds capability to supply custom parser for netlink attributes.

Some netlink attributes (notably BSS information elements) are provided
as a blob of raw data.  Since the parsing of these blobs is specific to
the attribute in question, the best way to deal with this is to tie the
parser directly to the attribute.  This CL provides a mechanism to do
just that.

BUG=chromium:221118
TEST=unittest (plus, there're some CLs, coming up, that use this feature).

Change-Id: I480cc586e48465f5c8ded816b84e5723097df20a
Reviewed-on: https://gerrit.chromium.org/gerrit/48012
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
Commit-Queue: Wade Guthrie <wdg@chromium.org>
diff --git a/control_netlink_attribute.cc b/control_netlink_attribute.cc
index 31bdb37..60f9252 100644
--- a/control_netlink_attribute.cc
+++ b/control_netlink_attribute.cc
@@ -29,27 +29,16 @@
 const char ControlAttributeAttrOps::kNameString[] = "CTRL_ATTR_OPS";
 
 ControlAttributeAttrOps::ControlAttributeAttrOps()
-      : NetlinkNestedAttribute(kName, kNameString) {}
+      : NetlinkNestedAttribute(kName, kNameString) {
+  NestedData array(NLA_NESTED, "FIRST", true);
+  array.deeper_nesting.push_back(
+      NestedData(NLA_U32, "CTRL_ATTR_OP_UNSPEC", false));
+  array.deeper_nesting.push_back(
+      NestedData(NLA_U32, "CTRL_ATTR_OP_ID", false));
+  array.deeper_nesting.push_back(
+      NestedData(NLA_U32, "CTRL_ATTR_OP_FLAGS", false));
 
-bool ControlAttributeAttrOps::InitFromNlAttr(const nlattr *const_data) {
-  static const NestedData kOps[CTRL_ATTR_OP_MAX  + 1] = {
-    {{NLA_U32, 0, 0}, "CTRL_ATTR_OP_UNSPEC", NULL, 0, false},
-    {{NLA_U32, 0, 0}, "CTRL_ATTR_OP_ID", NULL, 0, false},
-    {{NLA_U32, 0, 0}, "CTRL_ATTR_OP_FLAGS", NULL, 0, false},
-  };
-  static const NestedData kOpsList[] = {
-    {{NLA_NESTED, 0, 0 }, "FIRST", &kOps[0], arraysize(kOps), true},
-  };
-
-  if (!InitNestedFromNlAttr(value_.get(),
-                            kOpsList,
-                            arraysize(kOpsList),
-                            const_data)) {
-    LOG(ERROR) << "InitNestedFromNlAttr() failed";
-    return false;
-  }
-  has_a_value_ = true;
-  return true;
+  nested_template_.push_back(array);
 }
 
 const int ControlAttributeMcastGroups::kName = CTRL_ATTR_MCAST_GROUPS;
@@ -57,28 +46,16 @@
     "CTRL_ATTR_MCAST_GROUPS";
 
 ControlAttributeMcastGroups::ControlAttributeMcastGroups()
-      : NetlinkNestedAttribute(kName, kNameString) {}
+      : NetlinkNestedAttribute(kName, kNameString) {
+  NestedData array(NLA_NESTED, "FIRST", true);
+  array.deeper_nesting.push_back(
+      NestedData(NLA_U32, "CTRL_ATTR_MCAST_GRP_UNSPEC", false));
+  array.deeper_nesting.push_back(
+      NestedData(NLA_STRING, "CTRL_ATTR_MCAST_GRP_NAME", false));
+  array.deeper_nesting.push_back(
+      NestedData(NLA_U32, "CTRL_ATTR_MCAST_GRP_ID", false));
 
-bool ControlAttributeMcastGroups::InitFromNlAttr(const nlattr *const_data) {
-  static const NestedData kMulticast[CTRL_ATTR_MCAST_GRP_MAX  + 1] = {
-    {{NLA_U32, 0, 0}, "CTRL_ATTR_MCAST_GRP_UNSPEC", NULL, 0, false},
-    {{NLA_STRING, 0, 0}, "CTRL_ATTR_MCAST_GRP_NAME", NULL, 0, false},
-    {{NLA_U32, 0, 0}, "CTRL_ATTR_MCAST_GRP_ID", NULL, 0, false},
-  };
-  static const NestedData kMulticastList[] = {
-    {{NLA_NESTED, 0, 0}, "FIRST", &kMulticast[0], arraysize(kMulticast),
-      true},
-  };
-
-  if (!InitNestedFromNlAttr(value_.get(),
-                            kMulticastList,
-                            arraysize(kMulticastList),
-                            const_data)) {
-    LOG(ERROR) << "InitNestedFromNlAttr() failed";
-    return false;
-  }
-  has_a_value_ = true;
-  return true;
+  nested_template_.push_back(array);
 }
 
 }  // namespace shill