b.a.t.m.a.n.lists.open-mesh.org archive mirror
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] [PATCH 0/3] batctl: Add netlink support for sysfs-only functionality
@ 2019-04-03 18:01 Sven Eckelmann
  2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Support checking of meshif without sysfs Sven Eckelmann
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Sven Eckelmann @ 2019-04-03 18:01 UTC (permalink / raw)
  To: b.a.t.m.a.n

Hi,

some functionality in batctl was previously using sysfs to implement some
of its features. Since the sysfs support can now be disabled in the kernel,
these features were broken in such setups. This was especially problematic
for functionality which depends on the main mesh interface. The check to
make sure that this is interface is a valid batadv interface were
exclusively using sysfs.

Switching them to (or actually extending them to support) netlink should
fix this. The old sysfs functionality is still here but can be removed in
the future.

Kind regards,
	Sven

Sven Eckelmann (3):
  batctl: Support checking of meshif without sysfs
  batctl: Reimplement VLAN translation using helper
  batctl: Add netlink fallback for sysfs' iface_status

 debug.c     |   2 +-
 functions.c | 407 ++++++++++++++++++++++++++++++----------------------
 functions.h |   2 +-
 interface.c |  92 +++++++++++-
 4 files changed, 331 insertions(+), 172 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [B.A.T.M.A.N.] [PATCH 1/3] batctl: Support checking of meshif without sysfs
  2019-04-03 18:01 [B.A.T.M.A.N.] [PATCH 0/3] batctl: Add netlink support for sysfs-only functionality Sven Eckelmann
@ 2019-04-03 18:01 ` Sven Eckelmann
  2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 2/3] batctl: Reimplement VLAN translation using helper Sven Eckelmann
  2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 3/3] batctl: Add netlink fallback for sysfs' iface_status Sven Eckelmann
  2 siblings, 0 replies; 4+ messages in thread
From: Sven Eckelmann @ 2019-04-03 18:01 UTC (permalink / raw)
  To: b.a.t.m.a.n

batctl checks whether the supplied interface is a batadv interface. And for
hardif filters, whether this hardif is part of the selected meshif. This
was done traditionally using the sysfs files which batman-adv creates.

It is now possible to build the kernel module without sysfs support. These
checks must therefore also work when sysfs is not available. And since the
sysfs interface support was replaced in batctl by netlink commands, the
check should also be implemented using using NETLINK_ROUTE.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 debug.c     |   2 +-
 functions.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++-----
 functions.h |   2 +-
 3 files changed, 176 insertions(+), 20 deletions(-)

diff --git a/debug.c b/debug.c
index 4a3b6cb..597d59c 100644
--- a/debug.c
+++ b/debug.c
@@ -115,7 +115,7 @@ int handle_debug_table(struct state *state, int argc, char **argv)
 				return EXIT_FAILURE;
 			}
 
-			if (check_mesh_iface_ownership(state->mesh_iface, optarg) != EXIT_SUCCESS)
+			if (check_mesh_iface_ownership(state, optarg) != EXIT_SUCCESS)
 				return EXIT_FAILURE;
 
 			orig_iface = optarg;
diff --git a/functions.c b/functions.c
index 9720257..b52db08 100644
--- a/functions.c
+++ b/functions.c
@@ -1039,37 +1039,178 @@ int translate_mesh_iface(struct state *state)
 	return 0;
 }
 
-int check_mesh_iface(struct state *state)
+struct rtnl_link_iface_data {
+	uint8_t kind_found:1;
+	uint8_t master_found:1;
+	char kind[IF_NAMESIZE];
+	unsigned int master;
+};
+
+static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg)
+{
+	static struct nla_policy link_policy[IFLA_MAX + 1] = {
+		[IFLA_LINKINFO] = { .type = NLA_NESTED },
+		[IFLA_MASTER] = { .type = NLA_U32 },
+	};
+	static struct nla_policy link_info_policy[IFLA_INFO_MAX + 1] = {
+		[IFLA_INFO_KIND] = { .type = NLA_STRING },
+	};
+
+	struct rtnl_link_iface_data *link_data = arg;
+	struct nlattr *li[IFLA_INFO_MAX + 1];
+	struct nlmsghdr *n = nlmsg_hdr(msg);
+	struct nlattr *tb[IFLA_MAX + 1];
+	char *type;
+	int ret;
+
+	if (!nlmsg_valid_hdr(n, sizeof(struct ifinfomsg)))
+		return NL_OK;
+
+	ret = nlmsg_parse(n, sizeof(struct ifinfomsg), tb, IFLA_MAX,
+			  link_policy);
+	if (ret < 0)
+		return NL_OK;
+
+	if (tb[IFLA_MASTER]) {
+		link_data->master = nla_get_u32(tb[IFLA_MASTER]);
+		link_data->master_found = true;
+	}
+
+	/* parse subattributes linkinfo */
+	if (!tb[IFLA_LINKINFO])
+		return NL_OK;
+
+	ret = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO],
+			       link_info_policy);
+	if (ret < 0)
+		return NL_OK;
+
+	if (li[IFLA_INFO_KIND]) {
+		type = nla_get_string(li[IFLA_INFO_KIND]);
+		strncpy(link_data->kind, type, sizeof(link_data->kind));
+		link_data->kind[sizeof(link_data->kind) - 1] = '\0';
+
+		link_data->kind_found = true;
+	}
+
+	return NL_STOP;
+}
+
+static int query_rtnl_link_single(int mesh_ifindex,
+				  struct rtnl_link_iface_data *link_data)
+{
+	struct ifinfomsg ifinfo = {
+		.ifi_family = AF_UNSPEC,
+		.ifi_index = mesh_ifindex,
+	};
+	struct nl_cb *cb = NULL;
+	struct nl_sock *sock;
+	int ret;
+
+	link_data->kind_found = false;
+	link_data->master_found = false;
+
+	sock = nl_socket_alloc();
+	if (!sock)
+		return -1;
+
+	ret = nl_connect(sock, NETLINK_ROUTE);
+	if (ret < 0)
+		goto free_sock;
+
+	ret = nl_send_simple(sock, RTM_GETLINK, NLM_F_REQUEST,
+			     &ifinfo, sizeof(ifinfo));
+	if (ret < 0)
+		goto free_sock;
+
+	cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (!cb)
+		goto free_sock;
+
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, query_rtnl_link_single_parse,
+		  link_data);
+	nl_recvmsgs(sock, cb);
+
+	nl_cb_put(cb);
+free_sock:
+	nl_socket_free(sock);
+
+	return 0;
+}
+
+int check_mesh_iface_netlink(struct state *state)
+{
+	struct rtnl_link_iface_data link_data;
+
+	query_rtnl_link_single(state->mesh_ifindex, &link_data);
+	if (!link_data.kind_found)
+		return -1;
+
+	if (strcmp(link_data.kind, "batadv") != 0)
+		return -1;
+
+	return 0;
+}
+
+static int check_mesh_iface_sysfs(struct state *state)
 {
 	char path_buff[PATH_BUFF_LEN];
-	int ret = -1;
 	DIR *dir;
 
-	/* use the parent interface if this is a VLAN */
-	if (state->vid >= 0)
-		snprintf(path_buff, PATH_BUFF_LEN, SYS_VLAN_PATH,
-			 state->mesh_iface, state->vid);
-	else
-		snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT,
-			 state->mesh_iface);
-
 	/* try to open the mesh sys directory */
+	snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT,
+		 state->mesh_iface);
+
 	dir = opendir(path_buff);
 	if (!dir)
-		goto out;
+		return -1;
 
 	closedir(dir);
 
+	return 0;
+}
+
+int check_mesh_iface(struct state *state)
+{
+	int ret;
+
 	state->mesh_ifindex = if_nametoindex(state->mesh_iface);
 	if (state->mesh_ifindex == 0)
-		goto out;
+		return -1;
 
-	ret = 0;
-out:
-	return ret;
+	ret = check_mesh_iface_netlink(state);
+	if (ret == 0)
+		return ret;
+
+	ret = check_mesh_iface_sysfs(state);
+	if (ret == 0)
+		return ret;
+
+	return -1;
 }
 
-int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface)
+static int check_mesh_iface_ownership_netlink(struct state *state,
+					      char *hard_iface)
+{
+	struct rtnl_link_iface_data link_data;
+	unsigned int hardif_index;
+
+	hardif_index = if_nametoindex(hard_iface);
+	if (hardif_index == 0)
+		return EXIT_FAILURE;
+
+	query_rtnl_link_single(hardif_index, &link_data);
+	if (!link_data.master_found)
+		return EXIT_FAILURE;
+
+	if (state->mesh_ifindex != link_data.master)
+		return EXIT_FAILURE;
+
+	return EXIT_SUCCESS;
+}
+
+static int check_mesh_iface_ownership_sysfs(struct state *state,
+					    char *hard_iface)
 {
 	char path_buff[PATH_BUFF_LEN];
 	int res;
@@ -1087,15 +1228,30 @@ int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface)
 	if (line_ptr[strlen(line_ptr) - 1] == '\n')
 		line_ptr[strlen(line_ptr) - 1] = '\0';
 
-	if (strcmp(line_ptr, mesh_iface) != 0) {
+	if (strcmp(line_ptr, state->mesh_iface) != 0) {
 		fprintf(stderr, "Error - interface %s is part of batman network %s, not %s\n",
-			hard_iface, line_ptr, mesh_iface);
+			hard_iface, line_ptr, state->mesh_iface);
 		return EXIT_FAILURE;
 	}
 
 	return EXIT_SUCCESS;
 }
 
+int check_mesh_iface_ownership(struct state *state, char *hard_iface)
+{
+	int ret;
+
+	ret = check_mesh_iface_ownership_netlink(state, hard_iface);
+	if (ret == EXIT_SUCCESS)
+		return EXIT_SUCCESS;
+
+	ret = check_mesh_iface_ownership_sysfs(state, hard_iface);
+	if (ret == EXIT_SUCCESS)
+		return ret;
+
+	return EXIT_FAILURE;
+}
+
 static int get_random_bytes_syscall(void *buf __maybe_unused,
 				    size_t buflen __maybe_unused)
 {
diff --git a/functions.h b/functions.h
index 23186e5..02f7823 100644
--- a/functions.h
+++ b/functions.h
@@ -53,7 +53,7 @@ int netlink_simple_request(struct nl_msg *msg);
 int translate_mesh_iface(struct state *state);
 int get_algoname(const char *mesh_iface, char *algoname, size_t algoname_len);
 int check_mesh_iface(struct state *state);
-int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface);
+int check_mesh_iface_ownership(struct state *state, char *hard_iface);
 
 void get_random_bytes(void *buf, size_t buflen);
 void check_root_or_die(const char *cmd);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [B.A.T.M.A.N.] [PATCH 2/3] batctl: Reimplement VLAN translation using helper
  2019-04-03 18:01 [B.A.T.M.A.N.] [PATCH 0/3] batctl: Add netlink support for sysfs-only functionality Sven Eckelmann
  2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Support checking of meshif without sysfs Sven Eckelmann
@ 2019-04-03 18:01 ` Sven Eckelmann
  2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 3/3] batctl: Add netlink fallback for sysfs' iface_status Sven Eckelmann
  2 siblings, 0 replies; 4+ messages in thread
From: Sven Eckelmann @ 2019-04-03 18:01 UTC (permalink / raw)
  To: b.a.t.m.a.n

The functionality to translate VLAN interfaces to mesh interfaces and VID
is using NETLINK_ROUTE like the query_rtnl_link_single helper function.
Only minimal changes are required to also provide the link to the
underlying device and the VID.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 functions.c | 229 ++++++++++++++++------------------------------------
 1 file changed, 71 insertions(+), 158 deletions(-)

diff --git a/functions.c b/functions.c
index b52db08..bb7f517 100644
--- a/functions.c
+++ b/functions.c
@@ -760,149 +760,6 @@ struct ether_addr *resolve_mac(const char *asc)
 	return mac_result;
 }
 
-struct vlan_get_link_nl_arg {
-	char *iface;
-	int vid;
-};
-
-static struct nla_policy info_data_link_policy[IFLA_MAX + 1] = {
-	[IFLA_LINKINFO]	= { .type = NLA_NESTED },
-	[IFLA_LINK]	= { .type = NLA_U32 },
-};
-
-static struct nla_policy info_data_link_info_policy[IFLA_INFO_MAX + 1] = {
-	[IFLA_INFO_DATA]	= { .type = NLA_NESTED },
-};
-
-static struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
-	[IFLA_VLAN_ID]		= { .type = NLA_U16 },
-};
-
-/**
- * vlan_get_link_parse - parse a get_link rtnl message and extract the important
- *  data
- * @msg: the reply msg
- * @arg: pointer to the buffer which will store the return values
- *
- * Saves the vid  in arg::vid in case of success or -1 otherwise
- */
-static int vlan_get_link_parse(struct nl_msg *msg, void *arg)
-{
-	struct vlan_get_link_nl_arg *nl_arg = arg;
-	struct nlmsghdr *n = nlmsg_hdr(msg);
-	struct nlattr *tb[IFLA_MAX + 1];
-	struct nlattr *li[IFLA_INFO_MAX + 1];
-	struct nlattr *vi[IFLA_VLAN_MAX + 1];
-	int ret;
-	int idx;
-
-	if (!nlmsg_valid_hdr(n, sizeof(struct ifinfomsg)))
-		return -NLE_MSG_TOOSHORT;
-
-	ret = nlmsg_parse(n, sizeof(struct ifinfomsg), tb, IFLA_MAX,
-			  info_data_link_policy);
-	if (ret < 0)
-		return ret;
-
-	if (!tb[IFLA_LINK])
-		return -NLE_MISSING_ATTR;
-
-	/* parse subattributes linkinfo */
-	if (!tb[IFLA_LINKINFO])
-		return -NLE_MISSING_ATTR;
-
-	ret = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO],
-			       info_data_link_info_policy);
-	if (ret < 0)
-		return ret;
-
-	if (!li[IFLA_INFO_KIND])
-		return -NLE_MISSING_ATTR;
-
-	if (strcmp(nla_data(li[IFLA_INFO_KIND]), "vlan") != 0)
-		goto err;
-
-	/* parse subattributes info_data for vlan */
-	if (!li[IFLA_INFO_DATA])
-		return -NLE_MISSING_ATTR;
-
-	ret = nla_parse_nested(vi, IFLA_VLAN_MAX, li[IFLA_INFO_DATA],
-			       vlan_policy);
-	if (ret < 0)
-		return ret;
-
-	if (!vi[IFLA_VLAN_ID])
-		return -NLE_MISSING_ATTR;
-
-	/* get parent link name */
-	idx = *(int *)nla_data(tb[IFLA_LINK]);
-
-	if (!if_indextoname(idx, nl_arg->iface))
-		goto err;
-
-	/* get the corresponding vid */
-	nl_arg->vid = *(int *)nla_data(vi[IFLA_VLAN_ID]);
-
-err:
-	if (nl_arg->vid >= 0)
-		return NL_STOP;
-	else
-		return NL_OK;
-}
-
-/**
- * vlan_get_link - convert a VLAN interface into its parent one
- * @ifname: the interface to convert
- * @parent: buffer where the parent interface name will be written
- *  (minimum IF_NAMESIZE)
- *
- * Returns the vlan identifier on success or -1 on error
- */
-static int vlan_get_link(const char *ifname, char *parent)
-{
-	struct nl_sock *sock;
-	int ret;
-	struct ifinfomsg ifinfo = {
-		.ifi_family = AF_UNSPEC,
-		.ifi_index = if_nametoindex(ifname),
-	};
-	struct nl_cb *cb = NULL;
-	struct vlan_get_link_nl_arg arg = {
-		.iface = parent,
-		.vid = -1,
-	};
-
-	sock = nl_socket_alloc();
-	if (!sock)
-		goto err;
-
-	ret = nl_connect(sock, NETLINK_ROUTE);
-	if (ret < 0)
-		goto err;
-
-	ret = nl_send_simple(sock, RTM_GETLINK, NLM_F_REQUEST,
-			     &ifinfo, sizeof(ifinfo));
-	if (ret < 0)
-		goto err;
-
-	cb = nl_cb_alloc(NL_CB_DEFAULT);
-	if (!cb)
-		goto err;
-
-	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, vlan_get_link_parse, &arg);
-	ret = nl_recvmsgs(sock, cb);
-	if (ret < 0)
-		goto err;
-
-err:
-	if (cb)
-		nl_cb_put(cb);
-	if (sock)
-		nl_socket_free(sock);
-
-	return arg.vid;
-}
-
 int query_rtnl_link(int ifindex, nl_recvmsg_msg_cb_t func, void *arg)
 {
 	struct ifinfomsg rt_hdr = {
@@ -1025,25 +882,15 @@ int netlink_simple_request(struct nl_msg *msg)
 	return err;
 }
 
-int translate_mesh_iface(struct state *state)
-{
-	state->vid = vlan_get_link(state->arg_iface, state->mesh_iface);
-	if (state->vid < 0) {
-		/* if there is no iface then the argument must be the
-		 * mesh interface
-		 */
-		snprintf(state->mesh_iface, sizeof(state->mesh_iface), "%s",
-			 state->arg_iface);
-	}
-
-	return 0;
-}
-
 struct rtnl_link_iface_data {
 	uint8_t kind_found:1;
 	uint8_t master_found:1;
+	uint8_t link_found:1;
+	uint8_t vid_found:1;
 	char kind[IF_NAMESIZE];
 	unsigned int master;
+	unsigned int link;
+	uint16_t vid;
 };
 
 static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg)
@@ -1051,13 +898,19 @@ static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg)
 	static struct nla_policy link_policy[IFLA_MAX + 1] = {
 		[IFLA_LINKINFO] = { .type = NLA_NESTED },
 		[IFLA_MASTER] = { .type = NLA_U32 },
+		[IFLA_LINK] = { .type = NLA_U32 },
 	};
 	static struct nla_policy link_info_policy[IFLA_INFO_MAX + 1] = {
 		[IFLA_INFO_KIND] = { .type = NLA_STRING },
+		[IFLA_INFO_DATA] = { .type = NLA_NESTED },
+	};
+	static struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
+		[IFLA_VLAN_ID] = { .type = NLA_U16 },
 	};
 
 	struct rtnl_link_iface_data *link_data = arg;
 	struct nlattr *li[IFLA_INFO_MAX + 1];
+	struct nlattr *vi[IFLA_VLAN_MAX + 1];
 	struct nlmsghdr *n = nlmsg_hdr(msg);
 	struct nlattr *tb[IFLA_MAX + 1];
 	char *type;
@@ -1076,6 +929,11 @@ static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg)
 		link_data->master_found = true;
 	}
 
+	if (tb[IFLA_LINK]) {
+		link_data->link = nla_get_u32(tb[IFLA_LINK]);
+		link_data->link_found = true;
+	}
+
 	/* parse subattributes linkinfo */
 	if (!tb[IFLA_LINKINFO])
 		return NL_OK;
@@ -1093,6 +951,19 @@ static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg)
 		link_data->kind_found = true;
 	}
 
+	if (!li[IFLA_INFO_DATA])
+		return NL_OK;
+
+	ret = nla_parse_nested(vi, IFLA_VLAN_MAX, li[IFLA_INFO_DATA],
+			       vlan_policy);
+	if (ret < 0)
+		return NL_OK;
+
+	if (vi[IFLA_VLAN_ID]) {
+		link_data->vid = nla_get_u16(vi[IFLA_VLAN_ID]);
+		link_data->vid_found = true;
+	}
+
 	return NL_STOP;
 }
 
@@ -1109,6 +980,8 @@ static int query_rtnl_link_single(int mesh_ifindex,
 
 	link_data->kind_found = false;
 	link_data->master_found = false;
+	link_data->link_found = false;
+	link_data->vid_found = false;
 
 	sock = nl_socket_alloc();
 	if (!sock)
@@ -1138,7 +1011,47 @@ static int query_rtnl_link_single(int mesh_ifindex,
 	return 0;
 }
 
-int check_mesh_iface_netlink(struct state *state)
+int translate_mesh_iface(struct state *state)
+{
+	struct rtnl_link_iface_data link_data;
+	unsigned int arg_ifindex;
+
+	arg_ifindex = if_nametoindex(state->arg_iface);
+	if (arg_ifindex == 0)
+		goto fallback_meshif;
+
+	query_rtnl_link_single(arg_ifindex, &link_data);
+	if (!link_data.vid_found)
+		goto fallback_meshif;
+
+	if (!link_data.link_found)
+		goto fallback_meshif;
+
+	if (!link_data.kind_found)
+		goto fallback_meshif;
+
+	if (strcmp(link_data.kind, "vlan") != 0)
+		goto fallback_meshif;
+
+	if (!if_indextoname(link_data.link, state->mesh_iface))
+		goto fallback_meshif;
+
+	state->vid = link_data.vid;
+
+	return 0;
+
+fallback_meshif:
+	/* if there is no vid then the argument must be the
+	 * mesh interface
+	 */
+	snprintf(state->mesh_iface, sizeof(state->mesh_iface), "%s",
+		 state->arg_iface);
+	state->vid = -1;
+
+	return 0;
+}
+
+static int check_mesh_iface_netlink(struct state *state)
 {
 	struct rtnl_link_iface_data link_data;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [B.A.T.M.A.N.] [PATCH 3/3] batctl: Add netlink fallback for sysfs' iface_status
  2019-04-03 18:01 [B.A.T.M.A.N.] [PATCH 0/3] batctl: Add netlink support for sysfs-only functionality Sven Eckelmann
  2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Support checking of meshif without sysfs Sven Eckelmann
  2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 2/3] batctl: Reimplement VLAN translation using helper Sven Eckelmann
@ 2019-04-03 18:01 ` Sven Eckelmann
  2 siblings, 0 replies; 4+ messages in thread
From: Sven Eckelmann @ 2019-04-03 18:01 UTC (permalink / raw)
  To: b.a.t.m.a.n

The batman-adv kernel module can now be compiled without support for sysfs.
But the status of an interface in the list generated by `batctl interface`
can only get the status via the per hardif sysfs file iface_status. To
still have some information, fallback to BATADV_CMD_GET_HARDIF if the sysfs
file is not available.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 interface.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/interface.c b/interface.c
index 667a308..630dd91 100644
--- a/interface.c
+++ b/interface.c
@@ -24,6 +24,8 @@
 #include "sys.h"
 #include "functions.h"
 
+#define IFACE_STATUS_LEN 256
+
 static void interface_usage(void)
 {
 	fprintf(stderr, "Usage: batctl [options] interface [parameters] [add|del iface(s)]\n");
@@ -33,6 +35,92 @@ static void interface_usage(void)
 	fprintf(stderr, " \t -h print this help\n");
 }
 
+static int get_iface_status_netlink_parse(struct nl_msg *msg, void *arg)
+{
+
+	struct nlattr *attrs[NUM_BATADV_ATTR];
+	struct nlmsghdr *nlh = nlmsg_hdr(msg);
+	char *iface_status = arg;
+	struct genlmsghdr *ghdr;
+
+	if (!genlmsg_valid_hdr(nlh, 0))
+		return NL_OK;
+
+	ghdr = nlmsg_data(nlh);
+	if (ghdr->cmd != BATADV_CMD_GET_HARDIF)
+		return NL_OK;
+
+	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
+		      genlmsg_len(ghdr), batadv_netlink_policy))
+		return NL_OK;
+
+	if (attrs[BATADV_ATTR_ACTIVE])
+		strncpy(iface_status, "active\n", IFACE_STATUS_LEN);
+	else
+		strncpy(iface_status, "inactive\n", IFACE_STATUS_LEN);
+
+	iface_status[IFACE_STATUS_LEN - 1] = '\0';
+
+	return NL_STOP;
+}
+
+static char *get_iface_status_netlink(unsigned int meshif, unsigned int hardif,
+				      char *iface_status)
+{
+	struct nl_sock *sock;
+	struct nl_msg *msg;
+	int batadv_family;
+	struct nl_cb *cb;
+	int ret;
+
+	strncpy(iface_status, "<error reading status>\n", IFACE_STATUS_LEN);
+	iface_status[IFACE_STATUS_LEN - 1] = '\0';
+
+	sock = nl_socket_alloc();
+	if (!sock)
+		return iface_status;
+
+	ret = genl_connect(sock);
+	if (ret < 0)
+		goto err_free_sock;
+
+	batadv_family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
+	if (ret < 0)
+		goto err_free_sock;
+
+	cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (!cb)
+		goto err_free_sock;
+
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_iface_status_netlink_parse,
+		iface_status);
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		goto err_free_cb;
+
+	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, batadv_family,
+		    0, 0, BATADV_CMD_GET_HARDIF, 1);
+
+	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, meshif);
+	nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, hardif);
+
+	ret = nl_send_auto_complete(sock, msg);
+	if (ret < 0)
+		goto err_free_msg;
+
+	nl_recvmsgs(sock, cb);
+
+err_free_msg:
+	nlmsg_free(msg);
+err_free_cb:
+	nl_cb_put(cb);
+err_free_sock:
+	nl_socket_free(sock);
+
+	return iface_status;
+}
+
 static struct nla_policy link_policy[IFLA_MAX + 1] = {
 	[IFLA_IFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ },
 	[IFLA_MASTER] = { .type = NLA_U32 },
@@ -45,6 +133,7 @@ struct print_interfaces_rtnl_arg {
 static int print_interfaces_rtnl_parse(struct nl_msg *msg, void *arg)
 {
 	struct print_interfaces_rtnl_arg *print_arg = arg;
+	char iface_status[IFACE_STATUS_LEN];
 	struct nlattr *attrs[IFLA_MAX + 1];
 	char path_buff[PATH_BUFF_LEN];
 	struct ifinfomsg *ifm;
@@ -75,7 +164,8 @@ static int print_interfaces_rtnl_parse(struct nl_msg *msg, void *arg)
 	snprintf(path_buff, sizeof(path_buff), SYS_IFACE_STATUS_FMT, ifname);
 	ret = read_file("", path_buff, USE_READ_BUFF | SILENCE_ERRORS, 0, 0, 0);
 	if (ret != EXIT_SUCCESS)
-		status = "<error reading status>\n";
+		status = get_iface_status_netlink(master, ifm->ifi_index,
+						  iface_status);
 	else
 		status = line_ptr;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-04-03 18:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-03 18:01 [B.A.T.M.A.N.] [PATCH 0/3] batctl: Add netlink support for sysfs-only functionality Sven Eckelmann
2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Support checking of meshif without sysfs Sven Eckelmann
2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 2/3] batctl: Reimplement VLAN translation using helper Sven Eckelmann
2019-04-03 18:01 ` [B.A.T.M.A.N.] [PATCH 3/3] batctl: Add netlink fallback for sysfs' iface_status Sven Eckelmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).