[v12,11/11] batctl: Use debugfs fallback when netlink not supported

Message ID 1468958992-2972-1-git-send-email-sven@narfation.org (mailing list archive)
State Accepted, archived
Commit 5401c71adfad66113026e5cc549f2595b5329225
Delegated to: Marek Lindner
Headers

Commit Message

Sven Eckelmann July 19, 2016, 8:09 p.m. UTC
  The batman-adv release v2016.2 already has the batadv netlink family . Thus
the fallback to debugfs not only has to be triggered when the the netlink
family doesn't exist but also when the cmd returns a -EOPNOTSUPP. This
still has the problem that the header is generated via a different command
then the actual table entries. Falling back to debugfs would cause a second
header entry for the table.

The header print functionality is therefore refactored to only gather the
data for the header and print the actual header either with the first
received entry or when the CMD finished without any result.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
v12:
 - also use debugfs for originators/gwl when get_mesh_info is not supported
---
 functions.h |   1 -
 netlink.c   | 150 ++++++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 101 insertions(+), 50 deletions(-)
  

Comments

Marek Lindner July 22, 2016, 9:11 a.m. UTC | #1
On Tuesday, July 19, 2016 22:09:52 Sven Eckelmann wrote:
> The batman-adv release v2016.2 already has the batadv netlink family . Thus
> the fallback to debugfs not only has to be triggered when the the netlink
> family doesn't exist but also when the cmd returns a -EOPNOTSUPP. This
> still has the problem that the header is generated via a different command
> then the actual table entries. Falling back to debugfs would cause a second
> header entry for the table.
> 
> The header print functionality is therefore refactored to only gather the
> data for the header and print the actual header either with the first
> received entry or when the CMD finished without any result.
> 
> Signed-off-by: Sven Eckelmann <sven@narfation.org>
> ---
> v12:
>  - also use debugfs for originators/gwl when get_mesh_info is not supported
> ---
>  functions.h |   1 -
>  netlink.c   | 150
> ++++++++++++++++++++++++++++++++++++++++-------------------- 2 files
> changed, 101 insertions(+), 50 deletions(-)

Applied in revision 5401c71.

Thanks,
Marek
  

Patch

diff --git a/functions.h b/functions.h
index 1f311ca..e24dea0 100644
--- a/functions.h
+++ b/functions.h
@@ -61,7 +61,6 @@  enum {
 	SKIP_HEADER = 0x100,
 	UNICAST_ONLY = 0x200,
 	MULTICAST_ONLY = 0x400,
-	PARSE_ONLY = 0x800,
 };
 
 #endif
diff --git a/netlink.c b/netlink.c
index 423fc9b..e8e94b2 100644
--- a/netlink.c
+++ b/netlink.c
@@ -54,6 +54,9 @@  struct print_opts {
 	int read_opt;
 	float orig_timeout;
 	float watch_interval;
+	nl_recvmsg_msg_cb_t callback;
+	char *remaining_header;
+	const char *static_header;
 	uint8_t nl_cmd;
 };
 
@@ -139,7 +142,7 @@  static int print_error(struct sockaddr_nl *nla __unused,
 		fprintf(stderr, "Error received: %s\n",
 			strerror(-nlerr->error));
 
-	last_err = -nlerr->error;
+	last_err = nlerr->error;
 
 	return NL_STOP;
 }
@@ -182,6 +185,7 @@  static int info_callback(struct nl_msg *msg, void *arg)
 	uint8_t ttvn = 0;
 	uint16_t bla_group_id = 0;
 	const char *algo_name;
+	const char *extra_header;
 	int ret;
 
 	if (!genlmsg_valid_hdr(nlh, 0)) {
@@ -230,54 +234,64 @@  static int info_callback(struct nl_msg *msg, void *arg)
 		if (attrs[BATADV_ATTR_BLA_CRC])
 			bla_group_id = nla_get_u16(attrs[BATADV_ATTR_BLA_CRC]);
 
-		if (!(opts->read_opt & PARSE_ONLY)) {
-			switch (opts->nl_cmd) {
-			case BATADV_CMD_GET_TRANSTABLE_LOCAL:
-				ret = asprintf(&extra_info, ", TTVN: %u", ttvn);
-				if (ret < 0)
-					extra_info = NULL;
-				break;
-			case BATADV_CMD_GET_BLA_BACKBONE:
-			case BATADV_CMD_GET_BLA_CLAIM:
-				ret = asprintf(&extra_info, ", group id: 0x%04x",
-					       bla_group_id);
-				if (ret < 0)
-					extra_info = NULL;
-				break;
-			default:
-				extra_info = strdup("");
-				break;
-			}
-
-			printf("[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%02x:%02x:%02x:%02x:%02x:%02x (%s/%02x:%02x:%02x:%02x:%02x:%02x %s)%s]\n",
+		switch (opts->nl_cmd) {
+		case BATADV_CMD_GET_TRANSTABLE_LOCAL:
+			ret = asprintf(&extra_info, ", TTVN: %u", ttvn);
+			if (ret < 0)
+				extra_info = NULL;
+			break;
+		case BATADV_CMD_GET_BLA_BACKBONE:
+		case BATADV_CMD_GET_BLA_CLAIM:
+			ret = asprintf(&extra_info, ", group id: 0x%04x",
+				       bla_group_id);
+			if (ret < 0)
+				extra_info = NULL;
+			break;
+		default:
+			extra_info = strdup("");
+			break;
+		}
+
+		if (opts->static_header)
+			extra_header = opts->static_header;
+		else
+			extra_header = "";
+
+		ret = asprintf(&opts->remaining_header,
+			       "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%02x:%02x:%02x:%02x:%02x:%02x (%s/%02x:%02x:%02x:%02x:%02x:%02x %s)%s]\n%s",
 			       version, primary_if,
 			       primary_mac[0], primary_mac[1], primary_mac[2],
 			       primary_mac[3], primary_mac[4], primary_mac[5],
 			       mesh_name,
 			       mesh_mac[0], mesh_mac[1], mesh_mac[2],
 			       mesh_mac[3], mesh_mac[4], mesh_mac[5],
-			       algo_name, extra_info);
+			       algo_name, extra_info, extra_header);
+		if (ret < 0)
+			opts->remaining_header = NULL;
 
-			if (extra_info)
-				free(extra_info);
-		}
+		if (extra_info)
+			free(extra_info);
 	} else {
-		if (!(opts->read_opt & PARSE_ONLY))
-			printf("BATMAN mesh %s disabled\n", mesh_name);
+		ret = asprintf(&opts->remaining_header,
+			       "BATMAN mesh %s disabled\n", mesh_name);
+		if (ret < 0)
+			opts->remaining_header = NULL;
 	}
 
 	return NL_STOP;
 }
 
-static void netlink_print_info(int ifindex, uint8_t nl_cmd, int read_opt)
+static char *netlink_get_info(int ifindex, uint8_t nl_cmd, const char *header)
 {
 	struct nl_sock *sock;
 	struct nl_msg *msg;
 	struct nl_cb *cb;
 	int family;
 	struct print_opts opts = {
-		.read_opt = read_opt,
+		.read_opt = 0,
 		.nl_cmd = nl_cmd,
+		.remaining_header = NULL,
+		.static_header = header,
 	};
 
 	sock = nl_socket_alloc();
@@ -285,7 +299,7 @@  static void netlink_print_info(int ifindex, uint8_t nl_cmd, int read_opt)
 
 	family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
 	if (family < 0)
-		return;
+		return NULL;
 
 	msg = nlmsg_alloc();
 	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, 0,
@@ -304,6 +318,27 @@  static void netlink_print_info(int ifindex, uint8_t nl_cmd, int read_opt)
 	nl_recvmsgs(sock, cb);
 
 	nl_socket_free(sock);
+
+	return opts.remaining_header;
+}
+
+static void netlink_print_remaining_header(struct print_opts *opts)
+{
+	if (!opts->remaining_header)
+		return;
+
+	fputs(opts->remaining_header, stdout);
+	free(opts->remaining_header);
+	opts->remaining_header = NULL;
+}
+
+static int netlink_print_common_cb(struct nl_msg *msg, void *arg)
+{
+	struct print_opts *opts = arg;
+
+	netlink_print_remaining_header(opts);
+
+	return opts->callback(msg, arg);
 }
 
 static const int routing_algos_mandatory[] = {
@@ -352,6 +387,9 @@  int netlink_print_routing_algos(void)
 	struct nl_msg *msg;
 	struct nl_cb *cb;
 	int family;
+	struct print_opts opts = {
+		.callback = routing_algos_callback,
+	};
 
 	sock = nl_socket_alloc();
 	genl_connect(sock);
@@ -368,19 +406,21 @@  int netlink_print_routing_algos(void)
 
 	nlmsg_free(msg);
 
+	opts.remaining_header = strdup("Available routing algorithms:\n");
+
 	cb = nl_cb_alloc(NL_CB_DEFAULT);
-	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, routing_algos_callback,
-		  NULL);
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, netlink_print_common_cb,
+		  &opts);
 	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
 	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
 
-	printf("Available routing algorithms:\n");
-
 	nl_recvmsgs(sock, cb);
-
 	nl_socket_free(sock);
 
-	return 0;
+	if (!last_err)
+		netlink_print_remaining_header(&opts);
+
+	return last_err;
 }
 
 static const int originators_mandatory[] = {
@@ -1040,7 +1080,9 @@  static int netlink_print_common(char *mesh_iface, char *orig_iface,
 	struct print_opts opts = {
 		.read_opt = read_opt,
 		.orig_timeout = orig_timeout,
-		.watch_interval = watch_interval
+		.watch_interval = watch_interval,
+		.remaining_header = NULL,
+		.callback = callback,
 	};
 	int hardifindex = 0;
 	struct nl_sock *sock;
@@ -1074,7 +1116,7 @@  static int netlink_print_common(char *mesh_iface, char *orig_iface,
 	bat_hosts_init(read_opt);
 
 	cb = nl_cb_alloc(NL_CB_DEFAULT);
-	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, &opts);
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, netlink_print_common_cb, &opts);
 	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
 	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
 
@@ -1083,11 +1125,10 @@  static int netlink_print_common(char *mesh_iface, char *orig_iface,
 			/* clear screen, set cursor back to 0,0 */
 			printf("\033[2J\033[0;0f");
 
-		if (!(read_opt & SKIP_HEADER)) {
-			netlink_print_info(ifindex, nl_cmd, 0);
-			if (header)
-				printf("%s", header);
-		}
+		if (!(read_opt & SKIP_HEADER))
+			opts.remaining_header = netlink_get_info(ifindex,
+								 nl_cmd,
+								 header);
 
 		msg = nlmsg_alloc();
 		genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0,
@@ -1104,6 +1145,11 @@  static int netlink_print_common(char *mesh_iface, char *orig_iface,
 
 		last_err = 0;
 		nl_recvmsgs(sock, cb);
+
+		/* the header should still be printed when no entry was received */
+		if (!last_err)
+			netlink_print_remaining_header(&opts);
+
 		if (!last_err && read_opt & (CONT_READ|CLR_CONT_READ))
 			usleep(1000000 * watch_interval);
 
@@ -1120,7 +1166,8 @@  int netlink_print_originators(char *mesh_iface, char *orig_iface,
 			      int read_opts, float orig_timeout,
 			      float watch_interval)
 {
-	char *header;
+	char *header = NULL;
+	char *info_header;
 	int ifindex;
 
 	ifindex = if_nametoindex(mesh_iface);
@@ -1129,10 +1176,12 @@  int netlink_print_originators(char *mesh_iface, char *orig_iface,
 		return -ENODEV;
 	}
 
-	netlink_print_info(ifindex, BATADV_CMD_GET_ORIGINATORS, PARSE_ONLY);
+	/* only parse routing algorithm name */
+	info_header = netlink_get_info(ifindex, BATADV_CMD_GET_ORIGINATORS, NULL);
+	free(info_header);
 
 	if (strlen(algo_name_buf) == 0)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	if (!strcmp("BATMAN_IV", algo_name_buf))
 		header = "   Originator        last-seen (#/255) Nexthop           [outgoingIF]\n";
@@ -1184,7 +1233,8 @@  int netlink_print_translocal(char *mesh_iface, char *orig_iface, int read_opts,
 int netlink_print_gateways(char *mesh_iface, char *orig_iface, int read_opts,
 			   float orig_timeout,
 			   float watch_interval)
-{	char *header;
+{	char *header = NULL;
+	char *info_header;
 	int ifindex;
 
 	ifindex = if_nametoindex(mesh_iface);
@@ -1193,10 +1243,12 @@  int netlink_print_gateways(char *mesh_iface, char *orig_iface, int read_opts,
 		return -ENODEV;
 	}
 
-	netlink_print_info(ifindex, BATADV_CMD_GET_ORIGINATORS, PARSE_ONLY);
+	/* only parse routing algorithm name */
+	info_header = netlink_get_info(ifindex, BATADV_CMD_GET_ORIGINATORS, NULL);
+	free(info_header);
 
 	if (strlen(algo_name_buf) == 0)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	if (!strcmp("BATMAN_IV", algo_name_buf))
 		header = "  Router            ( TQ) Next Hop          [outgoingIf]  Bandwidth\n";