From patchwork Fri May 7 17:14:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Sarmanow X-Patchwork-Id: 18289 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from diktynna.open-mesh.org (localhost [IPv6:::1]) by diktynna.open-mesh.org (Postfix) with ESMTP id 8545F81A3A; Fri, 7 May 2021 19:22:47 +0200 (CEST) Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by diktynna.open-mesh.org (Postfix) with ESMTPS id 9B60C8078B for ; Fri, 7 May 2021 19:22:43 +0200 (CEST) Received: by mail-wm1-x32a.google.com with SMTP id g65so5672544wmg.2 for ; Fri, 07 May 2021 10:22:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=QuNNpm/02GWBjqtz+O16xdRwcWjMLRAmXRrxMGHa9ns=; b=DNYXZbwdWCxDyEzKk879tJk0DjcHC1tNj22Ch9NMBo6qU0ioFsJDKgNOxsn1ZWggSj ydiXrcTRwwJabQb7ae4tT7Osm9CRYdbEt/+W+vLJZQBX7ia96XP60OI6FGo8xeKBaBoQ whrgIBK68U7D+ItpHhqDH21hwX3ZjbRzAseUOGsAf4QXMSKx/cY3hFB+krkp1TnAN1D4 xNgNZSjPrJ230cpxYsFwRt8radi+p4f/I5I3wd9WVs+z7tQ7WE1omBoQGV009lGmEleo heMCq+cwh39TbmWAd0R8raxgjk2hQmalZf61aC6xyd4xw5OxOZFnP7g8HPGR0OFycitf S39g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=QuNNpm/02GWBjqtz+O16xdRwcWjMLRAmXRrxMGHa9ns=; b=EIE5cxRR69qNSaVHHRDs6p3QsEv7Y8INBKNCkHHL5Lhclan7i7oFZywXQNkgezN1Eo scTPiLrwfdvtt1mPbIJORc6c/PX+wXUp2kDpHac5C4v0MxgiWZgPwr+6WuXvX3dLwmid CqSrnBwNJcV+MVxRHmsVX/sD3RR68rulebAwjVJNwzbsfGpkHE5JhNENusI9BtNUDcDf AMpTMtNCJ7C9dFPZkj13z+6J0zCI694C1yRQmXnnnQ57s/af5DXCokzL3v+bw8CvT4cq PFQXXJTjciqNWQC8aSjNjZ9xoBC7junpJcEgJOexPNzyBBxpkNrzizJ/oWChrw0hB37n oWPw== X-Gm-Message-State: AOAM531w99PZnJrT0+3/nggXzH+tN6qFvxXVuSCoUd86VHqQO87kje98 qUB2Yq8BpkX2sgzdT/V33DT53lDU9ZMC7EM/ X-Google-Smtp-Source: ABdhPJzmTnqcVuura/Zc5F+RPG0DSEepWQyvZERnSClf2MiTtp4sxkC7QVBiGAyrBaYucneDZNw9zg== X-Received: by 2002:a1c:7e82:: with SMTP id z124mr22497856wmc.51.1620407686215; Fri, 07 May 2021 10:14:46 -0700 (PDT) Received: from machine.fritz.box (p4fc0a3a3.dip0.t-ipconnect.de. [79.192.163.163]) by smtp.googlemail.com with ESMTPSA id l12sm8897064wrm.76.2021.05.07.10.14.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 May 2021 10:14:45 -0700 (PDT) From: Alexander Sarmanow To: sven@narfation.org Subject: [PATCH v2 2/2] batctl: Add JSON debug commands Date: Fri, 7 May 2021 19:14:35 +0200 Message-Id: <20210507171435.370648-1-asarmanow@gmail.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 ARC-Seal: i=1; s=20121; d=open-mesh.org; t=1620408163; a=rsa-sha256; cv=none; b=28o/PUkG1HMF34Z+MSk36cjCCTKNCtLxHDCCcl+RTQVGVZ1piMa2vvMqBPnj6mV8w6XfA9 5i+zJxOYKtRjuunAuGhYB48qOQMK+o1kjZlWNprAGY2RUWkxyObH/2xlFzt5oPqyujjFc+ 4T+BhJYTxeh2JrrBQHhSlaAvm1JlC/k= ARC-Authentication-Results: i=1; diktynna.open-mesh.org; dkim=pass header.d=gmail.com header.s=20161025 header.b=DNYXZbwd; spf=pass (diktynna.open-mesh.org: domain of asarmanow@gmail.com designates 2a00:1450:4864:20::32a as permitted sender) smtp.mailfrom=asarmanow@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=open-mesh.org; s=20121; t=1620408163; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding:dkim-signature; bh=QuNNpm/02GWBjqtz+O16xdRwcWjMLRAmXRrxMGHa9ns=; b=lX4hkyzDdcakQcnYYQWYgZOYIYm4Z67Ly6dIs3twEYJk1ARrShql4O63QSPA/DF8/v/TsD YQSwVgvFRINbBqcIzQJgj9ZLJMLtqWtRx2U119DMnsdBRXeRoxxjV28YnkiJLum4Lzmaf/ 1VMcWZpdgrZrse5BLdWphJRmhceDnRI= Message-ID-Hash: CRDNONPIS7U7KALMQGV43OG4T6RE52HK X-Message-ID-Hash: CRDNONPIS7U7KALMQGV43OG4T6RE52HK X-MailFrom: asarmanow@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-b.a.t.m.a.n.lists.open-mesh.org-0; header-match-b.a.t.m.a.n.lists.open-mesh.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: b.a.t.m.a.n@lists.open-mesh.org, Alexander Sarmanow X-Mailman-Version: 3.2.1 Precedence: list Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking List-Id: The list for a Better Approach To Mobile Ad-hoc Networking Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: According to part 1 of this patch following commands will be added to the JSON debug: meshinfo_json, originators_json, neighbors_json, translocal_json, transglobal_json. Signed-off-by: Alexander Sarmanow --- Makefile | 5 ++ gateways.c | 2 +- main.c | 14 +++-- main.h | 1 + mcast_flags.c | 2 +- meshinfo_json.c | 139 +++++++++++++++++++++++++++++++++++++++++++++ neighbors_json.c | 89 +++++++++++++++++++++++++++++ netlink.c | 39 ++++++++----- netlink.h | 2 +- originators.c | 2 +- originators_json.c | 107 ++++++++++++++++++++++++++++++++++ transglobal_json.c | 109 +++++++++++++++++++++++++++++++++++ translocal_json.c | 102 +++++++++++++++++++++++++++++++++ 13 files changed, 592 insertions(+), 21 deletions(-) create mode 100644 meshinfo_json.c create mode 100644 neighbors_json.c create mode 100644 originators_json.c create mode 100644 transglobal_json.c create mode 100644 translocal_json.c diff --git a/Makefile b/Makefile index 98bf695..0f85561 100755 --- a/Makefile +++ b/Makefile @@ -54,13 +54,16 @@ $(eval $(call add_command,interface,y)) $(eval $(call add_command,isolation_mark,y)) $(eval $(call add_command,loglevel,y)) $(eval $(call add_command,mcast_flags,y)) +$(eval $(call add_command,meshinfo_json,y)) $(eval $(call add_command,multicast_fanout,y)) $(eval $(call add_command,multicast_forceflood,y)) $(eval $(call add_command,multicast_mode,y)) $(eval $(call add_command,neighbors,y)) +$(eval $(call add_command,neighbors_json,y)) $(eval $(call add_command,network_coding,y)) $(eval $(call add_command,orig_interval,y)) $(eval $(call add_command,originators,y)) +$(eval $(call add_command,originators_json,y)) $(eval $(call add_command,ping,y)) $(eval $(call add_command,routing_algo,y)) $(eval $(call add_command,statistics,y)) @@ -69,8 +72,10 @@ $(eval $(call add_command,throughput_override,y)) $(eval $(call add_command,throughputmeter,y)) $(eval $(call add_command,traceroute,y)) $(eval $(call add_command,transglobal,y)) +$(eval $(call add_command,transglobal_json,y)) $(eval $(call add_command,translate,y)) $(eval $(call add_command,translocal,y)) +$(eval $(call add_command,translocal_json,y)) MANPAGE = man/batctl.8 diff --git a/gateways.c b/gateways.c index 867c882..3704c99 100644 --- a/gateways.c +++ b/gateways.c @@ -123,7 +123,7 @@ static int netlink_print_gateways(struct state *state, char *orig_iface, /* only parse routing algorithm name */ last_err = -EINVAL; info_header = netlink_get_info(state->mesh_ifindex, - BATADV_CMD_GET_ORIGINATORS, NULL); + BATADV_CMD_GET_ORIGINATORS, NULL, 0); free(info_header); if (strlen(algo_name_buf) == 0) diff --git a/main.c b/main.c index d9b63f3..1371bc0 100644 --- a/main.c +++ b/main.c @@ -43,6 +43,10 @@ static void print_usage(void) .label = "debug tables: \tdisplay the corresponding debug table\n", .types = BIT(DEBUGTABLE), }, + { + .label = "debug JSONs: \tdisplay the corresponding debug JSON\n", + .types = BIT(DEBUGJSON), + }, }; const char *default_prefixes[] = { "", @@ -67,9 +71,9 @@ static void print_usage(void) char buf[64]; size_t i; - fprintf(stderr, "Usage: batctl [options] command|debug table [parameters]\n"); + fprintf(stderr, "Usage: batctl [options] command|debug table|debug json [parameters]\n"); fprintf(stderr, "options:\n"); - fprintf(stderr, " \t-h print this help (or 'batctl -h' for the parameter help)\n"); + fprintf(stderr, " \t-h print this help (or 'batctl -h' for the parameter help)\n"); fprintf(stderr, " \t-v print version\n"); for (i = 0; i < sizeof(type) / sizeof(*type); i++) { @@ -87,6 +91,7 @@ static void print_usage(void) continue; switch (cmd->type) { + case DEBUGJSON: case DEBUGTABLE: case SUBCOMMAND_MIF: prefixes = meshif_prefixes; @@ -167,7 +172,8 @@ static const struct command *find_command(struct state *state, const char *name) /* fall through */ case SP_MESHIF: types |= BIT(SUBCOMMAND_MIF) | - BIT(DEBUGTABLE); + BIT(DEBUGTABLE) | + BIT(DEBUGJSON); break; case SP_VLAN: types = BIT(SUBCOMMAND_VID); @@ -380,7 +386,7 @@ int main(int argc, char **argv) cmd = find_command(&state, argv[0]); if (!cmd) { fprintf(stderr, - "Error - no valid command or debug table specified: %s\n", + "Error - no valid command or debug table/JSON specified: %s\n", argv[0]); goto err; } diff --git a/main.h b/main.h index b1ff050..2efd136 100644 --- a/main.h +++ b/main.h @@ -71,6 +71,7 @@ enum command_type { SUBCOMMAND_VID, SUBCOMMAND_HIF, DEBUGTABLE, + DEBUGJSON, }; struct state { diff --git a/mcast_flags.c b/mcast_flags.c index cb6e89d..87fb077 100644 --- a/mcast_flags.c +++ b/mcast_flags.c @@ -105,7 +105,7 @@ static int netlink_print_mcast_flags(struct state *state, char *orig_iface, /* only parse own multicast flags */ info_header = netlink_get_info(state->mesh_ifindex, - BATADV_CMD_GET_MCAST_FLAGS, NULL); + BATADV_CMD_GET_MCAST_FLAGS, NULL, 0); free(info_header); if (mcast_flags == -EOPNOTSUPP || mcast_flags_priv == -EOPNOTSUPP) diff --git a/meshinfo_json.c b/meshinfo_json.c new file mode 100644 index 0000000..8c6f675 --- /dev/null +++ b/meshinfo_json.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) B.A.T.M.A.N. contributors: + * + * Alexander Sarmanow + * + * License-Filename: LICENSES/preferred/GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "batman_adv.h" +#include "debug.h" +#include "main.h" +#include "netlink.h" + +static const int info_mandatory[] = { + BATADV_ATTR_MESH_IFINDEX, + BATADV_ATTR_MESH_IFNAME, +}; + +static int meshinfo_callback(struct nl_msg *msg, void *arg) +{ + struct print_opts *opts = arg; + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *ghdr; + int selected_attrs[10] = { BATADV_ATTR_MESH_IFNAME, + BATADV_ATTR_MESH_ADDRESS, + BATADV_ATTR_HARD_IFNAME, + BATADV_ATTR_VERSION, + BATADV_ATTR_ALGO_NAME, + BATADV_ATTR_HARD_ADDRESS, + BATADV_ATTR_TT_TTVN }; + + if (!genlmsg_valid_hdr(nlh, 0)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_MESH_INFO) + return NL_OK; + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + if (missing_mandatory_attrs(attrs, info_mandatory, + ARRAY_SIZE(info_mandatory))) { + fputs("Missing attributes from kernel\n", stderr); + exit(1); + } + + netlink_print_json_entries(attrs, selected_attrs, + ARRAY_SIZE(selected_attrs), opts); + opts->is_first = 0; + + return NL_OK; +} + +static int netlink_print_meshinfo_json(struct state *state, char *orig_iface, + int read_opts, float orig_timeout, + float watch_interval) +{ + (void) orig_iface; + (void) orig_timeout; + (void) watch_interval; + (void) read_opts; + struct nl_sock *sock; + struct nl_msg *msg; + struct nl_cb *cb; + struct print_opts opts = { + .is_json = 1, + .is_first = 1, + }; + int family; + + if (!state->sock) { + last_err = -EOPNOTSUPP; + return last_err; + } + + sock = nl_socket_alloc(); + if (!sock) + return -1; + + genl_connect(sock); + + family = genl_ctrl_resolve(sock, BATADV_NL_NAME); + if (family < 0) { + nl_socket_free(sock); + return -1; + } + + msg = nlmsg_alloc(); + if (!msg) { + nl_socket_free(sock); + return -1; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, 0, + BATADV_CMD_GET_MESH_INFO, 1); + + nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, state->mesh_ifindex); + + nl_send_auto_complete(sock, msg); + + nlmsg_free(msg); + + cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!cb) + goto err_free_sock; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, meshinfo_callback, &opts); + nl_cb_err(cb, NL_CB_CUSTOM, netlink_print_error, NULL); + + nl_recvmsgs(sock, cb); + +err_free_sock: + nl_socket_free(sock); + + return 0; +} + +static struct debug_table_data batctl_debug_json_meshinfo = { + .netlink_fn = netlink_print_meshinfo_json, +}; + +COMMAND_NAMED(DEBUGJSON, meshinfo_json, "mij", handle_debug_table, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_debug_json_meshinfo, ""); diff --git a/neighbors_json.c b/neighbors_json.c new file mode 100644 index 0000000..5182e47 --- /dev/null +++ b/neighbors_json.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) B.A.T.M.A.N. contributors: + * + * Andrew Lunn + * Alexander Sarmanow + * + * License-Filename: LICENSES/preferred/GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "batadv_packet.h" +#include "batman_adv.h" +#include "bat-hosts.h" +#include "debug.h" +#include "functions.h" +#include "main.h" +#include "netlink.h" + +static const int neighbors_mandatory[] = { + BATADV_ATTR_NEIGH_ADDRESS, + BATADV_ATTR_HARD_IFINDEX, + BATADV_ATTR_LAST_SEEN_MSECS, +}; + +static int neighbors_json_callback(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct print_opts *opts = arg; + struct genlmsghdr *ghdr; + int selected_attrs[4] = { BATADV_ATTR_NEIGH_ADDRESS, + BATADV_ATTR_HARD_IFINDEX, + BATADV_ATTR_LAST_SEEN_MSECS, + BATADV_ATTR_THROUGHPUT }; + + if (!genlmsg_valid_hdr(nlh, 0)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_NEIGHBORS) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + if (missing_mandatory_attrs(attrs, neighbors_mandatory, + ARRAY_SIZE(neighbors_mandatory))) { + fputs("Missing attributes from kernel\n", stderr); + exit(1); + } + + netlink_print_json_entries(attrs, selected_attrs, + ARRAY_SIZE(selected_attrs), opts); + opts->is_first = 0; + + return NL_OK; +} + +static int netlink_print_neighbors_json(struct state *state, char *orig_iface, + int read_opts, float orig_timeout, + float watch_interval) +{ + return netlink_print_common(state, orig_iface, read_opts, + orig_timeout, watch_interval, NULL, + BATADV_CMD_GET_NEIGHBORS, + neighbors_json_callback, true); +} + +static struct debug_table_data batctl_debug_json_neighbors = { + .netlink_fn = netlink_print_neighbors_json, +}; + +COMMAND_NAMED(DEBUGJSON, neighbors_json, "nj", handle_debug_table, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_debug_json_neighbors, ""); diff --git a/netlink.c b/netlink.c index 26ae5ef..db44d82 100644 --- a/netlink.c +++ b/netlink.c @@ -363,17 +363,21 @@ static int info_callback(struct nl_msg *msg, void *arg) 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, extra_header); - if (ret < 0) - opts->remaining_header = NULL; + if (!opts->is_json) { + 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, extra_header); + + if (ret < 0) + opts->remaining_header = NULL; + } if (extra_info) free(extra_info); @@ -387,7 +391,8 @@ static int info_callback(struct nl_msg *msg, void *arg) return NL_STOP; } -char *netlink_get_info(int ifindex, uint8_t nl_cmd, const char *header) +char *netlink_get_info(int ifindex, uint8_t nl_cmd, const char *header, + uint8_t is_json) { struct nl_sock *sock; struct nl_msg *msg; @@ -398,6 +403,7 @@ char *netlink_get_info(int ifindex, uint8_t nl_cmd, const char *header) .nl_cmd = nl_cmd, .remaining_header = NULL, .static_header = header, + .is_json = is_json, }; sock = nl_socket_alloc(); @@ -494,6 +500,9 @@ int netlink_print_common(struct state *state, char *orig_iface, int read_opt, } } + if (is_json) + printf("["); + bat_hosts_init(read_opt); nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, netlink_print_common_cb, &opts); @@ -508,7 +517,8 @@ int netlink_print_common(struct state *state, char *orig_iface, int read_opt, if (!(read_opt & SKIP_HEADER)) opts.remaining_header = netlink_get_info(state->mesh_ifindex, nl_cmd, - header); + header, + is_json); msg = nlmsg_alloc(); if (!msg) @@ -529,6 +539,9 @@ int netlink_print_common(struct state *state, char *orig_iface, int read_opt, last_err = 0; nl_recvmsgs(state->sock, state->cb); + if (is_json) + printf("]"); + /* the header should still be printed when no entry was received */ if (!last_err) netlink_print_remaining_header(&opts); diff --git a/netlink.h b/netlink.h index c766741..47390fc 100644 --- a/netlink.h +++ b/netlink.h @@ -44,7 +44,7 @@ struct ether_addr; int netlink_create(struct state *state); void netlink_destroy(struct state *state); -char *netlink_get_info(int ifindex, uint8_t nl_cmd, const char *header); +char *netlink_get_info(int ifindex, uint8_t nl_cmd, const char *header, uint8_t is_json); int translate_mac_netlink(const char *mesh_iface, const struct ether_addr *mac, struct ether_addr *mac_out); int get_nexthop_netlink(const char *mesh_iface, const struct ether_addr *mac, diff --git a/originators.c b/originators.c index 674656c..c3af740 100644 --- a/originators.c +++ b/originators.c @@ -175,7 +175,7 @@ static int netlink_print_originators(struct state *state, char *orig_iface, /* only parse routing algorithm name */ last_err = -EINVAL; info_header = netlink_get_info(state->mesh_ifindex, - BATADV_CMD_GET_ORIGINATORS, NULL); + BATADV_CMD_GET_ORIGINATORS, NULL, 0); free(info_header); if (strlen(algo_name_buf) == 0) diff --git a/originators_json.c b/originators_json.c new file mode 100644 index 0000000..91dcb44 --- /dev/null +++ b/originators_json.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) B.A.T.M.A.N. contributors: + * + * Andrew Lunn + * Sven Eckelmann + * Alexander Sarmanow + * + * License-Filename: LICENSES/preferred/GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "batadv_packet.h" +#include "batman_adv.h" +#include "bat-hosts.h" +#include "debug.h" +#include "functions.h" +#include "main.h" +#include "netlink.h" + +static const int originators_mandatory[] = { + BATADV_ATTR_ORIG_ADDRESS, + BATADV_ATTR_NEIGH_ADDRESS, + BATADV_ATTR_HARD_IFINDEX, + BATADV_ATTR_LAST_SEEN_MSECS, +}; + +static int originators_json_callback(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + int last_seen_msecs; + struct print_opts *opts = arg; + struct genlmsghdr *ghdr; + float last_seen; + int selected_attrs[6] = { BATADV_ATTR_ORIG_ADDRESS, + BATADV_ATTR_NEIGH_ADDRESS, + BATADV_ATTR_HARD_IFINDEX, + BATADV_ATTR_LAST_SEEN_MSECS, + BATADV_ATTR_THROUGHPUT, + BATADV_ATTR_TQ }; + + if (!genlmsg_valid_hdr(nlh, 0)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + if (missing_mandatory_attrs(attrs, originators_mandatory, + ARRAY_SIZE(originators_mandatory))) { + fputs("Missing attributes from kernel\n", stderr); + exit(1); + } + + last_seen_msecs = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]); + last_seen = (float)last_seen_msecs / 1000.0; + + /* skip timed out originators */ + if (opts->read_opt & NO_OLD_ORIGS) + if (last_seen > opts->orig_timeout) + return NL_OK; + + netlink_print_json_entries(attrs, selected_attrs, + ARRAY_SIZE(selected_attrs), opts); + opts->is_first = 0; + + return NL_OK; +} + +static int netlink_print_originators_json(struct state *state, char *orig_iface, + int read_opts, float orig_timeout, + float watch_interval) +{ + return netlink_print_common(state, orig_iface, read_opts, + orig_timeout, watch_interval, NULL, + BATADV_CMD_GET_ORIGINATORS, + originators_json_callback, 1); +} + +static struct debug_table_data batctl_debug_json_originators = { + .netlink_fn = netlink_print_originators_json, + .option_timeout_interval = 1, + .option_orig_iface = 1, +}; + +COMMAND_NAMED(DEBUGJSON, originators_json, "oj", handle_debug_table, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_debug_json_originators, ""); diff --git a/transglobal_json.c b/transglobal_json.c new file mode 100644 index 0000000..faff8ec --- /dev/null +++ b/transglobal_json.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) B.A.T.M.A.N. contributors: + * + * Andrew Lunn +#include +#include +#include +#include +#include +#include + +#include "batadv_packet.h" +#include "batman_adv.h" +#include "bat-hosts.h" +#include "debug.h" +#include "functions.h" +#include "main.h" +#include "netlink.h" + +static const int transglobal_mandatory[] = { + BATADV_ATTR_TT_ADDRESS, + BATADV_ATTR_ORIG_ADDRESS, + BATADV_ATTR_TT_VID, + BATADV_ATTR_TT_TTVN, + BATADV_ATTR_TT_LAST_TTVN, + BATADV_ATTR_TT_CRC32, + BATADV_ATTR_TT_FLAGS, +}; + +static int transglobal_json_callback(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct print_opts *opts = arg; + struct genlmsghdr *ghdr; + uint8_t *addr; + int selected_attrs[8] = { BATADV_ATTR_TT_ADDRESS, + BATADV_ATTR_ORIG_ADDRESS, + BATADV_ATTR_TT_VID, + BATADV_ATTR_TT_TTVN, + BATADV_ATTR_TT_LAST_TTVN, + BATADV_ATTR_TT_CRC32, + BATADV_ATTR_TT_FLAGS, + BATADV_ATTR_FLAG_BEST }; + + if (!genlmsg_valid_hdr(nlh, 0)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_GLOBAL) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + if (missing_mandatory_attrs(attrs, transglobal_mandatory, + ARRAY_SIZE(transglobal_mandatory))) { + fputs("Missing attributes from kernel\n", stderr); + exit(1); + } + + addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]); + + if (opts->read_opt & MULTICAST_ONLY && !(addr[0] & 0x01)) + return NL_OK; + + if (opts->read_opt & UNICAST_ONLY && (addr[0] & 0x01)) + return NL_OK; + + netlink_print_json_entries(attrs, selected_attrs, + ARRAY_SIZE(selected_attrs), opts); + opts->is_first = 0; + + + return NL_OK; +} + +static int netlink_print_transglobal_json(struct state *state, char *orig_iface, + int read_opts, float orig_timeout, + float watch_interval) +{ + return netlink_print_common(state, orig_iface, read_opts, + orig_timeout, watch_interval, NULL, + BATADV_CMD_GET_TRANSTABLE_GLOBAL, + transglobal_json_callback, true); +} + +static struct debug_table_data batctl_debug_json_transglobal = { + .netlink_fn = netlink_print_transglobal_json, + .option_unicast_only = 1, + .option_multicast_only = 1, +}; + +COMMAND_NAMED(DEBUGJSON, transglobal_json, "tgj", handle_debug_table, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_debug_json_transglobal, ""); diff --git a/translocal_json.c b/translocal_json.c new file mode 100644 index 0000000..e78150e --- /dev/null +++ b/translocal_json.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) B.A.T.M.A.N. contributors: + * + * Andrew Lunn + * Sven Eckelmann + * Alexander Sarmanow + * + * License-Filename: LICENSES/preferred/GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "batadv_packet.h" +#include "batman_adv.h" +#include "bat-hosts.h" +#include "debug.h" +#include "functions.h" +#include "main.h" +#include "netlink.h" + +static const int translocal_mandatory[] = { + BATADV_ATTR_TT_ADDRESS, + BATADV_ATTR_TT_VID, + BATADV_ATTR_TT_CRC32, + BATADV_ATTR_TT_FLAGS, +}; + +static int translocal_json_callback(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct print_opts *opts = arg; + struct genlmsghdr *ghdr; + uint8_t *addr; + int selected_attrs[5] = { BATADV_ATTR_TT_ADDRESS, + BATADV_ATTR_TT_VID, + BATADV_ATTR_TT_CRC32, + BATADV_ATTR_TT_FLAGS, + BATADV_ATTR_LAST_SEEN_MSECS }; + + if (!genlmsg_valid_hdr(nlh, 0)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_LOCAL) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + fputs("Received invalid data from kernel.\n", stderr); + exit(1); + } + + if (missing_mandatory_attrs(attrs, translocal_mandatory, + ARRAY_SIZE(translocal_mandatory))) { + fputs("Missing attributes from kernel\n", stderr); + exit(1); + } + + addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]); + + if (opts->read_opt & MULTICAST_ONLY && !(addr[0] & 0x01)) + return NL_OK; + + if (opts->read_opt & UNICAST_ONLY && (addr[0] & 0x01)) + return NL_OK; + + netlink_print_json_entries(attrs, selected_attrs, + ARRAY_SIZE(selected_attrs), opts); + opts->is_first = 0; + + return NL_OK; +} + +static int netlink_print_translocal_json(struct state *state, char *orig_iface, + int read_opts, float orig_timeout, + float watch_interval) +{ + return netlink_print_common(state, orig_iface, read_opts, + orig_timeout, watch_interval, NULL, + BATADV_CMD_GET_TRANSTABLE_LOCAL, + translocal_json_callback, 1); +} + +static struct debug_table_data batctl_debug_json_translocal = { + .netlink_fn = netlink_print_translocal_json, + .option_unicast_only = 1, + .option_multicast_only = 1, +}; + +COMMAND_NAMED(DEBUGJSON, translocal_json, "tlj", handle_debug_table, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_debug_json_translocal, "");