shill: Use nllib for group name resolutions

Newer versions of libnl will do the work to resolve netlink group names
on its own.  Let it do the heavy lifting.

BUG=chromium-os:36122
TEST=Message flow through Config80211, unit tests

Change-Id: I29ea945994ce50473393817ed03be087f3e54bbd
Reviewed-on: https://gerrit.chromium.org/gerrit/37680
Tested-by: Christopher Wiley <wiley@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Christopher Wiley <wiley@chromium.org>
diff --git a/nl80211_socket.cc b/nl80211_socket.cc
index 47126b2..08d9d59 100644
--- a/nl80211_socket.cc
+++ b/nl80211_socket.cc
@@ -70,166 +70,20 @@
 }
 
 bool Nl80211Socket::AddGroupMembership(const string &group_name) {
-  int id = GetMulticastGroupId(group_name);
+  int id = genl_ctrl_resolve_grp(GetNlSock(),
+                                 kSocketFamilyName,
+                                 group_name.c_str());
   if (id < 0) {
     LOG(ERROR) << "No Id for group " << group_name;
     return false;
-  } else {
-    int result = nl_socket_add_membership(GetNlSock(), id);
-    if (result != 0) {
-      LOG(ERROR) << "Failed call to 'nl_socket_add_membership': " << result;
-      return false;
-    }
+  }
+  int result = nl_socket_add_membership(GetNlSock(), id);
+  if (result != 0) {
+    LOG(ERROR) << "Failed to join netlink multicast group: " << result;
+    return false;
   }
   LOG(INFO) << " Group " << group_name << " added successfully";
   return true;
 }
 
-int Nl80211Socket::OnAck(struct nl_msg *unused_msg, void *arg) {
-  if (arg) {
-    int *ret = reinterpret_cast<int *>(arg);
-    *ret = 0;
-  }
-  return NL_STOP;  // Stop parsing and discard remainder of buffer.
-}
-
-int Nl80211Socket::OnError(struct sockaddr_nl *unused_nla, struct nlmsgerr *err,
-                           void *arg) {
-  int *ret = reinterpret_cast<int *>(arg);
-  if (err) {
-    if (ret)
-      *ret = err->error;
-    LOG(ERROR) << "Error(" << err->error << ") " << strerror(err->error);
-  } else {
-    if (ret)
-      *ret = -1;
-    LOG(ERROR) << "Error(<unknown>)";
-  }
-  return NL_STOP;  // Stop parsing and discard remainder of buffer.
-}
-
-int Nl80211Socket::OnFamilyResponse(struct nl_msg *msg, void *arg) {
-  if (!msg) {
-    LOG(ERROR) << "NULL |msg| parameter";
-    return NL_SKIP;  // Skip current message, continue parsing buffer.
-  }
-
-  if (!arg) {
-    LOG(ERROR) << "NULL |arg| parameter";
-    return NL_SKIP;  // Skip current message, continue parsing buffer.
-  }
-
-  struct HandlerArgs *grp = reinterpret_cast<struct HandlerArgs *>(arg);
-  struct nlattr *tb[CTRL_ATTR_MAX + 1];
-  struct genlmsghdr *gnlh = reinterpret_cast<struct genlmsghdr *>(
-      nlmsg_data(nlmsg_hdr(msg)));
-  struct nlattr *mcgrp = NULL;
-  int rem_mcgrp;
-
-  nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
-            genlmsg_attrlen(gnlh, 0), NULL);
-
-  if (!tb[CTRL_ATTR_MCAST_GROUPS])
-    return NL_SKIP;  // Skip current message, continue parsing buffer.
-
-  // nla_for_each_nested(...)
-  mcgrp = reinterpret_cast<nlattr *>(nla_data(tb[CTRL_ATTR_MCAST_GROUPS]));
-  rem_mcgrp = nla_len(tb[CTRL_ATTR_MCAST_GROUPS]);
-  bool found_one = false;
-  for (; nla_ok(mcgrp, rem_mcgrp); mcgrp = nla_next(mcgrp, &(rem_mcgrp))) {
-    struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
-
-    nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
-        reinterpret_cast<nlattr *>(nla_data(mcgrp)), nla_len(mcgrp), NULL);
-
-    if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]) {
-      LOG(ERROR) << "No group name in 'group' message";
-      continue;
-    } else if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]) {
-      LOG(ERROR) << "No group id in 'group' message";
-      continue;
-    }
-
-    if (strncmp(reinterpret_cast<char *>(
-        nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])),
-          grp->group, nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]))) {
-      continue;
-    }
-    found_one = true;
-    grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
-    SLOG(WiFi, 6) << "GROUP '"
-                  << reinterpret_cast<char *>(
-                      nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]))
-                  << "' has ID "
-                  << grp->id;
-    break;
-  }
-  if (!found_one) {
-    LOG(ERROR) << "NO GROUP matched '"
-               << grp->group
-               << "', the one for which we were looking";
-  }
-
-  return NL_SKIP;  // Skip current message, continue parsing buffer.
-}
-
-int Nl80211Socket::GetMulticastGroupId(const string &group) {
-  // Allocate and build the message.
-  KernelBoundNlMessage message;
-  if (!message.Init()) {
-    LOG(ERROR) << "Couldn't initialize message";
-    return -1;
-  }
-
-  if (!message.AddNetlinkHeader(this, NL_AUTO_PID, NL_AUTO_SEQ, GetFamilyId(),
-                                0, 0, CTRL_CMD_GETFAMILY, 0))
-    return -1;
-
-  int result = message.AddAttribute(CTRL_ATTR_FAMILY_NAME,
-                                    GetSocketFamilyName().length() + 1,
-                                    GetSocketFamilyName().c_str());
-  if (result < 0) {
-    LOG(ERROR) << "nla_put return error: " << result;
-    return -1;
-  }
-
-  if (!message.Send(this)) {
-    return -1;
-  }
-
-  // Wait for the response.
-
-  NetlinkSocket::Callback netlink_callback;
-  struct HandlerArgs grp(group.c_str(), -ENOENT);
-  int status = 1;
-
-  if (netlink_callback.Init()) {
-    if (!netlink_callback.ErrHandler(NL_CB_CUSTOM, OnError, &status)) {
-      return -1;
-    }
-    if (!netlink_callback.SetHandler(NL_CB_ACK, NL_CB_CUSTOM, OnAck, &status)) {
-      return -1;
-    }
-    if (!netlink_callback.SetHandler(NL_CB_VALID, NL_CB_CUSTOM,
-                                     OnFamilyResponse, &grp)) {
-      return -1;
-    }
-  } else {
-    LOG(ERROR) << "Couldn't initialize callback";
-    return -1;
-  }
-
-  while (status > 0) {  // 'status' is set by the NL_CB_ACK handler.
-    if (!GetMessagesUsingCallback(&netlink_callback)) {
-      return -1;
-    }
-  }
-
-  if (status != 0) {
-    return -1;
-  }
-
-  return grp.id;
-}
-
 }  // namespace shill
diff --git a/nl80211_socket.h b/nl80211_socket.h
index c0e9cde..cc8823b 100644
--- a/nl80211_socket.h
+++ b/nl80211_socket.h
@@ -66,30 +66,9 @@
   }
 
  private:
-  struct HandlerArgs {
-    HandlerArgs() : group(NULL), id(0) {}
-    HandlerArgs(const char *group_arg, int id_arg) :
-      group(group_arg), id(id_arg) {}
-    const char *group;
-    int id;
-  };
-
-  // Contains 'nl80211', the family name of the netlink socket.
+  // The family name of this particular netlink socket.
   static const char kSocketFamilyName[];
 
-  // Method called by cfg80211 to acknowledge messages sent to cfg80211.
-  static int OnAck(nl_msg *unused_msg, void *arg);
-
-  // Method called by cfg80211 for message errors.
-  static int OnError(sockaddr_nl *unused_nla, nlmsgerr *err, void *arg);
-
-  // Netlink Callback for handling response to 'CTRL_CMD_GETFAMILY' message.
-  static int OnFamilyResponse(nl_msg *msg, void *arg);
-
-  // Gets an ID for a specified type of multicast messages sent from the
-  // cfg80211 module.
-  virtual int GetMulticastGroupId(const std::string &group);
-
   // The id returned by a call to 'genl_ctrl_resolve'.
   int nl80211_id_;