@@ -103,11 +103,11 @@ static int bla_backbone_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_bla_backbone(char *mesh_iface, char *orig_iface,
+static int netlink_print_bla_backbone(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
- return netlink_print_common(mesh_iface, orig_iface, read_opts,
+ return netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval,
"Originator VID last seen (CRC )\n",
BATADV_CMD_GET_BLA_BACKBONE,
@@ -121,4 +121,5 @@ static struct debug_table_data batctl_debug_table_backbonetable = {
};
COMMAND_NAMED(DEBUGTABLE, backbonetable, "bbt", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_backbonetable, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_backbonetable, "");
@@ -108,11 +108,11 @@ static int bla_claim_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_bla_claim(char *mesh_iface, char *orig_iface,
+static int netlink_print_bla_claim(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
- return netlink_print_common(mesh_iface, orig_iface, read_opts,
+ return netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval,
"Client VID Originator [o] (CRC )\n",
BATADV_CMD_GET_BLA_CLAIM,
@@ -126,4 +126,5 @@ static struct debug_table_data batctl_debug_table_claimtable = {
};
COMMAND_NAMED(DEBUGTABLE, claimtable, "cl", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_claimtable, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_claimtable, "");
@@ -112,7 +112,7 @@ static int dat_cache_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_dat_cache(char *mesh_iface, char *orig_iface,
+static int netlink_print_dat_cache(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
@@ -120,13 +120,13 @@ static int netlink_print_dat_cache(char *mesh_iface, char *orig_iface,
int ret;
ret = asprintf(&header, "Distributed ARP Table (%s):\n%s\n",
- mesh_iface,
+ state->mesh_iface,
" IPv4 MAC VID last-seen");
if (ret < 0)
return ret;
- ret = netlink_print_common(mesh_iface, orig_iface, read_opts,
+ ret = netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval, header,
BATADV_CMD_GET_DAT_CACHE,
dat_cache_callback);
@@ -142,4 +142,5 @@ static struct debug_table_data batctl_debug_table_dat_cache = {
};
COMMAND_NAMED(DEBUGTABLE, dat_cache, "dc", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_dat_cache, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_dat_cache, "");
@@ -168,9 +168,8 @@ int handle_debug_table(struct state *state, int argc, char **argv)
}
if (debug_table->netlink_fn) {
- err = debug_table->netlink_fn(
- state->mesh_iface, orig_iface, read_opt, orig_timeout,
- watch_interval);
+ err = debug_table->netlink_fn(state , orig_iface, read_opt,
+ orig_timeout, watch_interval);
if (err != -EOPNOTSUPP)
return err;
}
@@ -39,7 +39,7 @@
struct debug_table_data {
const char *debugfs_name;
size_t header_lines;
- int (*netlink_fn)(char *mesh_iface, char *hard_iface, int read_opt,
+ int (*netlink_fn)(struct state *state, char *hard_iface, int read_opt,
float orig_timeout, float watch_interval);
unsigned int option_unicast_only:1;
unsigned int option_multicast_only:1;
@@ -126,7 +126,7 @@ static int gateways_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_gateways(char *mesh_iface, char *orig_iface,
+static int netlink_print_gateways(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
@@ -134,9 +134,9 @@ static int netlink_print_gateways(char *mesh_iface, char *orig_iface,
char *info_header;
int ifindex;
- ifindex = if_nametoindex(mesh_iface);
+ ifindex = if_nametoindex(state->mesh_iface);
if (!ifindex) {
- fprintf(stderr, "Interface %s is unknown\n", mesh_iface);
+ fprintf(stderr, "Interface %s is unknown\n", state->mesh_iface);
return -ENODEV;
}
@@ -156,7 +156,7 @@ static int netlink_print_gateways(char *mesh_iface, char *orig_iface,
if (!header)
return -EINVAL;
- return netlink_print_common(mesh_iface, orig_iface, read_opts,
+ return netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval,
header,
BATADV_CMD_GET_GATEWAYS,
@@ -170,4 +170,5 @@ static struct debug_table_data batctl_debug_table_gateways = {
};
COMMAND_NAMED(DEBUGTABLE, gateways, "gwl", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_gateways, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_gateways, "");
@@ -21,7 +21,7 @@
*/
-
+#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
@@ -32,6 +32,7 @@
#include "sys.h"
#include "debug.h"
#include "functions.h"
+#include "netlink.h"
char mesh_dfl_iface[] = "bat0";
char module_ver_path[] = "/sys/module/batman_adv/version";
@@ -180,8 +181,23 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
+ if (cmd->flags & COMMAND_FLAG_NETLINK) {
+ ret = netlink_create(&state);
+ if (ret < 0 && ret != -EOPNOTSUPP) {
+ /* TODO handle -EOPNOTSUPP as error when fallbacks were
+ * removed
+ */
+ fprintf(stderr,
+ "Error - failed to connect to batadv\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
ret = cmd->handler(&state, argc, argv);
+ if (cmd->flags & COMMAND_FLAG_NETLINK)
+ netlink_destroy(&state);
+
return ret;
err:
@@ -25,6 +25,10 @@
#include <stdint.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/genl/genl.h>
+#include <netlink/netlink.h>
+
#ifndef SOURCE_VERSION
#define SOURCE_VERSION "2018.4"
#endif
@@ -61,6 +65,7 @@ extern char module_ver_path[];
enum command_flags {
COMMAND_FLAG_MESH_IFACE = BIT(0),
+ COMMAND_FLAG_NETLINK = BIT(1),
};
enum command_type {
@@ -71,6 +76,10 @@ enum command_type {
struct state {
char *mesh_iface;
const struct command *cmd;
+
+ struct nl_sock *sock;
+ struct nl_cb *cb;
+ int batadv_family;
};
struct command {
@@ -104,7 +104,7 @@ static int mcast_flags_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_mcast_flags(char *mesh_iface, char *orig_iface,
+static int netlink_print_mcast_flags(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
@@ -115,9 +115,9 @@ static int netlink_print_mcast_flags(char *mesh_iface, char *orig_iface,
int ifindex;
int ret;
- ifindex = if_nametoindex(mesh_iface);
+ ifindex = if_nametoindex(state->mesh_iface);
if (!ifindex) {
- fprintf(stderr, "Interface %s is unknown\n", mesh_iface);
+ fprintf(stderr, "Interface %s is unknown\n", state->mesh_iface);
return -ENODEV;
}
@@ -159,7 +159,7 @@ static int netlink_print_mcast_flags(char *mesh_iface, char *orig_iface,
if (ret < 0)
return ret;
- ret = netlink_print_common(mesh_iface, orig_iface, read_opts,
+ ret = netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval, header,
BATADV_CMD_GET_MCAST_FLAGS,
mcast_flags_callback);
@@ -175,4 +175,5 @@ static struct debug_table_data batctl_debug_table_mcast_flags = {
};
COMMAND_NAMED(DEBUGTABLE, mcast_flags, "mf", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_mcast_flags, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_mcast_flags, "");
@@ -119,11 +119,11 @@ static int neighbors_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_neighbors(char *mesh_iface, char *orig_iface,
+static int netlink_print_neighbors(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
- return netlink_print_common(mesh_iface, orig_iface, read_opts,
+ return netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval,
"IF Neighbor last-seen\n",
BATADV_CMD_GET_NEIGHBORS,
@@ -137,4 +137,5 @@ static struct debug_table_data batctl_debug_table_neighbors = {
};
COMMAND_NAMED(DEBUGTABLE, neighbors, "n", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_neighbors, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_neighbors, "");
@@ -109,6 +109,59 @@ struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
[BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 },
};
+int netlink_create(struct state *state)
+{
+ int ret;
+
+ state->sock = NULL;
+ state->cb = NULL;
+ state->batadv_family = 0;
+
+ state->sock = nl_socket_alloc();
+ if (!state->sock)
+ return -ENOMEM;
+
+ ret = genl_connect(state->sock);
+ if (ret < 0)
+ goto err_free_sock;
+
+ state->batadv_family = genl_ctrl_resolve(state->sock, BATADV_NL_NAME);
+ if (state->batadv_family < 0) {
+ ret = -EOPNOTSUPP;
+ goto err_free_sock;
+ }
+
+ state->cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!state->cb) {
+ ret = -ENOMEM;
+ goto err_free_family;
+ }
+
+ return 0;
+
+err_free_family:
+ state->batadv_family = 0;
+
+err_free_sock:
+ nl_socket_free(state->sock);
+ state->sock = NULL;
+
+ return ret;
+}
+
+void netlink_destroy(struct state *state)
+{
+ if (state->cb) {
+ nl_cb_put(state->cb);
+ state->cb = NULL;
+ }
+
+ if (state->sock) {
+ nl_socket_free(state->sock);
+ state->sock = NULL;
+ }
+}
+
int last_err;
char algo_name_buf[256] = "";
int64_t mcast_flags = -EOPNOTSUPP;
@@ -456,7 +509,7 @@ int netlink_print_routing_algos(void)
return last_err;
}
-int netlink_print_common(char *mesh_iface, char *orig_iface, int read_opt,
+int netlink_print_common(struct state *state, char *orig_iface, int read_opt,
float orig_timeout, float watch_interval,
const char *header, uint8_t nl_cmd,
nl_recvmsg_msg_cb_t callback)
@@ -469,29 +522,19 @@ int netlink_print_common(char *mesh_iface, char *orig_iface, int read_opt,
.callback = callback,
};
int hardifindex = 0;
- struct nl_sock *sock;
struct nl_msg *msg;
- struct nl_cb *cb;
int ifindex;
- int family;
- sock = nl_socket_alloc();
- if (!sock)
- return -ENOMEM;
-
- genl_connect(sock);
-
- family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
- if (family < 0) {
+ if (!state->sock) {
last_err = -EOPNOTSUPP;
- goto err_free_sock;
+ return last_err;
}
- ifindex = if_nametoindex(mesh_iface);
+ ifindex = if_nametoindex(state->mesh_iface);
if (!ifindex) {
- fprintf(stderr, "Interface %s is unknown\n", mesh_iface);
+ fprintf(stderr, "Interface %s is unknown\n", state->mesh_iface);
last_err = -ENODEV;
- goto err_free_sock;
+ return last_err;
}
if (orig_iface) {
@@ -500,21 +543,15 @@ int netlink_print_common(char *mesh_iface, char *orig_iface, int read_opt,
fprintf(stderr, "Interface %s is unknown\n",
orig_iface);
last_err = -ENODEV;
- goto err_free_sock;
+ return last_err;
}
}
- cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (!cb) {
- last_err = -ENOMEM;
- goto err_free_sock;
- }
-
bat_hosts_init(read_opt);
- 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);
+ nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, netlink_print_common_cb, &opts);
+ nl_cb_set(state->cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
+ nl_cb_err(state->cb, NL_CB_CUSTOM, print_error, NULL);
do {
if (read_opt & CLR_CONT_READ)
@@ -530,20 +567,20 @@ int netlink_print_common(char *mesh_iface, char *orig_iface, int read_opt,
if (!msg)
continue;
- genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0,
- NLM_F_DUMP, nl_cmd, 1);
+ genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, state->batadv_family,
+ 0, NLM_F_DUMP, nl_cmd, 1);
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
if (hardifindex)
nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
hardifindex);
- nl_send_auto_complete(sock, msg);
+ nl_send_auto_complete(state->sock, msg);
nlmsg_free(msg);
last_err = 0;
- nl_recvmsgs(sock, cb);
+ nl_recvmsgs(state->sock, state->cb);
/* the header should still be printed when no entry was received */
if (!last_err)
@@ -556,9 +593,6 @@ int netlink_print_common(char *mesh_iface, char *orig_iface, int read_opt,
bat_hosts_free();
-err_free_sock:
- nl_socket_free(sock);
-
return last_err;
}
@@ -27,6 +27,8 @@
#include <netlink/genl/ctrl.h>
#include <stdint.h>
+struct state;
+
struct print_opts {
int read_opt;
float orig_timeout;
@@ -39,6 +41,9 @@ struct print_opts {
struct ether_addr;
+int netlink_create(struct state *state);
+void netlink_destroy(struct state *state);
+
int netlink_print_routing_algos(void);
char *netlink_get_info(int ifindex, uint8_t nl_cmd, const char *header);
@@ -52,7 +57,7 @@ extern struct nla_policy batadv_netlink_policy[];
int missing_mandatory_attrs(struct nlattr *attrs[], const int mandatory[],
int num);
-int netlink_print_common(char *mesh_iface, char *orig_iface, int read_opt,
+int netlink_print_common(struct state *state, char *orig_iface, int read_opt,
float orig_timeout, float watch_interval,
const char *header, uint8_t nl_cmd,
nl_recvmsg_msg_cb_t callback);
@@ -177,7 +177,7 @@ static int originators_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_originators(char *mesh_iface, char *orig_iface,
+static int netlink_print_originators(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
@@ -185,9 +185,9 @@ static int netlink_print_originators(char *mesh_iface, char *orig_iface,
char *info_header;
int ifindex;
- ifindex = if_nametoindex(mesh_iface);
+ ifindex = if_nametoindex(state->mesh_iface);
if (!ifindex) {
- fprintf(stderr, "Interface %s is unknown\n", mesh_iface);
+ fprintf(stderr, "Interface %s is unknown\n", state->mesh_iface);
return -ENODEV;
}
@@ -207,7 +207,7 @@ static int netlink_print_originators(char *mesh_iface, char *orig_iface,
if (!header)
return -EINVAL;
- return netlink_print_common(mesh_iface, orig_iface, read_opts,
+ return netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval, header,
BATADV_CMD_GET_ORIGINATORS,
originators_callback);
@@ -222,4 +222,5 @@ static struct debug_table_data batctl_debug_table_originators = {
};
COMMAND_NAMED(DEBUGTABLE, originators, "o", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_originators, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_originators, "");
@@ -136,11 +136,11 @@ static int transglobal_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_transglobal(char *mesh_iface, char *orig_iface,
+static int netlink_print_transglobal(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
- return netlink_print_common(mesh_iface, orig_iface, read_opts,
+ return netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval,
" Client VID Flags Last ttvn Via ttvn (CRC )\n",
BATADV_CMD_GET_TRANSTABLE_GLOBAL,
@@ -156,4 +156,5 @@ static struct debug_table_data batctl_debug_table_transglobal = {
};
COMMAND_NAMED(DEBUGTABLE, transglobal, "tg", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_transglobal, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_transglobal, "");
@@ -132,11 +132,11 @@ static int translocal_callback(struct nl_msg *msg, void *arg)
return NL_OK;
}
-static int netlink_print_translocal(char *mesh_iface, char *orig_iface,
+static int netlink_print_translocal(struct state *state, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
- return netlink_print_common(mesh_iface, orig_iface, read_opts,
+ return netlink_print_common(state, orig_iface, read_opts,
orig_timeout, watch_interval,
"Client VID Flags Last seen (CRC )\n",
BATADV_CMD_GET_TRANSTABLE_LOCAL,
@@ -152,4 +152,5 @@ static struct debug_table_data batctl_debug_table_translocal = {
};
COMMAND_NAMED(DEBUGTABLE, translocal, "tl", handle_debug_table,
- COMMAND_FLAG_MESH_IFACE, &batctl_debug_table_translocal, "");
+ COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
+ &batctl_debug_table_translocal, "");