[08/10] alfred: Query TQ of originators via netlink
Commit Message
The debugfs entries are only available on the main network namespace. All
other network namespaces have to fall back to netlink to read the
originator table.
alfred has therefore try to access the originator via netlink and try to
fall back to the debugfs table in case the batman-adv module doesn't
support BATADV_CMD_GET_ORIGINATORS.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
batadv_query.c | 8 +++++-
netlink.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
netlink.h | 2 ++
3 files changed, 94 insertions(+), 1 deletion(-)
@@ -366,13 +366,19 @@ uint8_t get_tq(const char *mesh_iface, struct ether_addr *mac)
{
struct ether_addr in_mac;
uint8_t tq = 0;
+ int ret;
/* input mac has to be copied because it could be in the shared
* ether_aton buffer
*/
memcpy(&in_mac, mac, sizeof(in_mac));
- get_tq_debugfs(mesh_iface, &in_mac, &tq);
+ enable_net_admin_capability(1);
+ ret = get_tq_netlink(mesh_iface, &in_mac, &tq);
+ enable_net_admin_capability(0);
+
+ if (ret == -EOPNOTSUPP)
+ get_tq_debugfs(mesh_iface, &in_mac, &tq);
return tq;
}
@@ -280,3 +280,88 @@ int translate_mac_netlink(const char *mesh_iface, const struct ether_addr *mac,
return 0;
}
+
+static const int get_tq_netlink_mandatory[] = {
+ BATADV_ATTR_ORIG_ADDRESS,
+ BATADV_ATTR_TQ,
+};
+
+struct get_tq_netlink_opts {
+ struct ether_addr mac;
+ uint8_t tq;
+ bool found;
+ struct nlquery_opts query_opts;
+};
+
+static int get_tq_netlink_cb(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *attrs[BATADV_ATTR_MAX+1];
+ struct nlmsghdr *nlh = nlmsg_hdr(msg);
+ struct nlquery_opts *query_opts = arg;
+ struct get_tq_netlink_opts *opts;
+ struct genlmsghdr *ghdr;
+ uint8_t *orig;
+ uint8_t tq;
+
+ opts = container_of(query_opts, struct get_tq_netlink_opts,
+ query_opts);
+
+ if (!genlmsg_valid_hdr(nlh, 0))
+ return NL_OK;
+
+ ghdr = nlmsg_data(nlh);
+
+ if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS)
+ return NL_OK;
+
+ if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
+ genlmsg_len(ghdr), batadv_netlink_policy)) {
+ return NL_OK;
+ }
+
+ if (missing_mandatory_attrs(attrs, get_tq_netlink_mandatory,
+ ARRAY_SIZE(get_tq_netlink_mandatory)))
+ return NL_OK;
+
+ orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
+ tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);
+
+ if (!attrs[BATADV_ATTR_FLAG_BEST])
+ return NL_OK;
+
+ if (memcmp(&opts->mac, orig, ETH_ALEN) != 0)
+ return NL_OK;
+
+ opts->tq = tq;
+ opts->found = true;
+ opts->query_opts.err = 0;
+
+ return NL_STOP;
+}
+
+int get_tq_netlink(const char *mesh_iface, const struct ether_addr *mac,
+ uint8_t *tq)
+{
+ struct get_tq_netlink_opts opts = {
+ .tq = 0,
+ .found = false,
+ .query_opts = {
+ .err = 0,
+ },
+ };
+ int ret;
+
+ memcpy(&opts.mac, mac, ETH_ALEN);
+
+ ret = netlink_query_common(mesh_iface, BATADV_CMD_GET_ORIGINATORS,
+ get_tq_netlink_cb, &opts.query_opts);
+ if (ret < 0)
+ return ret;
+
+ if (!opts.found)
+ return -ENOENT;
+
+ *tq = opts.tq;
+
+ return 0;
+}
@@ -47,6 +47,8 @@ int missing_mandatory_attrs(struct nlattr *attrs[], const int mandatory[],
size_t num);
int translate_mac_netlink(const char *mesh_iface, const struct ether_addr *mac,
struct ether_addr *mac_out);
+int get_tq_netlink(const char *mesh_iface, const struct ether_addr *mac,
+ uint8_t *tq);
extern struct nla_policy batadv_netlink_policy[];