summaryrefslogtreecommitdiff
path: root/src/platform/nm-netlink.c
diff options
context:
space:
mode:
authorJavier Arteaga <jarteaga@jbeta.is>2018-03-29 21:00:28 +0100
committerThomas Haller <thaller@redhat.com>2018-03-30 22:09:04 +0200
commit56e79a4e07e70f7786aa5bcfb6d2aedf082c1cd6 (patch)
tree08c6d978feb6d1ec1f216d0451e7c04f8ed047e9 /src/platform/nm-netlink.c
parentddc2c5f215d2d817329aabe776551eae87c293ab (diff)
downloadNetworkManager-56e79a4e07e70f7786aa5bcfb6d2aedf082c1cd6.tar.gz
platform: move genl_ctrl_resolve to nm-netlink.c
Move genl_ctrl_resolve out of the wifi code so it can be reused by other interfaces based on genetlink. https://mail.gnome.org/archives/networkmanager-list/2018-March/msg00044.html
Diffstat (limited to 'src/platform/nm-netlink.c')
-rw-r--r--src/platform/nm-netlink.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c
index f935774877..4cb19780b0 100644
--- a/src/platform/nm-netlink.c
+++ b/src/platform/nm-netlink.c
@@ -783,6 +783,74 @@ genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
genlmsg_attrlen (ghdr, hdrlen), policy);
}
+static int
+_genl_parse_getfamily (struct nl_msg *msg, void *arg)
+{
+ static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
+ [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
+ [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING,
+ .maxlen = GENL_NAMSIZ },
+ [CTRL_ATTR_VERSION] = { .type = NLA_U32 },
+ [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 },
+ [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 },
+ [CTRL_ATTR_OPS] = { .type = NLA_NESTED },
+ [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED },
+ };
+ struct nlattr *tb[CTRL_ATTR_MAX+1];
+ struct nlmsghdr *nlh = nlmsg_hdr (msg);
+ gint32 *response_data = arg;
+
+ if (genlmsg_parse (nlh, 0, tb, CTRL_ATTR_MAX, ctrl_policy))
+ return NL_SKIP;
+
+ if (tb[CTRL_ATTR_FAMILY_ID])
+ *response_data = nla_get_u16 (tb[CTRL_ATTR_FAMILY_ID]);
+
+ return NL_STOP;
+}
+
+int
+genl_ctrl_resolve (struct nl_sock *sk, const char *name)
+{
+ nm_auto_nlmsg struct nl_msg *msg = NULL;
+ int result = -ENOMEM;
+ gint32 response_data = -1;
+ const struct nl_cb cb = {
+ .valid_cb = _genl_parse_getfamily,
+ .valid_arg = &response_data,
+ };
+
+ msg = nlmsg_alloc ();
+
+ if (!genlmsg_put (msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL,
+ 0, 0, CTRL_CMD_GETFAMILY, 1))
+ goto out;
+
+ if (nla_put_string (msg, CTRL_ATTR_FAMILY_NAME, name) < 0)
+ goto out;
+
+ result = nl_send_auto (sk, msg);
+ if (result < 0)
+ goto out;
+
+ result = nl_recvmsgs (sk, &cb);
+ if (result < 0)
+ goto out;
+
+ /* If search was successful, request may be ACKed after data */
+ result = nl_wait_for_ack (sk, NULL);
+ if (result < 0)
+ goto out;
+
+ if (response_data > 0)
+ result = response_data;
+ else
+ result = -ENOENT;
+
+out:
+ return result;
+}
+
/*****************************************************************************/
struct nl_sock *