[3/6] batctl: interface: List using shared genl socket

Message ID 20210510194945.103735-4-sven@narfation.org (mailing list archive)
State Accepted, archived
Delegated to: Simon Wunderlich
Headers
Series batctl: Use shared batadv genl socket for requests |

Commit Message

Sven Eckelmann May 10, 2021, 7:49 p.m. UTC
  The interface subcommand doesn't need to allocate a new netlink socket to
query the state of a single interface. But it can also not use the socket
which is automatically pre-configured by COMMAND_FLAG_NETLINK because the
(main sub)command might also be started for interfaces which might not
exist yet.

Instead use the shared functions to pre-allocate the necessary state
information when calling the "list" sub-subcommand.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 interface.c | 77 +++++++++++++++++++++--------------------------------
 1 file changed, 31 insertions(+), 46 deletions(-)
  

Patch

diff --git a/interface.c b/interface.c
index cf9c0c3..a96a328 100644
--- a/interface.c
+++ b/interface.c
@@ -62,65 +62,46 @@  static int get_iface_status_netlink_parse(struct nl_msg *msg, void *arg)
 
 	iface_status[IFACE_STATUS_LEN - 1] = '\0';
 
-	return NL_STOP;
+	return NL_OK;
 }
 
-static char *get_iface_status_netlink(unsigned int meshif, unsigned int hardif,
+static char *get_iface_status_netlink(struct state *state, unsigned int hardif,
 				      char *iface_status)
 {
 	char *ret_status = NULL;
-	struct nl_sock *sock;
 	struct nl_msg *msg;
-	int batadv_family;
-	struct nl_cb *cb;
 	int ret;
 
 	iface_status[0] = '\0';
 
-	sock = nl_socket_alloc();
-	if (!sock)
-		return NULL;
-
-	ret = genl_connect(sock);
-	if (ret < 0)
-		goto err_free_sock;
-
-	batadv_family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
-	if (batadv_family < 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,
+	nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, get_iface_status_netlink_parse,
 		iface_status);
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto err_free_cb;
+		return NULL;
 
-	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, batadv_family,
+	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, state->batadv_family,
 		    0, 0, BATADV_CMD_GET_HARDIF, 1);
 
-	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, meshif);
+	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, state->mesh_ifindex);
 	nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, hardif);
 
-	ret = nl_send_auto_complete(sock, msg);
+	ret = nl_send_auto_complete(state->sock, msg);
+	if (ret < 0)
+		goto err_free_msg;
+
+	ret = nl_recvmsgs(state->sock, state->cb);
 	if (ret < 0)
 		goto err_free_msg;
 
-	nl_recvmsgs(sock, cb);
+	nl_wait_for_ack(state->sock);
 
 	if (strlen(iface_status) > 0)
 		ret_status = iface_status;
 
 err_free_msg:
 	nlmsg_free(msg);
-err_free_cb:
-	nl_cb_put(cb);
-err_free_sock:
-	nl_socket_free(sock);
 
 	return ret_status;
 }
@@ -130,20 +111,16 @@  static struct nla_policy link_policy[IFLA_MAX + 1] = {
 	[IFLA_MASTER] = { .type = NLA_U32 },
 };
 
-struct print_interfaces_rtnl_arg {
-	int ifindex;
-};
-
 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];
+	struct state *state = arg;
 	struct ifinfomsg *ifm;
+	unsigned int master;
 	char *ifname;
 	int ret;
 	const char *status;
-	int master;
 
 	ifm = nlmsg_data(nlmsg_hdr(msg));
 	ret = nlmsg_parse(nlmsg_hdr(msg), sizeof(*ifm), attrs, IFLA_MAX,
@@ -161,10 +138,10 @@  static int print_interfaces_rtnl_parse(struct nl_msg *msg, void *arg)
 	master = nla_get_u32(attrs[IFLA_MASTER]);
 
 	/* required on older kernels which don't prefilter the results */
-	if (master != print_arg->ifindex)
+	if (master != state->mesh_ifindex)
 		goto err;
 
-	status = get_iface_status_netlink(master, ifm->ifi_index, iface_status);
+	status = get_iface_status_netlink(state, ifm->ifi_index, iface_status);
 	if (!status)
 		status = "<error reading status>\n";
 
@@ -174,21 +151,29 @@  static int print_interfaces_rtnl_parse(struct nl_msg *msg, void *arg)
 	return NL_OK;
 }
 
-static int print_interfaces(char *mesh_iface)
+static int print_interfaces(struct state *state)
 {
-	struct print_interfaces_rtnl_arg print_arg;
+	int ret;
 
 	if (!file_exists(module_ver_path)) {
 		fprintf(stderr, "Error - batman-adv module has not been loaded\n");
 		return EXIT_FAILURE;
 	}
 
-	print_arg.ifindex = if_nametoindex(mesh_iface);
-	if (!print_arg.ifindex)
+	/* duplicated code here from the main() because interface doesn't always
+	 * need COMMAND_FLAG_MESH_IFACE and COMMAND_FLAG_NETLINK
+	 */
+	if (check_mesh_iface(state))
 		return EXIT_FAILURE;
 
-	query_rtnl_link(print_arg.ifindex, print_interfaces_rtnl_parse,
-			&print_arg);
+	ret = netlink_create(state);
+	if (ret < 0)
+		return EXIT_FAILURE;
+
+	query_rtnl_link(state->mesh_ifindex, print_interfaces_rtnl_parse,
+			state);
+
+	netlink_destroy(state);
 
 	return EXIT_SUCCESS;
 }
@@ -452,7 +437,7 @@  static int interface(struct state *state, int argc, char **argv)
 	rest_argv = &argv[optind];
 
 	if (rest_argc == 0)
-		return print_interfaces(state->mesh_iface);
+		return print_interfaces(state);
 
 	check_root_or_die("batctl interface");