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_;