mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-03 17:08:11 +02:00
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
This commit is contained in:
parent
ddc2c5f215
commit
56e79a4e07
3 changed files with 88 additions and 96 deletions
|
|
@ -783,6 +783,74 @@ genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
|
||||||
genlmsg_attrlen (ghdr, hdrlen), policy);
|
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 *
|
struct nl_sock *
|
||||||
|
|
|
||||||
|
|
@ -409,21 +409,6 @@ struct nlmsghdr *nlmsg_put (struct nl_msg *n, uint32_t pid, uint32_t seq,
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void *genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family,
|
|
||||||
int hdrlen, int flags, uint8_t cmd, uint8_t version);
|
|
||||||
void *genlmsg_data (const struct genlmsghdr *gnlh);
|
|
||||||
void *genlmsg_user_hdr (const struct genlmsghdr *gnlh);
|
|
||||||
struct genlmsghdr *genlmsg_hdr (struct nlmsghdr *nlh);
|
|
||||||
void *genlmsg_user_data (const struct genlmsghdr *gnlh, const int hdrlen);
|
|
||||||
struct nlattr *genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen);
|
|
||||||
int genlmsg_len (const struct genlmsghdr *gnlh);
|
|
||||||
int genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen);
|
|
||||||
int genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen);
|
|
||||||
int genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
|
|
||||||
int maxtype, const struct nla_policy *policy);
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
#define NL_AUTO_PORT 0
|
#define NL_AUTO_PORT 0
|
||||||
#define NL_AUTO_SEQ 0
|
#define NL_AUTO_SEQ 0
|
||||||
|
|
||||||
|
|
@ -506,4 +491,21 @@ int nl_socket_set_ext_ack (struct nl_sock *sk, gboolean enable);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void *genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family,
|
||||||
|
int hdrlen, int flags, uint8_t cmd, uint8_t version);
|
||||||
|
void *genlmsg_data (const struct genlmsghdr *gnlh);
|
||||||
|
void *genlmsg_user_hdr (const struct genlmsghdr *gnlh);
|
||||||
|
struct genlmsghdr *genlmsg_hdr (struct nlmsghdr *nlh);
|
||||||
|
void *genlmsg_user_data (const struct genlmsghdr *gnlh, const int hdrlen);
|
||||||
|
struct nlattr *genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen);
|
||||||
|
int genlmsg_len (const struct genlmsghdr *gnlh);
|
||||||
|
int genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen);
|
||||||
|
int genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen);
|
||||||
|
int genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
|
||||||
|
int maxtype, const struct nla_policy *policy);
|
||||||
|
|
||||||
|
int genl_ctrl_resolve (struct nl_sock *sk, const char *name);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
#endif /* __NM_NETLINK_H__ */
|
#endif /* __NM_NETLINK_H__ */
|
||||||
|
|
|
||||||
|
|
@ -46,86 +46,6 @@
|
||||||
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||||
} G_STMT_END
|
} G_STMT_END
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* Reimplementation of libnl3/genl functions:
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
static int
|
|
||||||
probe_response (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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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 = probe_response,
|
|
||||||
.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:
|
|
||||||
if (result >= 0)
|
|
||||||
_LOGD (LOGD_WIFI, "genl_ctrl_resolve: resolved \"%s\" as 0x%x", name, result);
|
|
||||||
else
|
|
||||||
_LOGE (LOGD_WIFI, "genl_ctrl_resolve: failed resolve \"%s\"", name);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* </libn-genl-3>
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WifiData parent;
|
WifiData parent;
|
||||||
struct nl_sock *nl_sock;
|
struct nl_sock *nl_sock;
|
||||||
|
|
@ -960,8 +880,10 @@ wifi_nl80211_init (int ifindex)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
nl80211->id = genl_ctrl_resolve (nl80211->nl_sock, "nl80211");
|
nl80211->id = genl_ctrl_resolve (nl80211->nl_sock, "nl80211");
|
||||||
if (nl80211->id < 0)
|
if (nl80211->id < 0) {
|
||||||
|
_LOGD (LOGD_WIFI, "genl_ctrl_resolve: failed to resolve \"nl80211\"");
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
nl80211->phy = -1;
|
nl80211->phy = -1;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue