diff options
author | Javier Arteaga <jarteaga@jbeta.is> | 2018-03-29 21:00:28 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-03-30 22:09:04 +0200 |
commit | 56e79a4e07e70f7786aa5bcfb6d2aedf082c1cd6 (patch) | |
tree | 08c6d978feb6d1ec1f216d0451e7c04f8ed047e9 /src/platform/nm-netlink.c | |
parent | ddc2c5f215d2d817329aabe776551eae87c293ab (diff) | |
download | NetworkManager-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.c | 68 |
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 * |