From patchwork Sun Oct 21 22:55:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 17549 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 802E7831A4; Mon, 22 Oct 2018 00:57:56 +0200 (CEST) Authentication-Results: open-mesh.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=narfation.org header.i=@narfation.org header.b="AwTNGRYh"; dkim-atps=neutral Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2001:4d88:2000:7::2; helo=v3-1039.vlinux.de; envelope-from=sven@narfation.org; receiver= Received: from v3-1039.vlinux.de (narfation.org [IPv6:2001:4d88:2000:7::2]) by open-mesh.org (Postfix) with ESMTPS id EA88C83096 for ; Mon, 22 Oct 2018 00:56:19 +0200 (CEST) Received: from sven-desktop.home.narfation.org (p200300C593D704FD0000000000008096.dip0.t-ipconnect.de [IPv6:2003:c5:93d7:4fd::8096]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id 6F7A01100D5; Mon, 22 Oct 2018 00:56:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=narfation.org; s=20121; t=1540162578; bh=F2sORCziFezhGSHoAHiHvx37EwBEV0IwouqjXzb9mko=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AwTNGRYh21OA3nITlRvkBF1VodDu1yk4DNTqWy0vcKd5RiAX0U1WIxGp4gF3sxqDw +anHRtYokHg6atmXSZQUZlmmG1CKHRup6SkFIlKEPlc1rpJa0bIPPoQ8BWFidquzj6 i7qcDQ4Pbwil6nKsEP0DJHIJ93r/5dtHjFkhsoMU= From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Mon, 22 Oct 2018 00:55:23 +0200 Message-Id: <20181021225524.8155-38-sven@narfation.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181021225524.8155-1-sven@narfation.org> References: <20181021225524.8155-1-sven@narfation.org> MIME-Version: 1.0 Subject: [B.A.T.M.A.N.] [PATCH 37/38] batctl: Use external netlink socket for debug tables X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" The netlink socket is used by the debug table functionality to retrieve the tables. The initialization can be centralized and moved to the main function (controlled by a flag) to share it between the other commands. Since more commands will use netlink in the future, this flag can reduce the implementation effort significantly. Signed-off-by: Sven Eckelmann --- backbonetable.c | 7 ++-- claimtable.c | 7 ++-- dat_cache.c | 9 +++-- debug.c | 5 +-- debug.h | 2 +- gateways.c | 11 +++--- main.c | 18 ++++++++- main.h | 9 +++++ mcast_flags.c | 11 +++--- neighbors.c | 7 ++-- netlink.c | 100 ++++++++++++++++++++++++++++++++---------------- netlink.h | 7 +++- originators.c | 11 +++--- transglobal.c | 7 ++-- translocal.c | 7 ++-- 15 files changed, 145 insertions(+), 73 deletions(-) diff --git a/backbonetable.c b/backbonetable.c index 2512142..d799d8c 100644 --- a/backbonetable.c +++ b/backbonetable.c @@ -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, ""); diff --git a/claimtable.c b/claimtable.c index ca79fc3..989879f 100644 --- a/claimtable.c +++ b/claimtable.c @@ -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, ""); diff --git a/dat_cache.c b/dat_cache.c index 39f8f18..1e1f028 100644 --- a/dat_cache.c +++ b/dat_cache.c @@ -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, ""); diff --git a/debug.c b/debug.c index 17dde92..b908e00 100644 --- a/debug.c +++ b/debug.c @@ -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; } diff --git a/debug.h b/debug.h index 79c489a..525a46b 100644 --- a/debug.h +++ b/debug.h @@ -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; diff --git a/gateways.c b/gateways.c index d027a32..b0a36c7 100644 --- a/gateways.c +++ b/gateways.c @@ -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, ""); diff --git a/main.c b/main.c index 9fc6bfb..ab7da45 100644 --- a/main.c +++ b/main.c @@ -21,7 +21,7 @@ */ - +#include #include #include #include @@ -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: diff --git a/main.h b/main.h index 2656dcf..4a48f61 100644 --- a/main.h +++ b/main.h @@ -25,6 +25,10 @@ #include +#include +#include +#include + #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 { diff --git a/mcast_flags.c b/mcast_flags.c index 9a1b819..bcbe17c 100644 --- a/mcast_flags.c +++ b/mcast_flags.c @@ -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, ""); diff --git a/neighbors.c b/neighbors.c index c7a0f45..cd04be8 100644 --- a/neighbors.c +++ b/neighbors.c @@ -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, ""); diff --git a/netlink.c b/netlink.c index 26ae27d..8268037 100644 --- a/netlink.c +++ b/netlink.c @@ -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; } diff --git a/netlink.h b/netlink.h index 0b21ac1..2526b07 100644 --- a/netlink.h +++ b/netlink.h @@ -27,6 +27,8 @@ #include #include +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); diff --git a/originators.c b/originators.c index fd2aa66..a9c0606 100644 --- a/originators.c +++ b/originators.c @@ -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, ""); diff --git a/transglobal.c b/transglobal.c index f67682a..da2d687 100644 --- a/transglobal.c +++ b/transglobal.c @@ -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, ""); diff --git a/translocal.c b/translocal.c index 8b4cd59..a03b797 100644 --- a/translocal.c +++ b/translocal.c @@ -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, "");