Merge pull request #1201 from ecsv/batadv-for-24.10

[24.10] batman-adv: merge bugfixes from 2026.3
This commit is contained in:
Simon Wunderlich authored and GitHub committed 2026-09-03 09:33:33 +02:00
commit 00619bc7bc
185 files changed
+4732 -24

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=alfred
PKG_VERSION:=2024.3
PKG_RELEASE:=2
PKG_RELEASE:=3
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION)
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 8 Mar 2026 16:07:25 +0100
Subject: alfred: Fix printing of timespec
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 08:25:05 +0200
Subject: alfred: seed the random() generator for transaction IDs
time_random_seed() initialized the PRNG with srand(), but the only
consumer, get_random_id(), draws its values from random(). srand()/rand()
and srandom()/random() are two independent generators which can have
separate state; seeding one does not affect the other.
Seed random() with srandom() so the generator that is actually used gets
the computed seed.
Fixes: fcfe26c690ce ("alfred: Add transaction management block to push_data")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/alfred.git/commit/?id=b175725a5ac75a832370cefd604ee80e0cc226b4
--- a/util.c
+++ b/util.c
@@ -46,7 +46,7 @@ void time_random_seed(void)
s += c[i];
}
- srand(s);
+ srandom(s);
}
uint16_t get_random_id(void)
+8 -17
View File
@@ -4,12 +4,11 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=batctl
PKG_VERSION:=2024.3
PKG_RELEASE:=3
PKG_RELEASE:=5
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION)
PKG_HASH:=665e655eda381415218a4d5f5fd77ff33c4fa9b5edbb7e88e839096961e3600b
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
PKG_MAINTAINER:=Simon Wunderlich <sw@simonwunderlich.de>
PKG_LICENSE:=GPL-2.0-only ISC MIT
@@ -29,7 +28,7 @@ define Package/batctl/Default
endef
define Package/batctl/description
batctl is a more intuitive managment utility for B.A.T.M.A.N.-Advanced.
batctl is a more intuitive management utility for B.A.T.M.A.N.-Advanced.
It is an easier method for configuring batman-adv and provides some
additional tools for debugging as well. This package builds
version $(PKG_VERSION) of the user space utility.
@@ -72,11 +71,11 @@ $(Package/batctl/description)
endef
MAKE_VARS += \
LIBNL_NAME="libnl-tiny" \
LIBNL_GENL_NAME="libnl-tiny"
LIBNL_NAME="libnl-tiny" \
LIBNL_GENL_NAME="libnl-tiny"
MAKE_FLAGS += \
REVISION="$(PKG_VERSION)-openwrt-$(PKG_RELEASE)"
REVISION="$(PKG_VERSION)-openwrt-$(PKG_RELEASE)"
config-n := \
aggregation \
@@ -216,17 +215,9 @@ config-y := \
endif
define ConfigVars
$(subst $(space),,$(foreach opt,$(config-$(1)),CONFIG_$(opt)=$(1)
))
endef
define batctl_config
$(call ConfigVars,n)$(call ConfigVars,y)
endef
$(eval $(call shexport,batctl_config))
MAKE_FLAGS += $$$$$(call shvar,batctl_config)
MAKE_FLAGS += \
$(patsubst %,CONFIG_%=n,$(config-n)) \
$(patsubst %,CONFIG_%=y,$(config-y))
define Package/batctl-tiny/install
$(INSTALL_DIR) $(1)/usr/libexec
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 3 Aug 2025 08:48:40 +0200
Subject: batctl: event: Fix direct parsing on hardif for set_hardif
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 3 Aug 2025 08:49:12 +0200
Subject: batctl: Avoid memory leak in print_routing_algos
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 8 Mar 2026 15:52:30 +0100
Subject: batctl: tcpdump: Fix printing of usecs
@@ -0,0 +1,312 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 08:49:38 +0200
Subject: batctl: fix parsing of parameters with arguments
If using a getopt argument with an argument, it can be supplied via:
* -m asd
* -m=asd
* -masd
Only the first version is correctly handled by the found_args
implementation (without causing undefined behavior). But it can be instead
simplified and fixed at the same time by directly using the optind variable
from getopt.
Fixes: 87ade2869cf3 ("add interval and loop count options")
Fixes: 3bdfc388e74b ("implement simple tcpdump, first only batman packets")
Fixes: ece05e1c4c1f ("[batctl] bisect (a tool to analyze logfiles) added")
Fixes: f3c9cf9e730e ("source out calculation of round trip time to functions.c add abbreviation for modules, example ping = p add traceroute module, not complete")
Fixes: f109b3473f86 ("batctl: introduce throughput meter support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=26b997032052b0d7ab842a156f65fab5441581a7
--- a/bisect_iv.c
+++ b/bisect_iv.c
@@ -1429,7 +1429,7 @@ err:
static int bisect_iv(struct state *state __maybe_unused, int argc, char **argv)
{
- int ret = EXIT_FAILURE, res, optchar, found_args = 1;
+ int ret = EXIT_FAILURE, res, optchar;
int read_opt = USE_BAT_HOSTS, num_parsed_files;
long long tmp_seqno, seqno_max = -1, seqno_min = -1;
char *trace_orig_ptr = NULL, *rt_orig_ptr = NULL, *loop_orig_ptr = NULL;
@@ -1445,19 +1445,15 @@ static int bisect_iv(struct state *state
return EXIT_SUCCESS;
case 'l':
loop_orig_ptr = optarg;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 'n':
read_opt &= ~USE_BAT_HOSTS;
- found_args += 1;
break;
case 'o':
filter_orig_ptr = optarg;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 'r':
rt_orig_ptr = optarg;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 's':
dash_ptr = strchr(optarg, '-');
@@ -1480,11 +1476,9 @@ static int bisect_iv(struct state *state
*dash_ptr = '-';
}
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 't':
trace_orig_ptr = optarg;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
default:
bisect_iv_usage();
@@ -1492,7 +1486,7 @@ static int bisect_iv(struct state *state
}
}
- if (argc <= found_args + 1) {
+ if (argc <= optind + 1) {
fprintf(stderr, "Error - need at least 2 log files to compare\n");
bisect_iv_usage();
goto err;
@@ -1551,13 +1545,13 @@ static int bisect_iv(struct state *state
goto err;
}
- while (argc > found_args) {
- res = parse_log_file(argv[found_args]);
+ while (argc > optind) {
+ res = parse_log_file(argv[optind]);
if (res > 0)
num_parsed_files++;
- found_args++;
+ optind++;
}
if (num_parsed_files < 2) {
--- a/main.c
+++ b/main.c
@@ -357,7 +357,7 @@ int main(int argc, char **argv)
}
fprintf(stderr, "Warning - option -m was deprecated and will be removed in the future\n");
- state.arg_iface = argv[2];
+ state.arg_iface = optarg;
break;
case 'v':
version();
--- a/ping.c
+++ b/ping.c
@@ -64,7 +64,7 @@ static int ping(struct state *state, int
struct ether_addr *dst_mac = NULL, *rr_mac = NULL;
struct bat_host *bat_host, *rr_host;
ssize_t read_len;
- int ret = EXIT_FAILURE, res, optchar, found_args = 1;
+ int ret = EXIT_FAILURE, res, optchar;
int loop_count = -1, loop_interval = 0, timeout = 1, rr = 0, i;
unsigned int seq_counter = 0, packets_out = 0, packets_in = 0, packets_loss;
char *dst_string, *mac_string, *rr_string;
@@ -80,7 +80,6 @@ static int ping(struct state *state, int
loop_count = strtol(optarg, NULL , 10);
if (loop_count < 1)
loop_count = -1;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 'h':
ping_usage();
@@ -89,21 +88,17 @@ static int ping(struct state *state, int
loop_interval = strtol(optarg, NULL , 10);
if (loop_interval < 1)
loop_interval = 1;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 't':
timeout = strtol(optarg, NULL , 10);
if (timeout < 1)
timeout = 1;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 'R':
rr = 1;
- found_args++;
break;
case 'T':
disable_translate_mac = 1;
- found_args += 1;
break;
default:
ping_usage();
@@ -111,7 +106,7 @@ static int ping(struct state *state, int
}
}
- if (argc <= found_args) {
+ if (optind >= argc) {
fprintf(stderr, "Error - target mac address or bat-host name not specified\n");
ping_usage();
return EXIT_FAILURE;
@@ -119,7 +114,7 @@ static int ping(struct state *state, int
check_root_or_die("batctl ping");
- dst_string = argv[found_args];
+ dst_string = argv[optind];
bat_hosts_init(0);
bat_host = bat_hosts_find_by_name(dst_string);
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1440,7 +1440,7 @@ static int tcpdump(struct state *state _
struct list_head dump_if_list;
fd_set wait_sockets, tmp_wait_sockets;
ssize_t read_len;
- int ret = EXIT_FAILURE, res, optchar, found_args = 1, max_sock = 0, tmp;
+ int ret = EXIT_FAILURE, res, optchar, max_sock = 0, tmp;
int read_opt = USE_BAT_HOSTS;
unsigned char packet_buff[2000];
int monitor_header_len = -1;
@@ -1451,26 +1451,22 @@ static int tcpdump(struct state *state _
switch (optchar) {
case 'c':
read_opt |= COMPAT_FILTER;
- found_args += 1;
break;
case 'h':
tcpdump_usage();
return EXIT_SUCCESS;
case 'n':
read_opt &= ~USE_BAT_HOSTS;
- found_args += 1;
break;
case 'p':
tmp = strtol(optarg, NULL , 10);
if ((tmp > 0) && (tmp <= dump_level_all))
dump_level = tmp;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 'x':
tmp = strtol(optarg, NULL , 10);
if ((tmp > 0) && (tmp <= dump_level_all))
dump_level &= ~tmp;
- found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
default:
tcpdump_usage();
@@ -1478,7 +1474,7 @@ static int tcpdump(struct state *state _
}
}
- if (argc <= found_args) {
+ if (optind >= argc) {
fprintf(stderr, "Error - target interface not specified\n");
tcpdump_usage();
return EXIT_FAILURE;
@@ -1495,8 +1491,8 @@ static int tcpdump(struct state *state _
INIT_LIST_HEAD(&dump_if_list);
FD_ZERO(&wait_sockets);
- while (argc > found_args) {
- dump_if = create_dump_interface(argv[found_args]);
+ while (optind < argc) {
+ dump_if = create_dump_interface(argv[optind]);
if (!dump_if)
goto out;
@@ -1505,7 +1501,7 @@ static int tcpdump(struct state *state _
FD_SET(dump_if->raw_sock, &wait_sockets);
list_add_tail(&dump_if->list, &dump_if_list);
- found_args++;
+ optind++;
}
while (!is_aborted) {
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -315,7 +315,7 @@ static int throughputmeter(struct state
uint64_t throughput;
char *dst_string;
int ret = EXIT_FAILURE;
- int found_args = 1, read_opt = USE_BAT_HOSTS;
+ int read_opt = USE_BAT_HOSTS;
uint32_t time = 0;
int optchar;
struct nl_sock *listen_sock = NULL;
@@ -335,12 +335,10 @@ static int throughputmeter(struct state
while ((optchar = getopt(argc, argv, "t:n")) != -1) {
switch (optchar) {
case 't':
- found_args += 2;
time = strtoul(optarg, NULL, 10);
break;
case 'n':
read_opt &= ~USE_BAT_HOSTS;
- found_args += 1;
break;
default:
tp_meter_usage();
@@ -348,14 +346,14 @@ static int throughputmeter(struct state
}
}
- if (argc <= found_args) {
+ if (optind >= argc) {
tp_meter_usage();
return EXIT_FAILURE;
}
check_root_or_die("batctl throughputmeter");
- dst_string = argv[found_args];
+ dst_string = argv[optind];
bat_hosts_init(read_opt);
bat_host = bat_hosts_find_by_name(dst_string);
--- a/traceroute.c
+++ b/traceroute.c
@@ -49,7 +49,7 @@ static int traceroute(struct state *stat
ssize_t read_len;
char *dst_string, *mac_string, *return_mac, dst_reached = 0;
int ret = EXIT_FAILURE, res, i;
- int found_args = 1, optchar, seq_counter = 0, read_opt = USE_BAT_HOSTS;
+ int optchar, seq_counter = 0, read_opt = USE_BAT_HOSTS;
double time_delta[NUM_PACKETS];
int disable_translate_mac = 0;
@@ -60,11 +60,9 @@ static int traceroute(struct state *stat
return EXIT_SUCCESS;
case 'n':
read_opt &= ~USE_BAT_HOSTS;
- found_args += 1;
break;
case 'T':
disable_translate_mac = 1;
- found_args += 1;
break;
default:
traceroute_usage();
@@ -72,7 +70,7 @@ static int traceroute(struct state *stat
}
}
- if (argc <= found_args) {
+ if (optind >= argc) {
fprintf(stderr, "Error - target mac address or bat-host name not specified\n");
traceroute_usage();
return EXIT_FAILURE;
@@ -80,7 +78,7 @@ static int traceroute(struct state *stat
check_root_or_die("batctl traceroute");
- dst_string = argv[found_args];
+ dst_string = argv[optind];
bat_hosts_init(read_opt);
bat_host = bat_hosts_find_by_name(dst_string);
@@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 09:22:14 +0200
Subject: batctl: originators: fix throughput lines with bat_hosts
When bat_hosts is used, the output should be the same as without it. But
for B.A.T.M.A.N. V, there were two major differences:
* when no hostname was found: extra space before the nexthop neighbor
* when hostname was found: best-flag character before the hostname
Sync the implementation with the B.A.T.M.A.N. IV implementation to get rid
of the unexpected differences.
Fixes: d8dd1ff1a0fe ("batctl: Use netlink to replace some of debugfs")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=08fd004f9eaf2d443f4f89bd50cd1f96a723f52e
--- a/originators.c
+++ b/originators.c
@@ -129,9 +129,9 @@ static int originators_callback(struct n
throughput_mbits, throughput_kbits / 100);
bat_host = bat_hosts_find_by_mac((char *)neigh);
if (bat_host)
- printf(" %c %17s ", c, bat_host->name);
+ printf("%17s ", bat_host->name);
else
- printf(" %02x:%02x:%02x:%02x:%02x:%02x ",
+ printf("%02x:%02x:%02x:%02x:%02x:%02x ",
neigh[0], neigh[1], neigh[2],
neigh[3], neigh[4], neigh[5]);
printf("[%10s]\n", ifname);
@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 09:47:02 +0200
Subject: batctl: free header lines after error
If the common netlink helper or the routing algorithm code never printed
the header, nothing would clean up the remaining_headers. Explicitly free
it up to avoid a minor memory leak.
Fixes: 5401c71adfad ("batctl: Use debugfs fallback when netlink not supported")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=de6f6f554697836141892966d97f883f46beac4f
--- a/netlink.c
+++ b/netlink.c
@@ -593,6 +593,10 @@ int netlink_print_common(struct state *s
} while (!last_err && read_opt & (CONT_READ|CLR_CONT_READ));
+ /* free a header that was prepared but never printed (e.g. on error) */
+ free(opts.remaining_header);
+ opts.remaining_header = NULL;
+
bat_hosts_free();
return last_err;
--- a/routing_algo.c
+++ b/routing_algo.c
@@ -109,8 +109,12 @@ static int print_routing_algos(struct st
nl_recvmsgs(state->sock, cb);
- if (!last_err)
+ if (!last_err) {
netlink_print_remaining_header(&opts);
+ } else {
+ free(opts.remaining_header);
+ opts.remaining_header = NULL;
+ }
return last_err;
}
@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 13:20:12 +0200
Subject: batctl: traceroute: handle fast replies
If a reply for a traceroute is received faster than the CLOCK_MONOTONIC
precision or (in the rather unlikely scenario) the double precision,
time_delta[i] would be 0. In this case, the packet would be counted as
lost. Introduce a new array "received" to only track whether the packet was
received or not.
Fixes: 0641511400dc ("batctl: traceroute - use all received packets to retrieve neighbor mac")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=eda6c454d6909324a7f771239dc3ef334df42143
--- a/traceroute.c
+++ b/traceroute.c
@@ -51,6 +51,7 @@ static int traceroute(struct state *stat
int ret = EXIT_FAILURE, res, i;
int optchar, seq_counter = 0, read_opt = USE_BAT_HOSTS;
double time_delta[NUM_PACKETS];
+ uint8_t received[NUM_PACKETS];
int disable_translate_mac = 0;
while ((optchar = getopt(argc, argv, "hnT")) != -1) {
@@ -121,6 +122,7 @@ static int traceroute(struct state *stat
for (i = 0; i < NUM_PACKETS; i++) {
icmp_packet_out.seqno = htons(++seq_counter);
time_delta[i] = 0.0;
+ received[i] = 0;
res = icmp_interface_write(state,
(struct batadv_icmp_header *)&icmp_packet_out,
@@ -157,6 +159,7 @@ read_packet:
/* fall through */
case BATADV_TTL_EXCEEDED:
time_delta[i] = end_timer();
+ received[i] = 1;
if (!return_mac) {
return_mac = ether_ntoa_long((struct ether_addr *)&icmp_packet_in.orig);
@@ -190,7 +193,7 @@ read_packet:
bat_host->name, return_mac);
for (i = 0; i < NUM_PACKETS; i++) {
- if (time_delta[i])
+ if (received[i])
printf(" %.3f ms", time_delta[i]);
else
printf(" *");
@@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 13:51:21 +0200
Subject: batctl: return only initialized icmp destination unreached bytes
When icmp_interface_write() fails with an unreachable destination, it
prepares a reply packet using original packet but changes the message type
to BATADV_DESTINATION_UNREACHABLE. But when icmp_interface_read() tries to
retrieve this data, the requested packet len could be higher than the
length of the original packet. In this case, the returned packet length
must be truncated to the number of bytes of the original one.
Fixes: 4bd751eed4dc ("batctl: Implement non-routing batadv_icmp in userspace")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=7dab91c978f43cd8b84187511ba58e60d8d953ef
--- a/icmp_helper.c
+++ b/icmp_helper.c
@@ -471,6 +471,12 @@ ssize_t icmp_interface_read(struct batad
packet_len = len;
if (direct_reply_len > 0) {
+ /* never deliver more than was actually stored by the
+ * dst_unreachable path, nor more than the caller's buffer holds
+ */
+ if (packet_len > direct_reply_len)
+ packet_len = direct_reply_len;
+
memcpy(icmp_packet, icmp_buffer, packet_len);
direct_reply_len = 0;
return (ssize_t)packet_len;
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 13:57:33 +0200
Subject: batctl: tcpdump: fix coded packet mac dest mac addresses
get_name_by_macaddr uses returns shared buffer. The content of the buffer
must therefore be processed first before the next get_name_by_macaddr()
call is performed.
Fixes: 9aae3c9f27b8 ("batctl: tcpdump: Add support for coded packets")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=760aa456b45ae73e840aa211c5b58b95f8752af2
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1121,9 +1121,10 @@ static void dump_batman_coded(unsigned c
get_name_by_macaddr((struct ether_addr *)ether_header->ether_shost,
read_opt));
- printf("%s|%s: CODED, ttvn %d|%d, ttl %hhu\n",
+ printf("%s|",
get_name_by_macaddr((struct ether_addr *)coded_packet->first_orig_dest,
- read_opt),
+ read_opt));
+ printf("%s: CODED, ttvn %d|%d, ttl %hhu\n",
get_name_by_macaddr((struct ether_addr *)coded_packet->second_dest,
read_opt),
coded_packet->first_ttvn, coded_packet->second_ttvn,
@@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 14:00:21 +0200
Subject: batctl: tcpdump: fix endianness of fragmentation sequence number
The kernel returns the unicast fragmentation packet in network (big endian)
byte order. But the system might be little endian. In this case, the bytes
must be first reordered before they can be printed.
Fixes: 30f8fe9c105a ("batctl: tcpdump: Add support for unicast fragmentation")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=ae2632b8cf4b1881ad7fe87f72e93f85f482de03
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1023,7 +1023,7 @@ static void dump_batman_ucast_frag(unsig
printf("%s: UCAST FRAG, seqno %d, no %d, ttl %hhu\n",
get_name_by_macaddr((struct ether_addr *)frag_packet->dest,
read_opt),
- frag_packet->seqno, frag_packet->no, frag_packet->ttl);
+ ntohs(frag_packet->seqno), frag_packet->no, frag_packet->ttl);
}
static void dump_batman_bcast(unsigned char *packet_buff, ssize_t buff_len, int read_opt, int time_printed)
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 14:06:47 +0200
Subject: batctl: tcpdump: correct output of VLAN IDs
The 16 bit TCI header for VLAN tagging (IEEE 802.1Q) stores 12 bit for the
12 bit VID, 1 bit DEI and 3 bit PCP. It is therefore unexpected to print
the 16 bit as vlan identifier without masking out the upper 4 bit.
At the same time, also split the DEI ( Drop Eligible Indicator) and the PCP
(Priority Code Point) in separate output fields.
Fixes: 7738b534fb07 ("batctl: tcpdump - add vlan support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=cd0ba25ad03a27226617678638ebb666b7f8eeb1
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -802,7 +802,8 @@ static void dump_vlan(unsigned char *pac
time_printed = print_time();
vlanhdr->vid = ntohs(vlanhdr->vid);
- printf("vlan %u, p %u, ", vlanhdr->vid, vlanhdr->vid >> 12);
+ printf("vlan %u, d %u, p %u, ", vlanhdr->vid & 0x0fff, (vlanhdr->vid >> 12) & 0x1,
+ vlanhdr->vid >> 13);
/* overwrite vlan tags */
memmove(packet_buff + 4, packet_buff, 2 * ETH_ALEN);
@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 14:17:09 +0200
Subject: batctl: tcpdump: drop hardcoded IPv6 buffer sizes
The inet_ntop expects to know the dst size buffer. But instead of
specifying how to calculate the size of this buffer, just a value was
hardcoded - which might not fulfill the "INET6_ADDRSTRLEN" size
requirements.
Evaluate the size of the buffer at compile time to avoid potential
discrepancies.
Fixes: 35b37756f4a3 ("add IPv6 support to tcpdump parser")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=12165ffbd5e4d14bb71270a2108274754584615e
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -657,7 +657,7 @@ static void dump_ipv6(unsigned char *pac
sizeof(*nd_neigh_sol), "ICMPv6 Neighbor Solicitation");
nd_neigh_sol = (struct nd_neighbor_solicit *)icmphdr;
inet_ntop(AF_INET6, &(nd_neigh_sol->nd_ns_target),
- nd_nas_target, 40);
+ nd_nas_target, sizeof(nd_nas_target));
printf(" neighbor solicitation, who has %s, length %zd\n",
nd_nas_target, buff_len);
break;
@@ -666,7 +666,7 @@ static void dump_ipv6(unsigned char *pac
sizeof(*nd_advert), "ICMPv6 Neighbor Advertisement");
nd_advert = (struct nd_neighbor_advert *)icmphdr;
inet_ntop(AF_INET6, &(nd_advert->nd_na_target),
- nd_nas_target, 40);
+ nd_nas_target, sizeof(nd_nas_target));
printf(" neighbor advertisement, tgt is %s, length %zd\n",
nd_nas_target, buff_len);
break;
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 14:25:08 +0200
Subject: batctl: tcpdump: fix reported length for ICMP6_TIME_EXCEEDED
The remaining buffer size for ICMP6_TIME_EXCEEDED is only the buffer length
minus the IPv6 header. It could now be discussed whether the output length
should now be with or without the icmp6_hdr length. The length with
icmp6_hdr was chosen because the code looks like a simple copy and paste
error and ip6_hdr's length was most likely the actual intent for the
calculation.
Fixes: 35b37756f4a3 ("add IPv6 support to tcpdump parser")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=2653fa20705098a8c90ee30265bef4c5d0277aed
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -650,7 +650,7 @@ static void dump_ipv6(unsigned char *pac
break;
case ICMP6_TIME_EXCEEDED:
printf(" time exceeded in-transit, length %zu\n",
- (size_t)buff_len - sizeof(struct icmp6_hdr));
+ (size_t)buff_len - sizeof(struct ip6_hdr));
break;
case ND_NEIGHBOR_SOLICIT:
LEN_CHECK((size_t)buff_len - (size_t)(sizeof(struct ip6_hdr)),
@@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 14:31:58 +0200
Subject: batctl: tcpdump: handle TCP packet with bogus data offset
dump_tcp() computes length as (buff_len - ip6_header_len - tcp_header_len),
but the only bounds guard ensures 20 bytes, while doff allows a higher
header length (60 bytes). With a doff of 15 (60 bytes) and only 20 bytes
available in the buffer, the calculation would underflow and show a bugus
length of the TCP payload. For now, set the payload length to zero for such
a packet.
Fixes: 35b37756f4a3 ("add IPv6 support to tcpdump parser")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=18c101bc28440f5638865cbdcf6faa64c5974a33
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -518,18 +518,20 @@ static void dump_tcp(const char ip_strin
{
uint16_t tcp_header_len;
struct tcphdr *tcphdr;
+ size_t tcp_len;
LEN_CHECK((size_t)buff_len - ip6_header_len,
sizeof(struct tcphdr), "TCP");
tcphdr = (struct tcphdr *)(packet_buff + ip6_header_len);
tcp_header_len = tcphdr->doff * 4;
+ tcp_len = (size_t)buff_len - ip6_header_len;
printf("%s %s.%i > ", ip_string, src_addr, ntohs(tcphdr->source));
printf("%s.%i: TCP, Flags [%c%c%c%c%c%c], length %zu\n",
dst_addr, ntohs(tcphdr->dest),
(tcphdr->fin ? 'F' : '.'), (tcphdr->syn ? 'S' : '.'),
(tcphdr->rst ? 'R' : '.'), (tcphdr->psh ? 'P' : '.'),
(tcphdr->ack ? 'A' : '.'), (tcphdr->urg ? 'U' : '.'),
- (size_t)buff_len - ip6_header_len - tcp_header_len);
+ tcp_len > tcp_header_len ? tcp_len - tcp_header_len : 0);
}
static void dump_udp(const char ip_string[], unsigned char *packet_buff,
@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 14:43:31 +0200
Subject: batctl: tpmeter: fix Gbps output
The formatter for the Gbps result should print 2 digits after the dot. But
the format specifier was different than in all other branches and didn't
specify the precision after the dot. Instead a minimal number of digits (or
spaces) before the dot was defined.
Fixes: f109b3473f86 ("batctl: introduce throughput meter support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=3842d2e62b26f4c34621d18cef1d7dfd48557023
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -436,7 +436,7 @@ static int throughputmeter(struct state
if (throughput == UINT64_MAX)
printf("inf\n");
else if (throughput > (1UL<<30))
- printf("%.2f GB/s (%2.f Gbps)\n",
+ printf("%.2f GB/s (%.2f Gbps)\n",
(float)throughput / (1<<30),
(float)throughput * 8 / 1000000000);
else if (throughput > (1UL<<20))
@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 14:20:03 +0200
Subject: batctl: tpmeter: label sub-kByte/s rate in bits per second
The throughput result is printed as a bytes-per-second value followed by
the same rate in bits per second in parentheses. The GB/s, MB/s and KB/s
branches correctly label the parenthesised "throughput * 8" value as
Gbps/Mbps/Kbps (lower-case "b" for bits), but the fallback branch for
rates below one kByte/s labels it "Bps" (upper-case "B", conventionally
bytes per second). That makes the line self-contradictory, e.g.
5 Bytes/s (40 Bps)
which reads as "40 bytes/s" while the value is actually 40 bits/s.
Use the lower-case "bps" suffix so the unit matches the other branches
and the value it describes.
Fixes: f109b3473f86 ("batctl: introduce throughput meter support")
Signed-off-by: Sven Eckelmann <se@simonwunderlich.de>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=904f2bc9f50482eb5262525a7c99c4a7b7f71147
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -448,7 +448,7 @@ static int throughputmeter(struct state
(float)throughput / (1<<10),
(float)throughput * 8 / 1000);
else
- printf("%" PRIu64 " Bytes/s (%" PRIu64 " Bps)\n",
+ printf("%" PRIu64 " Bytes/s (%" PRIu64 " bps)\n",
throughput, throughput * 8);
ret = 0;
@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 13:11:06 +0200
Subject: batctl: netlink: check for BATADV_ATTR_MESH_ADDRESS before accessing it
info_callback expects the BATADV_ATTR_MESH_ADDRESS attribute to be set. But
it never checked if it is not NULL.
Fixes: d8dd1ff1a0fe ("batctl: Use netlink to replace some of debugfs")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=fcac106f46bcf2b6339560ee81548a25a5cb3498
--- a/netlink.c
+++ b/netlink.c
@@ -329,6 +329,7 @@ int netlink_stop_callback(struct nl_msg
static const int info_mandatory[] = {
BATADV_ATTR_MESH_IFINDEX,
BATADV_ATTR_MESH_IFNAME,
+ BATADV_ATTR_MESH_ADDRESS,
};
static const int info_hard_mandatory[] = {
@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 14:55:05 +0200
Subject: batctl: netlink: always 0-terminate hardif name
The kernel should not send non-0 terminated interface name name or an
interface name larger than IFNAMSIZ. Just to be on the safe side, still
force the last byte to the 0-delimiter.
Fixes: 426e48c8d9ca ("batctl: ping: Get outgoing ifname from netlink")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=60b8ff8b56dd90ba5c6b0cfc98295b2696eebaff
--- a/netlink.c
+++ b/netlink.c
@@ -828,7 +828,8 @@ static int get_nexthop_netlink_cb(struct
if (attrs[BATADV_ATTR_HARD_IFNAME]) {
ifname = nla_get_string(attrs[BATADV_ATTR_HARD_IFNAME]);
- strncpy(opts->ifname, ifname, IFNAMSIZ);
+ strncpy(opts->ifname, ifname, IFNAMSIZ - 1);
+ opts->ifname[IFNAMSIZ - 1] = '\0';
} else {
/* compatibility for Linux < 5.14/batman-adv < 2021.2 */
ifname = if_indextoname(index, opts->ifname);
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 15:06:20 +0200
Subject: batctl: bat-hosts: compare full path for deduplication
The deduplication code uses realpath to store the real path of a provided
configuration file. The code then tries to compare these paths but
accidentally only comparse only the first CONF_DIR_LEN (256) bytes of the
path.
The number of bytes must be set to the same length as the path size slot in
the normalized buffer.
Fixes: db97c2a77e81 ("batctl: fix crash in bat-hosts parser on embedded systems")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=65d8c6d78d745264a2bb49fa79baaa8865e6d5f7
--- a/bat-hosts.c
+++ b/bat-hosts.c
@@ -193,7 +193,7 @@ void bat_hosts_init(int read_opt)
/* check for duplicates: don't parse the same file twice */
parse = 1;
for (j = 0; j < i; j++) {
- if (strncmp(normalized + (i * PATH_MAX), normalized + (j * PATH_MAX), CONF_DIR_LEN) == 0) {
+ if (strncmp(normalized + (i * PATH_MAX), normalized + (j * PATH_MAX), PATH_MAX) == 0) {
parse = 0;
break;
}
@@ -0,0 +1,202 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 11:05:04 +0200
Subject: batctl: improve number parsing error handling
The strtoul error handling is rather complicated and it is not only about
checking the return value. The possible error indicators are:
* endptr is NULL
* endptr is not pointing to end delimiter
* endptr is pointing at nptr (because it might have been an empty string)
* returned value is larger than the expected maximum value range
THe last two conditions were not checked even when it is a potential
problem for multiple places.
Fixes: df5c452a4469 ("batctl: Add elp_interval setting command")
Fixes: 74b6d3bd7763 ("batctl: Parse the arguments for gw_mode")
Fixes: cde0af829351 ("batctl: Add hop_penalty setting command")
Fixes: a319ec4dcbff ("batctl: Support generic netlink for isolation_mark command")
Fixes: 1ca604d5a0f2 ("batctl: add switch for setting multicast_fanout")
Fixes: c49893119205 ("batctl: Support generic netlink for orig_interval command")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=20f137cb0a2addb761ab88ba66121c887c9f2fec
--- a/elp_interval.c
+++ b/elp_interval.c
@@ -22,6 +22,7 @@ static int parse_elp_interval(struct sta
{
struct settings_data *settings = state->cmd->arg;
struct elp_interval_data *data = settings->data;
+ unsigned long elp_interval;
char *endptr;
if (argc != 2) {
@@ -29,12 +30,14 @@ static int parse_elp_interval(struct sta
return -EINVAL;
}
- data->elp_interval = strtoul(argv[1], &endptr, 0);
- if (!endptr || *endptr != '\0') {
+ elp_interval = strtoul(argv[1], &endptr, 0);
+ if (!endptr || *endptr != '\0' || endptr == argv[1] || elp_interval > UINT32_MAX) {
fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]);
return -EINVAL;
}
+ data->elp_interval = elp_interval;
+
return 0;
}
--- a/functions.c
+++ b/functions.c
@@ -985,7 +985,7 @@ bool parse_throughput(char *buff, const
}
lthroughput = strtoull(buff, &endptr, 10);
- if (!endptr || *endptr != '\0') {
+ if (!endptr || *endptr != '\0' || endptr == buff) {
fprintf(stderr, "Invalid throughput speed for %s: %s\n",
description, buff);
return false;
--- a/gw_mode.c
+++ b/gw_mode.c
@@ -89,6 +89,7 @@ static int parse_gw_limit(char *buff)
static int parse_gw(struct state *state, int argc, char *argv[])
{
+ unsigned long sel_class;
char buff[256];
char *endptr;
int ret;
@@ -130,11 +131,14 @@ static int parse_gw(struct state *state,
&gw_globals.sel_class))
return -EINVAL;
} else {
- gw_globals.sel_class = strtoul(buff, &endptr, 0);
- if (!endptr || *endptr != '\0') {
+ sel_class = strtoul(buff, &endptr, 0);
+ if (!endptr || *endptr != '\0' || endptr == buff ||
+ sel_class > UINT32_MAX) {
fprintf(stderr, "Error - unexpected argument for mode \"client\": %s\n", buff);
return -EINVAL;
}
+
+ gw_globals.sel_class = sel_class;
}
gw_globals.sel_class_found = 1;
--- a/hop_penalty.c
+++ b/hop_penalty.c
@@ -22,6 +22,7 @@ static int parse_hop_penalty(struct stat
{
struct settings_data *settings = state->cmd->arg;
struct hop_penalty_data *data = settings->data;
+ unsigned long hop_penalty;
char *endptr;
if (argc != 2) {
@@ -29,12 +30,14 @@ static int parse_hop_penalty(struct stat
return -EINVAL;
}
- data->hop_penalty = strtoul(argv[1], &endptr, 0);
- if (!endptr || *endptr != '\0') {
+ hop_penalty = strtoul(argv[1], &endptr, 0);
+ if (!endptr || *endptr != '\0' || endptr == argv[1] || hop_penalty > UINT8_MAX) {
fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]);
return -EINVAL;
}
+ data->hop_penalty = hop_penalty;
+
return 0;
}
--- a/isolation_mark.c
+++ b/isolation_mark.c
@@ -23,10 +23,10 @@ static int parse_isolation_mark(struct s
{
struct settings_data *settings = state->cmd->arg;
struct isolation_mark_data *data = settings->data;
+ unsigned long mark;
+ unsigned long mask;
char *mask_ptr;
char buff[256];
- uint32_t mark;
- uint32_t mask;
char *endptr;
if (argc != 2) {
@@ -50,13 +50,13 @@ static int parse_isolation_mark(struct s
* bitmask and not a prefix length
*/
mask = strtoul(mask_ptr, &endptr, 16);
- if (!endptr || *endptr != '\0')
+ if (!endptr || *endptr != '\0' || endptr == mask_ptr || mask > UINT32_MAX)
goto inval_format;
}
/* the mark can be entered in any base */
mark = strtoul(buff, &endptr, 0);
- if (!endptr || *endptr != '\0')
+ if (!endptr || *endptr != '\0' || endptr == buff || mark > UINT32_MAX)
goto inval_format;
data->isolation_mask = mask;
--- a/multicast_fanout.c
+++ b/multicast_fanout.c
@@ -22,6 +22,7 @@ static int parse_multicast_fanout(struct
{
struct settings_data *settings = state->cmd->arg;
struct multicast_fanout_data *data = settings->data;
+ unsigned long multicast_fanout;
char *endptr;
if (argc != 2) {
@@ -29,12 +30,14 @@ static int parse_multicast_fanout(struct
return -EINVAL;
}
- data->multicast_fanout = strtoul(argv[1], &endptr, 0);
- if (!endptr || *endptr != '\0') {
+ multicast_fanout = strtoul(argv[1], &endptr, 0);
+ if (!endptr || *endptr != '\0' || endptr == argv[1] || multicast_fanout > UINT32_MAX) {
fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]);
return -EINVAL;
}
+ data->multicast_fanout = multicast_fanout;
+
return 0;
}
--- a/orig_interval.c
+++ b/orig_interval.c
@@ -22,6 +22,7 @@ static int parse_orig_interval(struct st
{
struct settings_data *settings = state->cmd->arg;
struct orig_interval_data *data = settings->data;
+ unsigned long orig_interval;
char *endptr;
if (argc != 2) {
@@ -29,12 +30,14 @@ static int parse_orig_interval(struct st
return -EINVAL;
}
- data->orig_interval = strtoul(argv[1], &endptr, 0);
- if (!endptr || *endptr != '\0') {
+ orig_interval = strtoul(argv[1], &endptr, 0);
+ if (!endptr || *endptr != '\0' || endptr == argv[1] || orig_interval > UINT32_MAX) {
fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]);
return -EINVAL;
}
+ data->orig_interval = orig_interval;
+
return 0;
}
@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:04:11 +0200
Subject: batctl: bat-hosts: free bat_host when hash_add fails
If the hash_add fails (OOM or duplicated entry), then the allocated
bat_host would leak. The user would also not be informed about this
problem.
Check the return value and handle the error to make this problem visible to
the user.
Fixes: c7c76f63c1f9 ("[batctl] integrating batman hash implementation / move bat-hosts stuff into an extra set of files")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=a48555e14dacb99eeb31cde8c88d27a5cf67a456
--- a/bat-hosts.c
+++ b/bat-hosts.c
@@ -123,7 +123,14 @@ static void parse_hosts_file(struct hash
strncpy(bat_host->name, name, HOST_NAME_MAX_LEN);
bat_host->name[HOST_NAME_MAX_LEN - 1] = '\0';
- hash_add(*hash, bat_host);
+ if (hash_add(*hash, bat_host) < 0) {
+ if (read_opt & USE_BAT_HOSTS)
+ fprintf(stderr,
+ "Error - could not add bat host: %s\n",
+ name);
+ free(bat_host);
+ continue;
+ }
if ((*hash)->elements * 4 > (*hash)->size) {
swaphash = hash_resize((*hash), (*hash)->size * 2);
@@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:12:56 +0200
Subject: batctl: dat_cache: fix multicast/unicast filter for MAC address
The -u/-m filters in the DAT cache callback test addr[0], but addr in this
callback is function is the text representation of the mac address - not
the binary representation like in all other functions. The binary check of
the multicast-bit will therefore not correctly identify multicast entries.
The kernel reply BATADV_ATTR_DAT_CACHE_HWADDRESS has to be checked instead.
Fixes: d8dd1ff1a0fe ("batctl: Use netlink to replace some of debugfs")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=c664029d507daf261a55e30be53929a69b07538b
--- a/dat_cache.c
+++ b/dat_cache.c
@@ -77,10 +77,10 @@ static int dat_cache_callback(struct nl_
last_seen_msecs = last_seen_msecs % 60000;
last_seen_secs = last_seen_msecs / 1000;
- if (opts->read_opt & MULTICAST_ONLY && !(addr[0] & 0x01))
+ if (opts->read_opt & MULTICAST_ONLY && !(hwaddr[0] & 0x01))
return NL_OK;
- if (opts->read_opt & UNICAST_ONLY && (addr[0] & 0x01))
+ if (opts->read_opt & UNICAST_ONLY && (hwaddr[0] & 0x01))
return NL_OK;
printf(" * %15s ", addr);
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:51:06 +0200
Subject: batctl: isolation_mark: fix error message for invalid mark/mask values
When the mark or mask argument fails to parse, error message claims
"incorrect number of arguments (expected 1)" even though exactly one
argument was given.
Print the offending value and say that the format is invalid instead.
Fixes: a319ec4dcbff ("batctl: Support generic netlink for isolation_mark command")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=847e8a576b3b3abc64abf3044167b6bcd590c31a
--- a/isolation_mark.c
+++ b/isolation_mark.c
@@ -66,7 +66,8 @@ static int parse_isolation_mark(struct s
return 0;
inval_format:
- fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n");
+ fprintf(stderr, "Error - invalid isolation mark/mask format: %s\n",
+ argv[1]);
fprintf(stderr, "The following formats for mark(/mask) are allowed:\n");
fprintf(stderr, " * 0x12345678\n");
fprintf(stderr, " * 0x12345678/0xabcdef09\n");
@@ -0,0 +1,126 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:23:05 +0200
Subject: batctl: event: don't print timestamp prefix for skipped events
The timestamp is printed before the event is parsed. Each parse function
can still decide to skip the event without printing anything In these cases
a bare "1234.567890: " fragment without newline remains on the line and the
next event is appended to it, corrupting the output stream.
Format the timestamp into a prefix string instead and let the parse
functions print it together with their first line.
Fixes: 5d7850e3582e ("batctl: Add command to monitor for netlink events")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=eb4f3c97db42d6e85339385b758318b26f219870
--- a/event.c
+++ b/event.c
@@ -115,7 +115,7 @@ static const int tp_meter_mandatory[] =
BATADV_ATTR_TPMETER_RESULT,
};
-static void event_parse_tp_meter(struct nlattr **attrs)
+static void event_parse_tp_meter(struct nlattr **attrs, const char *prefix)
{
const char *result_str;
uint32_t cookie;
@@ -156,10 +156,10 @@ static void event_parse_tp_meter(struct
break;
}
- printf("tp_meter 0x%08x: %s\n", cookie, result_str);
+ printf("%stp_meter 0x%08x: %s\n", prefix, cookie, result_str);
}
-static void event_parse_set_mesh(struct nlattr **attrs)
+static void event_parse_set_mesh(struct nlattr **attrs, const char *prefix)
{
static const int mesh_mandatory[] = {
BATADV_ATTR_MESH_IFINDEX,
@@ -184,7 +184,7 @@ static void event_parse_set_mesh(struct
return;
}
- printf("%s: set mesh:\n", meshif_name);
+ printf("%s%s: set mesh:\n", prefix, meshif_name);
if (attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED])
printf("* aggregated_ogms %s\n",
@@ -292,7 +292,7 @@ static void event_parse_set_mesh(struct
nla_get_u32(attrs[BATADV_ATTR_ORIG_INTERVAL]));
}
-static void event_parse_set_hardif(struct nlattr **attrs)
+static void event_parse_set_hardif(struct nlattr **attrs, const char *prefix)
{
static const int hardif_mandatory[] = {
BATADV_ATTR_MESH_IFINDEX,
@@ -330,7 +330,7 @@ static void event_parse_set_hardif(struc
return;
}
- printf("%s (%s): set hardif:\n", meshif_name, hardif_name);
+ printf("%s%s (%s): set hardif:\n", prefix, meshif_name, hardif_name);
if (attrs[BATADV_ATTR_HOP_PENALTY])
printf("* hop_penalty %u\n",
@@ -349,7 +349,7 @@ static void event_parse_set_hardif(struc
}
}
-static void event_parse_set_vlan(struct nlattr **attrs)
+static void event_parse_set_vlan(struct nlattr **attrs, const char *prefix)
{
static const int vlan_mandatory[] = {
BATADV_ATTR_MESH_IFINDEX,
@@ -377,7 +377,7 @@ static void event_parse_set_vlan(struct
vid = nla_get_u16(attrs[BATADV_ATTR_VLANID]);
- printf("%s (vid %u): set vlan:\n", meshif_name, vid);
+ printf("%s%s (vid %u): set vlan:\n", prefix, meshif_name, vid);
if (attrs[BATADV_ATTR_AP_ISOLATION_ENABLED])
printf("* ap_isolation %s\n",
@@ -408,6 +408,7 @@ static int event_parse(struct nl_msg *ms
struct event_args *event_args = arg;
unsigned long long timestamp;
struct genlmsghdr *ghdr;
+ char prefix[32] = "";
if (!genlmsg_valid_hdr(nlh, 0))
return NL_OK;
@@ -422,24 +423,25 @@ static int event_parse(struct nl_msg *ms
if (event_args->mode != EVENT_TIME_NO) {
timestamp = get_timestamp(event_args);
- printf("%llu.%06llu: ", timestamp / 1000000, timestamp % 1000000);
+ snprintf(prefix, sizeof(prefix), "%llu.%06llu: ",
+ timestamp / 1000000, timestamp % 1000000);
}
switch (ghdr->cmd) {
case BATADV_CMD_TP_METER:
- event_parse_tp_meter(attrs);
+ event_parse_tp_meter(attrs, prefix);
break;
case BATADV_CMD_SET_MESH:
- event_parse_set_mesh(attrs);
+ event_parse_set_mesh(attrs, prefix);
break;
case BATADV_CMD_SET_HARDIF:
- event_parse_set_hardif(attrs);
+ event_parse_set_hardif(attrs, prefix);
break;
case BATADV_CMD_SET_VLAN:
- event_parse_set_vlan(attrs);
+ event_parse_set_vlan(attrs, prefix);
break;
default:
- printf("Received unknown event %u\n", ghdr->cmd);
+ printf("%sReceived unknown event %u\n", prefix, ghdr->cmd);
break;
}
@@ -0,0 +1,103 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:10:21 +0200
Subject: batctl: debug: avoid endless getopt loop for attached '-w' argument
The watch-mode "optinaparsing hack is not stable and breaks the assumptions
of getopt parsers. If something like "-w-" was specified as argument, then
the glibc and musl parsers would just cause an endless loop. And when no
argument was specified, an error "option requires an argument: w" was
always appearing.
It is better to use the optional parameter support which is directly
provided by glibc and musl:
batctl meshif bat0 originators -w
batctl meshif bat0 originators -w2.3
Fixes: e4a7b7733faf ("batctl: Add an optional interval for watch-mode")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=46aca094072a611ff41f353aa62d0d08e8c36c46
--- a/debug.c
+++ b/debug.c
@@ -27,7 +27,7 @@ static void debug_table_usage(struct sta
fprintf(stderr, " \t -h print this help\n");
fprintf(stderr, " \t -n don't replace mac addresses with bat-host names\n");
fprintf(stderr, " \t -H don't show the header\n");
- fprintf(stderr, " \t -w [interval] watch mode - refresh the table continuously\n");
+ fprintf(stderr, " \t -w[interval] watch mode - refresh the table continuously\n");
if (debug_table->option_timeout_interval)
fprintf(stderr, " \t -t timeout interval - don't print originators not seen for x.y seconds \n");
@@ -51,7 +51,8 @@ int handle_debug_table(struct state *sta
float watch_interval = 1;
int err;
- while ((optchar = getopt(argc, argv, "hnw:t:Humi:")) != -1) {
+ while ((optchar = getopt(argc, argv, "hnw::t:Humi:")) != -1) {
+ printf("%c\n", optchar);
switch (optchar) {
case 'h':
debug_table_usage(state);
@@ -61,10 +62,8 @@ int handle_debug_table(struct state *sta
break;
case 'w':
read_opt |= CLR_CONT_READ;
- if (optarg[0] == '-') {
- optind--;
+ if (!optarg)
break;
- }
if (!sscanf(optarg, "%f", &watch_interval)) {
fprintf(stderr, "Error - provided argument of '-%c' is not a number\n", optchar);
@@ -122,9 +121,6 @@ int handle_debug_table(struct state *sta
fprintf(stderr, "Error - option '-t' needs a number as argument\n");
} else if (optopt == 'i') {
fprintf(stderr, "Error - option '-i' needs an interface as argument\n");
- } else if (optopt == 'w') {
- read_opt |= CLR_CONT_READ;
- break;
}
else
fprintf(stderr, "Error - unrecognised option: '-%c'\n", optopt);
--- a/man/batctl.8
+++ b/man/batctl.8
@@ -380,27 +380,27 @@ is printed.
The local and global translation tables also support the "\-u" and "\-m" option to only display unicast or multicast translation table announcements respectively.
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBbackbonetable\fP|\fBbbt\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBbackbonetable\fP|\fBbbt\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP\fIinterval\fP]
(compile time option)
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBclaimtable\fP|\fBcl\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBclaimtable\fP|\fBcl\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP[\fIinterval\fP]]
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBdat_cache\fP|\fBdc\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBdat_cache\fP|\fBdc\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP[\fIinterval\fP]]
(compile time option)
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBgateways\fP|\fBgwl\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBgateways\fP|\fBgwl\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP[\fIinterval\fP]]
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBmcast_flags\fP|\fBmf\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBmcast_flags\fP|\fBmf\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP[\fIinterval\fP]]
(compile time option)
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBneighbors\fP|\fBn\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBneighbors\fP|\fBn\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP[\fIinterval\fP]]
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBoriginators\fP|\fBo\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP] [\fB-t\fP \fItimeout_interval\fP] [\fB-i\fP \fIinterface\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBoriginators\fP|\fBo\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP[\fIinterval\fP]] [\fB-t\fP \fItimeout_interval\fP] [\fB-i\fP \fIinterface\fP]
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBtransglobal\fP|\fBtg\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP] [\fB-u\fP] [\fB-m\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBtransglobal\fP|\fBtg\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP[\fIinterval\fP]] [\fB-u\fP] [\fB-m\fP]
(compile time option)
.TP
-[\fBmeshif\fP \fInetdev\fP] \fBtranslocal\fP|\fBtl\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP \fIinterval\fP] [\fB-u\fP] [\fB-m\fP]
+[\fBmeshif\fP \fInetdev\fP] \fBtranslocal\fP|\fBtl\fP [\fB-n\fP] [\fB-H\fP] [\fB-w\fP[\fIinterval\fP]] [\fB-u\fP] [\fB-m\fP]
.SH JSON QUERIES
@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 10:16:03 +0200
Subject: batctl: debug: use strict interval/timeout parsing
The sscanf() function does not only return 0 when the value could not be
parsed from the string. Also EOF is a potential return value. To make the
check more strict, just compare the returned value with the expected number
of scanned/parsed items.
Fixes: 302a41a73915 ("batctl: Add timeout filtering option for originators")
Fixes: e4a7b7733faf ("batctl: Add an optional interval for watch-mode")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=df40586930d6c864bde47b1cb42dbcf607f625bd
--- a/debug.c
+++ b/debug.c
@@ -65,7 +65,7 @@ int handle_debug_table(struct state *sta
if (!optarg)
break;
- if (!sscanf(optarg, "%f", &watch_interval)) {
+ if (sscanf(optarg, "%f", &watch_interval) != 1) {
fprintf(stderr, "Error - provided argument of '-%c' is not a number\n", optchar);
return EXIT_FAILURE;
}
@@ -78,7 +78,7 @@ int handle_debug_table(struct state *sta
}
read_opt |= NO_OLD_ORIGS;
- if (!sscanf(optarg, "%f", &orig_timeout)) {
+ if (sscanf(optarg, "%f", &orig_timeout) != 1) {
fprintf(stderr, "Error - provided argument of '-%c' is not a number\n", optchar);
return EXIT_FAILURE;
}
@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 13:57:02 +0200
Subject: batctl: debug: reject trailing garbage for intervals
A "%f" sscanf conversion stops at the first
character it cannot consume and reports success for the leading numeric
part, so trailing garbag are still accepted silently.
Append a "%c" conversion so any trailing character makes sscanf() report
more than the one expected item.
Fixes: 302a41a73915 ("batctl: Add timeout filtering option for originators")
Fixes: e4a7b7733faf ("batctl: Add an optional interval for watch-mode")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=543d4053c18efd58e79c91f567a348d7920cd434
--- a/debug.c
+++ b/debug.c
@@ -49,6 +49,7 @@ int handle_debug_table(struct state *sta
char *orig_iface = NULL;
float orig_timeout = 0.0f;
float watch_interval = 1;
+ char tmp;
int err;
while ((optchar = getopt(argc, argv, "hnw::t:Humi:")) != -1) {
@@ -65,7 +66,7 @@ int handle_debug_table(struct state *sta
if (!optarg)
break;
- if (sscanf(optarg, "%f", &watch_interval) != 1) {
+ if (sscanf(optarg, "%f%c", &watch_interval, &tmp) != 1) {
fprintf(stderr, "Error - provided argument of '-%c' is not a number\n", optchar);
return EXIT_FAILURE;
}
@@ -78,7 +79,7 @@ int handle_debug_table(struct state *sta
}
read_opt |= NO_OLD_ORIGS;
- if (sscanf(optarg, "%f", &orig_timeout) != 1) {
+ if (sscanf(optarg, "%f%c", &orig_timeout, &tmp) != 1) {
fprintf(stderr, "Error - provided argument of '-%c' is not a number\n", optchar);
return EXIT_FAILURE;
}
@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 14:10:31 +0200
Subject: batctl: debug: reject non-finite/negative interval/timeout values
A "%f" sscanf conversion accepts the textual floating point literals "nan",
"inf" and "infinity", and an out-of-range magnitude such as "1e9999" is
converted to infinity. There are calculations and comparisons performed
with the values. They must therefore be well defined non-negative and
finite numbers.
Fixes: 302a41a73915 ("batctl: Add timeout filtering option for originators")
Fixes: e4a7b7733faf ("batctl: Add an optional interval for watch-mode")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=b258fe1884c090a571d9881e76b04bac5a763007
--- a/debug.c
+++ b/debug.c
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <math.h>
#include "debug.h"
#include "functions.h"
@@ -66,8 +67,9 @@ int handle_debug_table(struct state *sta
if (!optarg)
break;
- if (sscanf(optarg, "%f%c", &watch_interval, &tmp) != 1) {
- fprintf(stderr, "Error - provided argument of '-%c' is not a number\n", optchar);
+ if (sscanf(optarg, "%f%c", &watch_interval, &tmp) != 1 ||
+ !isfinite(watch_interval) || watch_interval < 0) {
+ fprintf(stderr, "Error - provided argument of '-%c' is not a positive number\n", optchar);
return EXIT_FAILURE;
}
break;
@@ -79,8 +81,9 @@ int handle_debug_table(struct state *sta
}
read_opt |= NO_OLD_ORIGS;
- if (sscanf(optarg, "%f%c", &orig_timeout, &tmp) != 1) {
- fprintf(stderr, "Error - provided argument of '-%c' is not a number\n", optchar);
+ if (sscanf(optarg, "%f%c", &orig_timeout, &tmp) != 1 ||
+ !isfinite(orig_timeout) || orig_timeout < 0) {
+ fprintf(stderr, "Error - provided argument of '-%c' is not a positive number\n", optchar);
return EXIT_FAILURE;
}
break;
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:44:37 +0200
Subject: batctl: debug: don't return negative error codes from handle_debug_table
handle_debug_table() returns the result of the netlink dump function
directly. This is a negative errno code on failure and main() passes it
straight to exit(). The process then terminates with a mangled exit status
like 161 (-95 & 0xff).
Limit the return codes to EXIT_SUCCESS and EXIT_FAILURE.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=2f1b8b367ffab60b0f7f969bfc73c4a9b4bfc6d3
--- a/debug.c
+++ b/debug.c
@@ -146,5 +146,8 @@ int handle_debug_table(struct state *sta
err = debug_table->netlink_fn(state , orig_iface, read_opt,
orig_timeout, watch_interval);
- return err;
+ if (err < 0)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
}
@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 15:12:40 +0200
Subject: batctl: only mark file read successful on read line
The line_ptr is shared globally. It can happen that another function like
parse_hosts_file() allocated the buffer successfully. But the next
getline() in read_file() fails - but keeps the line_ptr valid. In this
case, the function would return a success - even when the buffer contains
stale data.
Instead only set the return value to EXIT_SUCCESS when a single line could
be read.
Fixes: deb324e65044 ("batctl: buffer based reading replaced by line-by-line reading")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=ef685613924fddb553369d41688c6c9ce4c7562b
--- a/functions.c
+++ b/functions.c
@@ -157,6 +157,8 @@ int read_file(const char *full_path, int
}
while (getline(&line_ptr, &len, fp) != -1) {
+ res = EXIT_SUCCESS;
+
/* the buffer will be handled elsewhere */
if (read_opt & USE_READ_BUFF)
break;
@@ -164,9 +166,6 @@ int read_file(const char *full_path, int
printf("%s", line_ptr);
}
- if (line_ptr)
- res = EXIT_SUCCESS;
-
fclose(fp);
return res;
}
@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:02:28 +0200
Subject: batctl: version: avoid use of uninitialized read buffer
version() strips the trailing newline from line_ptr before checking whether
read_file() actually succeeded. If the read_file() returned an error, it
could be that line_ptr was allocated buyt not yet initialized. It could
therefore not contain any \0 delimiter - making the strlen read outside the
buffer. The write of the \0 could therefore also be outside the buffer.
Only attempt to access the buffer when a success was indicated.
Fixes: dbc4a8c8e585 ("batctl: version also prints the kernel module version if available")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=f4d637a2ab51505d72d7b02735cecd990b22c7fb
--- a/main.c
+++ b/main.c
@@ -133,13 +133,14 @@ static void version(void)
printf("batctl %s [batman-adv: ", SOURCE_VERSION);
ret = read_file(module_ver_path, USE_READ_BUFF | SILENCE_ERRORS);
- if ((line_ptr) && (line_ptr[strlen(line_ptr) - 1] == '\n'))
- line_ptr[strlen(line_ptr) - 1] = '\0';
+ if (ret == EXIT_SUCCESS) {
+ if (line_ptr[strlen(line_ptr) - 1] == '\n')
+ line_ptr[strlen(line_ptr) - 1] = '\0';
- if (ret == EXIT_SUCCESS)
printf("%s]\n", line_ptr);
- else
+ } else {
printf("module not loaded]\n");
+ }
free(line_ptr);
exit(EXIT_SUCCESS);
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 14:58:06 +0200
Subject: batctl: version: don't strip newline for empty buffer
When read_file() would return an empty buffer, then version() must not
strip the last byte. Otherwise it would try to access 1 byte before the
start of the buffer.
Fixes: dbc4a8c8e585 ("batctl: version also prints the kernel module version if available")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=ce0fa8d53b62ee8f40d34dbd801a1e4b9e89a80a
--- a/main.c
+++ b/main.c
@@ -134,8 +134,10 @@ static void version(void)
ret = read_file(module_ver_path, USE_READ_BUFF | SILENCE_ERRORS);
if (ret == EXIT_SUCCESS) {
- if (line_ptr[strlen(line_ptr) - 1] == '\n')
- line_ptr[strlen(line_ptr) - 1] = '\0';
+ size_t line_len = strlen(line_ptr);
+
+ if (line_len > 0 && line_ptr[line_len - 1] == '\n')
+ line_ptr[line_len - 1] = '\0';
printf("%s]\n", line_ptr);
} else {
@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:23:44 +0200
Subject: batctl: interface: report rtnl query failures
print_interfaces() ignores the query_rtnl_link() result. When the rtnl
socket setup or the dump request fails, batctl interface prints nothing and
exits with EXIT_SUCCESS. This is indistinguishable from a
meshif without any slave interfaces.
Check the result and fail with an error message instead.
Fixes: 60e519bfeaa3 ("batctl: Use rtnl to query list of softif devices")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=7d9bfae7a98603bd45f5e9261b10eff71a7634f4
--- a/interface.c
+++ b/interface.c
@@ -170,11 +170,17 @@ static int print_interfaces(struct state
if (ret < 0)
return EXIT_FAILURE;
- query_rtnl_link(state->mesh_ifindex, print_interfaces_rtnl_parse,
- state);
+ ret = query_rtnl_link(state->mesh_ifindex, print_interfaces_rtnl_parse,
+ state);
netlink_destroy(state);
+ if (ret < 0) {
+ fprintf(stderr, "Error - could not query interfaces: %s\n",
+ strerror(-ret));
+ return EXIT_FAILURE;
+ }
+
return EXIT_SUCCESS;
}
@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 08:12:11 +0200
Subject: batctl: interface: return fail for non-existing interface
The add/del loop skips a non-existent interface name with a plain continue
and returns a success when no other error class was detected. Which causes
scripts (depending on the return value) to miss the problem.
Remember that a name could not be resolved and return EXIT_FAILURE at
the end, while still processing the remaining interfaces.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=6fd8c94dc36c36bc2c8e9e8a8e9a3e67afd588f5
--- a/interface.c
+++ b/interface.c
@@ -414,6 +414,7 @@ err_free_msg:
static int interface(struct state *state, int argc, char **argv)
{
struct interface_create_params create_params = {};
+ bool iface_error = false;
int i, optchar;
int ret;
unsigned int ifindex;
@@ -548,6 +549,7 @@ static int interface(struct state *state
if (!ifindex) {
fprintf(stderr, "Error - interface does not exist: %s\n", rest_argv[i]);
+ iface_error = true;
continue;
}
@@ -577,6 +579,9 @@ static int interface(struct state *state
state->mesh_iface, state->mesh_iface);
}
+ if (iface_error)
+ return EXIT_FAILURE;
+
return EXIT_SUCCESS;
err:
@@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 14:32:25 +0200
Subject: batctl: translate: don't overwrite the search key
translate_mac_netlink_cb() walks the whole global translation table dump
and searches for an originator address for the provided TT mac address. It
stored that originator back into opts->mac (used for the search key). But
since NL_STOP is no longer used, it might continue to traverse the
translation table but would now use the wrong search key.
Split ethernet address in search key and result field to avoid this
confusion.
Fixes: e2a3d3599cb2 ("batctl: Use common genl socket for netlink_query_common")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=7eb2f4b811d13b8d0c9860867822268a2fc1bf64
--- a/netlink.c
+++ b/netlink.c
@@ -688,7 +688,8 @@ static const int translate_mac_netlink_m
};
struct translate_mac_netlink_opts {
- struct ether_addr mac;
+ struct ether_addr search;
+ struct ether_addr result;
uint8_t found:1;
struct nlquery_opts query_opts;
};
@@ -729,10 +730,10 @@ static int translate_mac_netlink_cb(stru
if (!attrs[BATADV_ATTR_FLAG_BEST])
return NL_OK;
- if (memcmp(&opts->mac, addr, ETH_ALEN) != 0)
+ if (memcmp(&opts->search, addr, ETH_ALEN) != 0)
return NL_OK;
- memcpy(&opts->mac, orig, ETH_ALEN);
+ memcpy(&opts->result, orig, ETH_ALEN);
opts->found = true;
opts->query_opts.err = 0;
@@ -750,7 +751,7 @@ int translate_mac_netlink(struct state *
};
int ret;
- memcpy(&opts.mac, mac, ETH_ALEN);
+ memcpy(&opts.search, mac, ETH_ALEN);
ret = netlink_query_common(state, state->mesh_ifindex,
BATADV_CMD_GET_TRANSTABLE_GLOBAL,
@@ -762,7 +763,7 @@ int translate_mac_netlink(struct state *
if (!opts.found)
return -ENOENT;
- memcpy(mac_out, &opts.mac, ETH_ALEN);
+ memcpy(mac_out, &opts.result, ETH_ALEN);
return 0;
}
@@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:06:19 +0200
Subject: batctl: genl_json: avoid negative chars in sanitize_string
char is signed on common platforms. Passing a "negative" string byte to
isprint() is undefined behavior when it is not EOF. The manpage for isprint
is therefore requesting to provide the argument as unsigned char.
Fixes: ae1a3d3f0bb7 ("batctl: genl_json: Add generic JSON interface")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=1db9b42918f4ef9f7b4f0cb070fb486cc3e543f4
--- a/genl_json.c
+++ b/genl_json.c
@@ -33,16 +33,18 @@ struct nla_policy_json {
static void sanitize_string(const char *str)
{
- while (*str) {
- if (*str == '"' || *str == '\\') {
+ const unsigned char *c = (const unsigned char *)str;
+
+ while (*c) {
+ if (*c == '"' || *c == '\\') {
putchar('\\');
- putchar(*str);
- } else if (!isprint(*str)) {
- printf("\\x%02x", *str);
+ putchar(*c);
+ } else if (!isprint(*c)) {
+ printf("\\x%02x", *c);
} else {
- putchar(*str);
+ putchar(*c);
}
- str++;
+ c++;
}
}
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:08:10 +0200
Subject: batctl: genl_json: reject unknown options in handle_json_query
Print the usage and return a failure for unknown options.
Fixes: 57cc3c472a7d ("batctl: Introduce handler for JSON_* command types")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=ff9bd36e6d77c412efb504e140c708b6c99fba23
--- a/genl_json.c
+++ b/genl_json.c
@@ -597,6 +597,9 @@ int handle_json_query(struct state *stat
case 'h':
json_query_usage(state);
return EXIT_SUCCESS;
+ default:
+ json_query_usage(state);
+ return EXIT_FAILURE;
}
}
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:45:15 +0200
Subject: batctl: genl_json: don't return negative error codes to main
handle_json_query() returns the result of netlink_print_query_json()
directly. This is a negative errno code on failure and main() passes it
straight to exit(). The process then terminates with a mangled exit status
like 161 (-95 & 0xff).
Limit the return codes to EXIT_SUCCESS and EXIT_FAILURE.
Fixes: 57cc3c472a7d ("batctl: Introduce handler for JSON_* command types")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=baeb0179229295c74c1f2a56bea5c3292037350a
--- a/genl_json.c
+++ b/genl_json.c
@@ -606,6 +606,8 @@ int handle_json_query(struct state *stat
check_root_or_die("batctl");
err = netlink_print_query_json(state, json_query);
+ if (err < 0)
+ return EXIT_FAILURE;
- return err;
+ return EXIT_SUCCESS;
}
@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:45:43 +0200
Subject: batctl: genl_json: escape non-printable characters as valid JSON
sanitize_string() emits non-printable bytes as \xNN inside JSON string
values. JSON only allows the escape sequences \" \\ \/ \b \f \n \r \t and
\uXXXX. The latter is the correct option for printing arbitrary character
values.
Fixes: ae1a3d3f0bb7 ("batctl: genl_json: Add generic JSON interface")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=f81c512c9d71b2acaee88a2a7510d4a309825390
--- a/genl_json.c
+++ b/genl_json.c
@@ -40,7 +40,7 @@ static void sanitize_string(const char *
putchar('\\');
putchar(*c);
} else if (!isprint(*c)) {
- printf("\\x%02x", *c);
+ printf("\\u%04x", *c);
} else {
putchar(*c);
}
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 12:24:05 +0200
Subject: batctl: genl_json: drop leftover network coding log level
Support for the network coding feature was removed from batctl but missed
in the genl_json loglevel output.
Fixes: 882ab0d91468 ("batctl: remove support for network coding")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=96b0c7dc42e8cf4a4fecaa57ad0aa94598aa3ceb
--- a/genl_json.c
+++ b/genl_json.c
@@ -219,8 +219,6 @@ static void nljson_print_loglevel(struct
val & BIT(3) ? "true" : "false");
printf("\"dat\": %s,",
val & BIT(4) ? "true" : "false");
- printf("\"nc\": %s,",
- val & BIT(5) ? "true" : "false");
printf("\"mcast\": %s,",
val & BIT(6) ? "true" : "false");
printf("\"tp\": %s,",
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 07:01:53 +0200
Subject: batctl: tcpdump: fix "subtybe" typo in 4ADDR output
The unicast-4addr packet dump prints the field label as "subtybe"
instead of "subtype".
Fixes: 02921f7519a2 ("batctl: tcpdump - print subtype for UNICAST4ADDR packets")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=8e911500ff96ddec47e53b66cf7613f918a4fbcb
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1152,7 +1152,7 @@ static void dump_batman_4addr(unsigned c
printf("BAT %s > ",
get_name_by_macaddr((struct ether_addr *)ether_header->ether_shost, read_opt));
- printf("%s: 4ADDR, subtybe %hhu, ttvn %d, ttl %hhu, ",
+ printf("%s: 4ADDR, subtype %hhu, ttvn %d, ttl %hhu, ",
get_name_by_macaddr((struct ether_addr *)unicast_4addr_packet->u.dest, read_opt),
unicast_4addr_packet->subtype, unicast_4addr_packet->u.ttvn,
unicast_4addr_packet->u.ttl);
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:47:02 +0200
Subject: batctl: tcpdump: return EXIT_SUCCESS on normal termination
The main capture loop of tcpdump ends when SIGINT/SIGTERM sets
is_aborted. In this case, the return value should reflect this clean
shutdown.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=e8629a0e169e44c3f9fa7f12cc5a8eadb07ea89a
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1562,6 +1562,8 @@ static int tcpdump(struct state *state _
}
+ ret = EXIT_SUCCESS;
+
out:
list_for_each_entry_safe(dump_if, dump_if_tmp, &dump_if_list, list) {
if (dump_if->raw_sock >= 0)
@@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:09:12 +0200
Subject: batctl: tcpdump: check frame length before reading the ethernet header
parse_eth_hdr() reads ether_type without checking that the buffer actually
contains a complete ethernet header. Use an header length check like in all
other functions.
Fixes: 3bdfc388e74b ("implement simple tcpdump, first only batman packets")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=e69b8fefded470adbb952d0c6a0ac6dd6c9d88b2
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1167,6 +1167,8 @@ static void parse_eth_hdr(unsigned char
struct batadv_ogm_packet *batman_ogm_packet;
struct ether_header *eth_hdr;
+ LEN_CHECK(buff_len, sizeof(*eth_hdr), "ETH HEADER");
+
eth_hdr = (struct ether_header *)packet_buff;
switch (ntohs(eth_hdr->ether_type)) {
@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 14:19:06 +0200
Subject: batctl: tcpdump: resolve bat-host name for ROAMv1 client
Every packet parser in tcpdump forwards its read_opt argument to
get_name_by_macaddr(), which only consults the bat-hosts table when
read_opt carries USE_BAT_HOSTS. This was (without reason) not done in the
TVLV ROAMv1 parser and the NO_FLAGS is hardcoded for the
get_name_by_macaddr().
Just forward the read_opts flags like in all other functions to have the
same user experience.
Fixes: 4c39fb823b86 ("batctl: tcpdump - parse TVLV containers")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=6bf0ae6d831bdd1743a4f0bdafbbc8e04bf3dd3d
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -191,7 +191,7 @@ static void batctl_tvlv_parse_tt_v1(void
}
static void batctl_tvlv_parse_roam_v1(void *buff, ssize_t buff_len,
- int read_opt __maybe_unused)
+ int read_opt)
{
struct batadv_tvlv_roam_adv *tvlv = buff;
@@ -202,7 +202,7 @@ static void batctl_tvlv_parse_roam_v1(vo
}
printf("\tTVLV ROAMv1: client %s, VLAN ID %d\n",
- get_name_by_macaddr((struct ether_addr *)tvlv->client, NO_FLAGS),
+ get_name_by_macaddr((struct ether_addr *)tvlv->client, read_opt),
BATADV_PRINT_VID(ntohs(tvlv->vid)));
}
@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 07:01:01 +0200
Subject: batctl: tcpdump: print the unreachable host for ICMP port unreachable
When decoding an ICMP port-unreachable message, tcpdump prints the
destination of the ICMP repply packet. The actual relevant IP (the original
destination) is only in the inner IP header.
The destinatin IP from the already validated tmp_udphdr must be used
instead.
Fixes: f08a28dcffb1 ("batctl: tcpdump - fix IP header parsing")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=26e7eb43e8422810f941f5afb7ed0e4046226b10
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -697,6 +697,7 @@ static void dump_ip(unsigned char *packe
char ipsrc[INET_ADDRSTRLEN], ipdst[INET_ADDRSTRLEN];
struct iphdr *iphdr, *tmp_iphdr;
const char ip_string[] = "IP";
+ char ipinner[INET_ADDRSTRLEN];
struct udphdr *tmp_udphdr;
struct icmphdr *icmphdr;
@@ -749,9 +750,15 @@ static void dump_ip(unsigned char *packe
tmp_udphdr = (struct udphdr *)(((char *)tmp_iphdr) + (tmp_iphdr->ihl * 4));
+ if (!inet_ntop(AF_INET, &tmp_iphdr->daddr, ipinner,
+ sizeof(ipinner))) {
+ fprintf(stderr, "Cannot decode unreachable destination IP\n");
+ return;
+ }
+
printf("%s: ICMP ", ipdst);
printf("%s udp port %hu unreachable, length %zu\n",
- ipdst, ntohs(tmp_udphdr->dest),
+ ipinner, ntohs(tmp_udphdr->dest),
(size_t)buff_len - (iphdr->ihl * 4));
break;
default:
@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 07:01:29 +0200
Subject: batctl: tcpdump: skip partial line for oversized ICMPv6 errors
dump_ipv6() prints the "IP6 <src> > <dst> " line prefix before it checks
whether an ICMPv6 error message exceeds IPV6_MIN_MTU. The length check
might just stop the processing and causes some truncated output on stdout.
Which is then also not terminated by a newline.
Move the size check ahead of the printf to avoid this partial line.
Fixes: 35b37756f4a3 ("add IPv6 support to tcpdump parser")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=d5a305d7c8c8aa2b18233aa16a332cf4ac1f0a78
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -605,7 +605,6 @@ static void dump_ipv6(unsigned char *pac
icmphdr = (struct icmp6_hdr *)(packet_buff +
sizeof(struct ip6_hdr));
- printf("%s %s > %s ", ip_string, ipsrc, ipdst);
if (icmphdr->icmp6_type < ICMP6_INFOMSG_MASK &&
(size_t)(buff_len) > IPV6_MIN_MTU) {
fprintf(stderr,
@@ -614,6 +613,7 @@ static void dump_ipv6(unsigned char *pac
return;
}
+ printf("%s %s > %s ", ip_string, ipsrc, ipdst);
printf("ICMP6");
switch (icmphdr->icmp6_type) {
case ICMP6_DST_UNREACH:
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 07:02:41 +0200
Subject: batctl: tcpdump: don't label unknown ICMPv6 types as unreachable
The default case of the ICMPv6 type switch prints ", destination
unreachable, unknown icmp6 type (N)". Every ICMPv6 type that is not
explicitly handled is therefore mislabelled as a destination unreachable
message.
Just report "unknown icmp6 type" instead.
Fixes: 35b37756f4a3 ("add IPv6 support to tcpdump parser")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=020ccec918cbd7ab0da0d0988b49f515e711bbfe
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -673,7 +673,7 @@ static void dump_ipv6(unsigned char *pac
nd_nas_target, buff_len);
break;
default:
- printf(", destination unreachable, unknown icmp6 type (%u)\n",
+ printf(", unknown icmp6 type (%u)\n",
icmphdr->icmp6_type);
break;
}
@@ -0,0 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 11:48:47 +0200
Subject: batctl: tcpdump: reject invalid packet type arguments
The strtol error handling is rather complicated and it is not only about
checking the return value. The possible error indicators are:
* endptr is NULL
* endptr is not pointing to end delimiter
* endptr is pointing at nptr (because it might have been an empty string)
* returned value is larger/smaller than the expected maximum/minimum value
range
The first tree conditions were not checked even when it is a potential
problem for multiple places. And the user was never informed about the
parsing errors. The old value was simply used.
Perform the needed validation steps and stop with an user readable error on
parsing problems. At the same time, switch to the unsigned number parsing
function strtoul because no negative numbers are allowed as inputs.
Fixes: fca4ef98aa99 ("change mac convert functions, add icmp packet output")
Fixes: c6ed60c0f6fd ("batctl: tcpdump - add option to select all packet types except specified")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=9cefbc4c37969c5502494ee68e72381a1694eb8a
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1453,7 +1453,9 @@ static int tcpdump(struct state *state _
struct list_head dump_if_list;
fd_set wait_sockets, tmp_wait_sockets;
ssize_t read_len;
- int ret = EXIT_FAILURE, res, optchar, max_sock = 0, tmp;
+ unsigned long tmp;
+ char *endptr;
+ int ret = EXIT_FAILURE, res, optchar, max_sock = 0;
int read_opt = USE_BAT_HOSTS;
unsigned char packet_buff[2000];
int monitor_header_len = -1;
@@ -1472,14 +1474,28 @@ static int tcpdump(struct state *state _
read_opt &= ~USE_BAT_HOSTS;
break;
case 'p':
- tmp = strtol(optarg, NULL , 10);
- if ((tmp > 0) && (tmp <= dump_level_all))
- dump_level = tmp;
+ tmp = strtoul(optarg, &endptr, 10);
+ if (!endptr || *endptr != '\0' || endptr == optarg ||
+ tmp == 0 || tmp > dump_level_all) {
+ fprintf(stderr,
+ "Error - the supplied packet type is invalid: %s\n",
+ optarg);
+ tcpdump_usage();
+ return EXIT_FAILURE;
+ }
+ dump_level = tmp;
break;
case 'x':
- tmp = strtol(optarg, NULL , 10);
- if ((tmp > 0) && (tmp <= dump_level_all))
- dump_level &= ~tmp;
+ tmp = strtoul(optarg, &endptr, 10);
+ if (!endptr || *endptr != '\0' || endptr == optarg ||
+ tmp == 0 || tmp > dump_level_all) {
+ fprintf(stderr,
+ "Error - the supplied packet type is invalid: %s\n",
+ optarg);
+ tcpdump_usage();
+ return EXIT_FAILURE;
+ }
+ dump_level &= ~tmp;
break;
default:
tcpdump_usage();
@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:46:13 +0200
Subject: batctl: tcpdump: fix source address selection for 802.11 data frames
For non-AMSDU data frame, we need to select as source host:
* neither from/to DS: addr2
* from DS: addr3
* to DS: addr2
* from+to DS: addr4
But the code is actually selecting:
* neither from/to DS: addr2
* from DS: addr3
* to DS: addr4
* from+to DS: addr3
Instead of checking single bits, the special cases "from+to DS" and "from
DS" have to be checked separately.
Fixes: 5143e351a77b ("batctl: add raw wifi packet decapsulation support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=980ed5d0bb53d6552bcc0be522d6327bf298b4b7
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1319,10 +1319,10 @@ static void parse_wifi_hdr(unsigned char
return;
shost = wifi_hdr->addr2;
- if (fc & IEEE80211_FCTL_FROMDS)
- shost = wifi_hdr->addr3;
- else if (fc & IEEE80211_FCTL_TODS)
+ if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
shost = wifi_hdr->addr4;
+ else if (fc & IEEE80211_FCTL_FROMDS)
+ shost = wifi_hdr->addr3;
dhost = wifi_hdr->addr1;
if (fc & IEEE80211_FCTL_TODS)
@@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 07:14:35 +0200
Subject: batctl: traceroute: return EXIT_NOSUCCESS when destination not reached
traceroute sets ret to EXIT_SUCCESS unconditionally once the probe loop
finishes. dst_reached is only set on an actual echo reply, so when the
target never answers within TTL_MAX hops, it is unreachable or all
probes time out. But this information is ignored when traceroute exits. A
script will not be able to distinguish a failed and working traceroute.
Use the same error codes as the ping but make it depend on the dst_reached
variable.
Fixes: e1c83d9260e8 ("[batctl] traceroute utility updated to latest batman adv")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=68e764875f9e9cb0652b0729ba408e0de43e5642
--- a/traceroute.c
+++ b/traceroute.c
@@ -202,7 +202,10 @@ read_packet:
printf("\n");
}
- ret = EXIT_SUCCESS;
+ if (dst_reached)
+ ret = EXIT_SUCCESS;
+ else
+ ret = EXIT_NOSUCCESS;
out:
icmp_interfaces_clean();
@@ -0,0 +1,76 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:12:03 +0200
Subject: batctl: icmp_helper: return proper errno on syscall failures
icmp_interface_send(), icmp_interface_read() and icmp_interface_filter()
return the raw syscall results. On failure this is -1 while the callers
interpret negative values as negative errno codes: ping and traceroute
print strerror(-res) and thus always report "Operation not permitted" no
matter why the send, receive or filter setup actually failed (for example
ENETDOWN when the interface goes down mid-ping or ENOMEM when attaching the
socket filter). The other error paths of these functions already return
proper negative errno values.
Convert the syscall failures to -errno before returning them.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=3c6156ecf602e5c135318bac60618046b5c862d5
--- a/icmp_helper.c
+++ b/icmp_helper.c
@@ -153,7 +153,7 @@ static int icmp_interface_filter(int soc
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter,
sizeof(filter)))
- return -1;
+ return -errno;
return 0;
}
@@ -340,6 +340,7 @@ static int icmp_interface_send(struct ba
{
struct ether_header header;
struct iovec vector[2];
+ ssize_t ret;
header.ether_type = htons(ETH_P_BATMAN);
memcpy(header.ether_shost, iface->mac, ETH_ALEN);
@@ -350,7 +351,11 @@ static int icmp_interface_send(struct ba
vector[1].iov_base = icmp_packet;
vector[1].iov_len = packet_len;
- return (int)writev(iface->sock, vector, 2);
+ ret = writev(iface->sock, vector, 2);
+ if (ret < 0)
+ return -errno;
+
+ return (int)ret;
}
int icmp_interface_write(struct state *state,
@@ -486,9 +491,12 @@ retry:
max_sock = icmp_interface_preselect(&read_sockets);
res = select(max_sock, &read_sockets, NULL, NULL, tv);
- /* timeout, or < 0 error */
- if (res <= 0)
- return res;
+ if (res < 0)
+ return -errno;
+
+ /* timeout */
+ if (res == 0)
+ return 0;
read_sock = icmp_interface_get_read_sock(&read_sockets, &iface);
if (read_sock < 0)
@@ -501,7 +509,7 @@ retry:
read_len = readv(read_sock, vector, 2);
if (read_len < 0)
- return read_len;
+ return -errno;
if (read_len < ETH_HLEN)
goto retry;
@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 13:31:32 +0200
Subject: batctl: ping: count sent and not received pings
packets_out was increased whenever a read of a packet was started. But the
read was repeated whenever the sequence number of a received packet was
incorrect. The packets_out would then be higher then the actual sent ones.
Fixes: 2474249a6312 ("[batctl] ping utility updated to latest batman adv")
Fixes: 2ecb2c8b060b ("batctl: tr / ping - ignore packets with wrong sequence number")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=714c6b0ff18a7fc1e7d2c547d0142ad639a40946
--- a/ping.c
+++ b/ping.c
@@ -180,6 +180,8 @@ static int ping(struct state *state, int
goto sleep;
}
+ packets_out++;
+
read_packet:
start_timer();
@@ -189,8 +191,6 @@ read_packet:
if (is_aborted)
break;
- packets_out++;
-
if (read_len == 0) {
printf("Reply from host %s timed out\n", dst_string);
goto sleep;
@@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:16:41 +0200
Subject: batctl: ping/traceroute: don't restart RTT timer on stray replies
When a reply with an unexpected seqno arrives (for example a late answer to
an already timed out request), ping and traceroute jump back to read_packet
to keep waiting for the real answer. The jump target also re-runs
start_timer(), so the reported round trip time only measures from the
arrival of the stray packet instead of from the transmission of the
request, underreporting the RTT and polluting the min/avg/max statistics.
Start the timer (and initialize the timeout in traceroute) once per
transmitted request. At the same time, let select in icmp_interface_read()
the wait time instead of restarting it each time.
Fixes: 2ecb2c8b060b ("batctl: tr / ping - ignore packets with wrong sequence number")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=8983dc388306906afb1b951b11fb9b6395feed8e
--- a/ping.c
+++ b/ping.c
@@ -182,9 +182,9 @@ static int ping(struct state *state, int
packets_out++;
-read_packet:
start_timer();
+read_packet:
read_len = icmp_interface_read((struct batadv_icmp_header *)&icmp_packet_in,
packet_len, &tv);
--- a/traceroute.c
+++ b/traceroute.c
@@ -132,12 +132,12 @@ static int traceroute(struct state *stat
continue;
}
-read_packet:
start_timer();
tv.tv_sec = 2;
tv.tv_usec = 0;
+read_packet:
read_len = icmp_interface_read((struct batadv_icmp_header *)&icmp_packet_in,
sizeof(icmp_packet_in), &tv);
if (read_len <= 0)
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:17:12 +0200
Subject: batctl: traceroute: probe the advertised maximum number of hops
The hop loop stops when the TTL reaches TTL_MAX, so only 49 hops are probed
while the header line announces "50 hops max". A destination which is
exactly TTL_MAX hops away is reported as unreachable even though the last
probe was never sent.
Run the loop up to and including TTL_MAX.
Fixes: e1c83d9260e8 ("[batctl] traceroute utility updated to latest batman adv")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=718db5633200bfe312b89598d32360b854e3e6b4
--- a/traceroute.c
+++ b/traceroute.c
@@ -114,7 +114,7 @@ static int traceroute(struct state *stat
dst_string, mac_string, TTL_MAX, sizeof(icmp_packet_out));
for (icmp_packet_out.ttl = 1;
- !dst_reached && icmp_packet_out.ttl < TTL_MAX;
+ !dst_reached && icmp_packet_out.ttl <= TTL_MAX;
icmp_packet_out.ttl++) {
return_mac = NULL;
bat_host = NULL;
@@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 13:55:09 +0200
Subject: batctl: ping: reject invalid packet count argument
The -c option parsed its argument with strtol and only mapped the result to
the internal "endless" value when it was smaller than 1. But it ignores any
invalid parameter silently. The manpage also only documented the "missing
-c" as valid selection of the endless loop and not an invalid or smaller
than 1 value.
Use the same strto* validation as the rest of batctl and print a user
readable error in case of an parsing error.
Fixes: 87ade2869cf3 ("add interval and loop count options")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=73c9bb12e9114e265b42118c0f09a93517d7d90d
--- a/ping.c
+++ b/ping.c
@@ -10,6 +10,7 @@
#include <netinet/in.h>
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -73,13 +74,22 @@ static int ping(struct state *state, int
uint8_t last_rr_cur = 0, last_rr[BATADV_RR_LEN][ETH_ALEN];
size_t packet_len;
int disable_translate_mac = 0;
+ char *endptr;
+ long tmp;
while ((optchar = getopt(argc, argv, "hc:i:t:RT")) != -1) {
switch (optchar) {
case 'c':
- loop_count = strtol(optarg, NULL , 10);
- if (loop_count < 1)
- loop_count = -1;
+ tmp = strtol(optarg, &endptr, 10);
+ if (!endptr || *endptr != '\0' || endptr == optarg ||
+ tmp < 1 || tmp > INT_MAX) {
+ fprintf(stderr,
+ "Error - the supplied packet count is invalid: %s\n",
+ optarg);
+ ping_usage();
+ return EXIT_FAILURE;
+ }
+ loop_count = tmp;
break;
case 'h':
ping_usage();
@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 13:55:32 +0200
Subject: batctl: ping: reject invalid timeout argument
The -t option parses its argument with strtol and defines a lower limit of
1. But it ignores any invalid parameter silently.
Use the same strto* validation as the rest of batctl and print a user
readable error in case of an parsing error.
Fixes: 2474249a6312 ("[batctl] ping utility updated to latest batman adv")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=8e57d0baeb34016165b6690298e7e06006f8fea9
--- a/ping.c
+++ b/ping.c
@@ -100,9 +100,16 @@ static int ping(struct state *state, int
loop_interval = 1;
break;
case 't':
- timeout = strtol(optarg, NULL , 10);
- if (timeout < 1)
- timeout = 1;
+ tmp = strtol(optarg, &endptr, 10);
+ if (!endptr || *endptr != '\0' || endptr == optarg ||
+ tmp < 1 || tmp > INT_MAX) {
+ fprintf(stderr,
+ "Error - the supplied timeout is invalid: %s\n",
+ optarg);
+ ping_usage();
+ return EXIT_FAILURE;
+ }
+ timeout = tmp;
break;
case 'R':
rr = 1;
@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 07:14:59 +0200
Subject: batctl: ping: fix rtt minimum tracking when a sample is 0.0
The rtt minimum is tracked with "if (time_delta < min || min == 0.0)",
using min's initial value of 0.0 as a "not set yet" sentinel. But 0.0 is
also a valid measurement which must be accepted as minimum.
packets_in is still 0 while the first reply is processed (it is incremented
afterwards), so use it to detect the first sample instead of overloading
min == 0.0.
Fixes: 2474249a6312 ("[batctl] ping utility updated to latest batman adv")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=b8a1b4344ce4a96dfc9f5a0a98daae2fcc1a6f27
--- a/ping.c
+++ b/ping.c
@@ -268,10 +268,14 @@ read_packet:
printf("\n");
- if ((time_delta < min) || (min == 0.0))
+ if (packets_in == 0)
min = time_delta;
+
+ min = fmin(time_delta, min);
+
if (time_delta > max)
max = time_delta;
+
avg += time_delta;
mdev += time_delta * time_delta;
packets_in++;
@@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 08:21:31 +0200
Subject: batctl: icmp_helper: fail send when the primary mac is unknown
icmp_interface_update() calls get_primarymac_netlink() but discards its
return value. That helper only writes the output buffer on success; on
failure (netlink error, or BATADV_ATTR_HARD_ADDRESS missing from the
BATADV_CMD_GET_MESH_INFO reply) it returns a negative errno and leaves the
buffer untouched. primary_mac is a zero-initialised static and this is the
only place that ever writes it, so a failed query leaves it as
00:00:00:00:00:00. And address which the receiver cannot use to send a
reply.
Propagate the failure out of icmp_interface_update() and abort the send.
Fixes: 4bd751eed4dc ("batctl: Implement non-routing batadv_icmp in userspace")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=61324450de7be775eb838ffaee866f71990a7295
--- a/icmp_helper.c
+++ b/icmp_helper.c
@@ -329,9 +329,7 @@ static int icmp_interface_update(struct
/* remove old interfaces */
icmp_interface_sweep();
- get_primarymac_netlink(state, primary_mac);
-
- return 0;
+ return get_primarymac_netlink(state, primary_mac);
}
static int icmp_interface_send(struct batadv_icmp_header *icmp_packet,
@@ -383,7 +381,9 @@ int icmp_interface_write(struct state *s
if (icmp_packet->msg_type != BATADV_ECHO_REQUEST)
return -EINVAL;
- icmp_interface_update(state);
+ ret = icmp_interface_update(state);
+ if (ret < 0)
+ return ret;
if (list_empty(&interface_list))
return -EFAULT;
@@ -0,0 +1,66 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 08:34:46 +0200
Subject: batctl: icmp_helper: attach socket filter before packets can arrive
The raw packet socket is created with ETH_P_ALL as protocol, which
registers the ethernet packet hook immediately. Frames from every interface
start queuing the moment the socket exists. The BPF filter that restricts
the socket to batman-adv ICMP packets with our uid is only attached after
bind(). Frames received in the window between socket() and SO_ATTACH_FILTER
are therefore queued unfiltered.
Delay the start of the capture by:
* create the socket with protocol 0 (no capture)
* attach the filter while the queue is guaranteed empty
* then bind() with sll_protocol = htons(ETH_P_ALL)
Only after the bind, packets will be captured.
Fixes: 4bd751eed4dc ("batctl: Implement non-routing batadv_icmp in userspace")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=3e85d01cdf1c4dbc433e4d8cc7cbaf19501b5a19
--- a/icmp_helper.c
+++ b/icmp_helper.c
@@ -175,7 +175,12 @@ static int icmp_interface_add(const char
strncpy(iface->name, ifname, IFNAMSIZ);
iface->name[sizeof(iface->name) - 1] = '\0';
- iface->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ /* create the socket with protocol 0 so the kernel does not start
+ * capturing yet - otherwise frames would queue unfiltered between
+ * socket() and SO_ATTACH_FILTER. Delivery only starts at bind() below,
+ * by which time the filter is already installed.
+ */
+ iface->sock = socket(PF_PACKET, SOCK_RAW, 0);
if (iface->sock < 0) {
perror("Error - can't create raw socket");
ret = -errno;
@@ -193,6 +198,12 @@ static int icmp_interface_add(const char
goto close_sock;
}
+ ret = icmp_interface_filter(iface->sock, uid);
+ if (ret < 0) {
+ fprintf(stderr, "Error - can't add filter to raw socket: %s\n", strerror(-ret));
+ goto close_sock;
+ }
+
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(ETH_P_ALL);
@@ -206,12 +217,6 @@ static int icmp_interface_add(const char
goto close_sock;
}
- ret = icmp_interface_filter(iface->sock, uid);
- if (ret < 0) {
- fprintf(stderr, "Error - can't add filter to raw socket: %s\n", strerror(-ret));
- goto close_sock;
- }
-
list_add(&iface->list, &interface_list);
return 0;
@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:17:54 +0200
Subject: batctl: tpmeter: don't use negative errno as exit status
The netlink error codes from tp_meter_start() and tp_recv_result() are
returned unmodified as command result, which main() passes to exit(). A
failure like -EOPNOTSUPP therefore turns into the meaningless exit status
instead of EXIT_FAILURE.
Report EXIT_FAILURE after printing the error.
Fixes: f109b3473f86 ("batctl: introduce throughput meter support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=aa4148ec99e308df403115fa1e6aeb2a80445c3a
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -388,6 +388,7 @@ static int throughputmeter(struct state
ret = tp_meter_start(state, dst_mac, time, &cookie);
if (ret < 0) {
printf("Failed to send tp_meter request to kernel: %d\n", ret);
+ ret = EXIT_FAILURE;
goto out;
}
@@ -395,6 +396,7 @@ static int throughputmeter(struct state
ret = tp_recv_result(listen_sock, &result);
if (ret < 0) {
printf("Failed to recv tp_meter result from kernel: %d\n", ret);
+ ret = EXIT_FAILURE;
goto out;
}
@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:48:58 +0200
Subject: batctl: tpmeter: abort result wait on receive errors
tp_recv_result() loops on nl_recvmsgs() until the tp_meter result
notification arrives, but never checks its return value. When the receive
fails (receive queue overrun and drops notification, socket failed
completely, ...), the loop just calls nl_recvmsgs() again and blocks
forever in recvmsg() waiting for a message that will never arrive.
Leave the receive loop on errors instead; the existing checks below then
report the failure to the caller.
Fixes: f109b3473f86 ("batctl: introduce throughput meter support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=3e64e20048e1459fe6afca55898a4b62ec4f83af
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -200,6 +200,7 @@ static int tp_recv_result(struct nl_sock
{
int err = 0;
struct nl_cb *cb;
+ int ret;
cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
@@ -207,8 +208,11 @@ static int tp_recv_result(struct nl_sock
result);
nl_cb_err(cb, NL_CB_CUSTOM, tpmeter_nl_print_error, result);
- while (result->error == 0 && !result->found)
- nl_recvmsgs(sock, cb);
+ while (result->error == 0 && !result->found) {
+ ret = nl_recvmsgs(sock, cb);
+ if (ret < 0)
+ break;
+ }
nl_cb_put(cb);
@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 12:22:10 +0200
Subject: batctl: tpmeter: reject invalid test duration argument
The -t option parses its argument with strtoul and
assigns the result straight into the uint32_t test length without any
validation.
Use the same strto* validation as the rest of batctl and print a user
readable error in case of an parsing error.
Fixes: f109b3473f86 ("batctl: introduce throughput meter support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=6ff39c6d5b9fc3763d84d55c7e8119cf683b238e
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -335,11 +335,22 @@ static int throughputmeter(struct state
.cookie = 0,
.found = false,
};
+ unsigned long time_arg;
+ char *endptr;
while ((optchar = getopt(argc, argv, "t:n")) != -1) {
switch (optchar) {
case 't':
- time = strtoul(optarg, NULL, 10);
+ time_arg = strtoul(optarg, &endptr, 10);
+ if (!endptr || *endptr != '\0' || endptr == optarg ||
+ time_arg > UINT32_MAX) {
+ fprintf(stderr,
+ "Error - the supplied test duration is invalid: %s\n",
+ optarg);
+ tp_meter_usage();
+ return EXIT_FAILURE;
+ }
+ time = time_arg;
break;
case 'n':
read_opt &= ~USE_BAT_HOSTS;
@@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 22:10:05 +0200
Subject: batctl: tpmeter: report kernel errors via strerror
tp_meter_start() and tp_recv_result() return a negative system errno
captured from the kernel's netlink error reply. Both failure paths in
throughputmeter() printed that value with "%d", so the user saw a raw
negative number instead of a readable message. In batctl, this is usually
formatted with strerror() to get a human readable version.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=0d5537a5c2ac46f74d5dbaf8601594383e0961bb
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -402,7 +402,8 @@ static int throughputmeter(struct state
ret = tp_meter_start(state, dst_mac, time, &cookie);
if (ret < 0) {
- printf("Failed to send tp_meter request to kernel: %d\n", ret);
+ printf("Failed to send tp_meter request to kernel: %s\n",
+ strerror(-ret));
ret = EXIT_FAILURE;
goto out;
}
@@ -410,7 +411,8 @@ static int throughputmeter(struct state
result.cookie = cookie.cookie;
ret = tp_recv_result(listen_sock, &result);
if (ret < 0) {
- printf("Failed to recv tp_meter result from kernel: %d\n", ret);
+ printf("Failed to recv tp_meter result from kernel: %s\n",
+ strerror(-ret));
ret = EXIT_FAILURE;
goto out;
}
@@ -0,0 +1,87 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:50:36 +0200
Subject: batctl: tpmeter: don't cancel test from the signal handler
tp_sig_handler() calls fflush() and tp_meter_stop() directly from signal
context. tp_meter_stop() allocates a netlink message with nlmsg_alloc() and
sends it via nl_send_auto_complete() - none of these functions (nor fflush)
are async-signal-safe.
Let the signal handler only set a flag. tp_recv_result() now waits for the
result notification with poll(), which is not restarted when a signal
arrives, and sends the CANCEL request from the main flow before continuing
to wait for the (then canceled) test result.
Fixes: f109b3473f86 ("batctl: introduce throughput meter support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: backported, https://git.open-mesh.org/batctl.git/commit/?id=a7aa6484b2a3c0fcd44d2307eddcfd712336e8d7
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -17,6 +17,7 @@
#include <inttypes.h>
#include <limits.h>
#include <net/if.h>
+#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -35,6 +36,7 @@
static struct ether_addr *dst_mac;
static struct state *tp_state;
+static volatile sig_atomic_t tp_aborted;
struct tp_result {
int error;
@@ -196,8 +198,15 @@ static int no_seq_check(struct nl_msg *m
return NL_OK;
}
+static int tp_meter_stop(struct state *state, struct ether_addr *dst_mac);
+
static int tp_recv_result(struct nl_sock *sock, struct tp_result *result)
{
+ struct pollfd pfd = {
+ .fd = nl_socket_get_fd(sock),
+ .events = POLLIN,
+ };
+ bool cancel_sent = false;
int err = 0;
struct nl_cb *cb;
int ret;
@@ -209,6 +218,23 @@ static int tp_recv_result(struct nl_sock
nl_cb_err(cb, NL_CB_CUSTOM, tpmeter_nl_print_error, result);
while (result->error == 0 && !result->found) {
+ if (tp_aborted && !cancel_sent) {
+ cancel_sent = true;
+ tp_meter_stop(tp_state, dst_mac);
+ }
+
+ /* wake up regularly to notice an abort even when the signal
+ * arrived outside of poll()
+ */
+ ret = poll(&pfd, 1, 1000);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+ if (ret == 0)
+ continue;
+
ret = nl_recvmsgs(sock, cb);
if (ret < 0)
break;
@@ -297,8 +323,7 @@ void tp_sig_handler(int sig)
switch (sig) {
case SIGINT:
case SIGTERM:
- fflush(stdout);
- tp_meter_stop(tp_state, dst_mac);
+ tp_aborted = 1;
break;
default:
break;
@@ -0,0 +1,74 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 09:37:32 +0200
Subject: batctl: handle netlink callback object on error
The libnl callback object is allocated and must be deallocated when it is
no longer used. This is especially important when an error happened.
Fixes: d8dd1ff1a0fe ("batctl: Use netlink to replace some of debugfs")
Fixes: f109b3473f86 ("batctl: introduce throughput meter support")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=2fb0542f6881c7205dd025774b08789036f110b1
--- a/netlink.c
+++ b/netlink.c
@@ -493,11 +493,15 @@ char *netlink_get_info(struct state *sta
nl_cb_err(cb, NL_CB_CUSTOM, netlink_print_error, NULL);
ret = nl_recvmsgs(state->sock, cb);
- if (ret < 0)
+ if (ret < 0) {
+ nl_cb_put(cb);
return opts.remaining_header;
+ }
nl_wait_for_ack(state->sock);
+ nl_cb_put(cb);
+
return opts.remaining_header;
}
--- a/routing_algo.c
+++ b/routing_algo.c
@@ -108,6 +108,7 @@ static int print_routing_algos(struct st
nl_cb_err(cb, NL_CB_CUSTOM, netlink_print_error, NULL);
nl_recvmsgs(state->sock, cb);
+ nl_cb_put(cb);
if (!last_err) {
netlink_print_remaining_header(&opts);
--- a/throughputmeter.c
+++ b/throughputmeter.c
@@ -162,13 +162,18 @@ static int tp_meter_start(struct state *
int err = 0;
cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ return -ENOMEM;
+
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, tp_meter_cookie_callback,
cookie);
nl_cb_err(cb, NL_CB_CUSTOM, tpmeter_nl_print_error, cookie);
msg = nlmsg_alloc();
- if (!msg)
+ if (!msg) {
+ nl_cb_put(cb);
return -ENOMEM;
+ }
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, state->batadv_family, 0,
0, BATADV_CMD_TP_METER, 1);
@@ -212,6 +217,9 @@ static int tp_recv_result(struct nl_sock
int ret;
cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ return -ENOMEM;
+
nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, tp_meter_result_callback,
result);
@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:07:05 +0200
Subject: batctl: netlink: abort netlink_print_common when message allocation fails
When nlmsg_alloc() fails, netlink_print_common() just continues. In
one-shot mode this leaves the loop with the stale last_err of 0 and the
command reports success even though nothing was queried or printed. In
watch mode the loop retries immediately without the usleep() pause and
leaks the header that netlink_get_info() prepared in the previous
iteration.
Treat the allocation failure as -ENOMEM and leave the query loop.
Fixes: d8dd1ff1a0fe ("batctl: Use netlink to replace some of debugfs")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=0e93dc083e07bafc6efd1f7b13302cb320f7f1fb
--- a/netlink.c
+++ b/netlink.c
@@ -571,8 +571,10 @@ int netlink_print_common(struct state *s
header);
msg = nlmsg_alloc();
- if (!msg)
- continue;
+ if (!msg) {
+ last_err = -ENOMEM;
+ break;
+ }
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, state->batadv_family,
0, NLM_F_DUMP, nl_cmd, 1);
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:07:42 +0200
Subject: batctl: netlink: don't format NULL extra_info in info_callback
When asprintf() or strdup() fail to create the extra_info string,
info_callback() continues with extra_info set to NULL and passes it as
%s argument to the following asprintf(). Passing NULL to %s is
undefined behavior.
Fall back to an empty string when extra_info could not be allocated.
Fixes: d8dd1ff1a0fe ("batctl: Use netlink to replace some of debugfs")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=a199671424f13ff04e60ba114448a0fd663f1af9
--- a/netlink.c
+++ b/netlink.c
@@ -444,7 +444,8 @@ static int info_callback(struct nl_msg *
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);
+ algo_name, extra_info ? extra_info : "",
+ extra_header);
if (ret < 0)
opts->remaining_header = NULL;
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 08:13:51 +0200
Subject: batctl: netlink: report dump errors signalled in the NLMSG_DONE message
When a dump is terminated with a non-zero error code in its NLMSG_DONE
message, "Error received" is printed but it is missed to update the global
error state (last_err). netlink_print_common() therefore returns 0 and the
command exits EXIT_SUCCESS despite the error just printed.
Fixes: 854835788001 ("batctl: Move routing_algo specific code it command source file")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=5d92fd26f616020852748db5c0e131f3044c83ff
--- a/netlink.c
+++ b/netlink.c
@@ -320,8 +320,10 @@ int netlink_stop_callback(struct nl_msg
struct nlmsghdr *nlh = nlmsg_hdr(msg);
int *error = nlmsg_data(nlh);
- if (*error)
+ if (*error) {
fprintf(stderr, "Error received: %s\n", strerror(-*error));
+ last_err = *error;
+ }
return NL_STOP;
}
@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 11:46:43 +0200
Subject: batctl: netlink: detect receive errors in netlink_print_common
netlink_print_common() clears last_err to 0 before each dump and then
ignores the return value of nl_recvmsgs(). It will therefore only print
errors which were received in netlink messages - but not the major errors
when communicating with the kernel.
Capture the nl_recvmsgs() return value, matching the sibling helper
netlink_query_common().
Fixes: d8dd1ff1a0fe ("batctl: Use netlink to replace some of debugfs")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=c7cc6e10d280b7724ff3bd9cb6abef91437f48c1
--- a/netlink.c
+++ b/netlink.c
@@ -541,6 +541,7 @@ int netlink_print_common(struct state *s
};
int hardifindex = 0;
struct nl_msg *msg;
+ int ret;
if (!state->sock) {
last_err = -EOPNOTSUPP;
@@ -592,7 +593,9 @@ int netlink_print_common(struct state *s
nlmsg_free(msg);
last_err = 0;
- nl_recvmsgs(state->sock, state->cb);
+ ret = nl_recvmsgs(state->sock, state->cb);
+ if (ret < 0)
+ last_err = -EIO;
/* the header should still be printed when no entry was received */
if (!last_err)
@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 04:43:26 +0200
Subject: batctl: netlink: report kernel errors when writing settings
When writing a setting, sys_simple_nlquery() consumes the kernel reply via
nl_wait_for_ack(). This helper uses the socket's default callbacks instead
of state->cb, so sys_simple_nlerror() never runs and its (negative) return
value is discarded. A set request rejected by the kernel therefore prints
no error message and exits with EXIT_SUCCESS.
This can be seen easily by calling: "batctl meshif bat0 aggregation 1"
without CAP_NET_ADMIN.
Receive the reply through state->cb instead, like the read path already
does. The error handler then prints the kernel error, stores it in result
and the command exits with EXIT_FAILURE.
Fixes: 0b81e8fbaed5 ("batctl: Consume genl ACKs after setting reads")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=9de9f65aaae6fece0463f39930daac5f50f73bed
--- a/sys.c
+++ b/sys.c
@@ -110,10 +110,16 @@ int sys_simple_nlquery(struct state *sta
if (callback) {
ret = nl_recvmsgs(state->sock, state->cb);
if (ret < 0)
- return ret;
+ return -EIO;
+
+ nl_wait_for_ack(state->sock);
+
+ return result;
}
- nl_wait_for_ack(state->sock);
+ ret = nl_recvmsgs(state->sock, state->cb);
+ if (ret < 0 && result >= 0)
+ result = -EIO;
return result;
}
@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Thu, 2 Jul 2026 10:02:03 +0200
Subject: batctl: netlink: report send errors in netlink_simple_request
netlink_simple_request() initializes err to 0 and only lets
ack_errno_handler() update it while receiving. When nl_send_auto_complete()
fails, the function jumps to the cleanup path with err still set to 0 and
reports success even though the request never reached the kernel. Callers
like the interface create/destroy handling then exit without any error
indication.
Set err to -EIO on the send error path to let the caller handle it as
actual error.
Fixes: dd2bbe182780 ("batctl: Add command to create/destroy batman-adv interface")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=8cb6fb00dcfefb047f31b599b3b6d83c967cc5cb
--- a/functions.c
+++ b/functions.c
@@ -558,8 +558,10 @@ int netlink_simple_request(struct nl_msg
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
ret = nl_send_auto_complete(sock, msg);
- if (ret < 0)
+ if (ret < 0) {
+ err = -EIO;
goto err_free_cb;
+ }
// ack_errno_handler sets err on errors
err = 0;
@@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 07:13:53 +0200
Subject: batctl: netlink: detect receive errors in query_rtnl_link
query_rtnl_link() ignores the return value of nl_recvmsgs(). Once
nl_send_auto_complete() succeeds, the local err stays 0 no matter what
happens while receiving the RTM_GETLINK dump, so a failed or truncated dump
is reported as success.
Set err to -EIO on an receive error to let the caller handle it as actual
error.
Fixes: 45548f578683 ("batctl: Use rtnl to query list of softif devices")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=043adfdf579c656b707c60f7a3a08a38e4543f49
--- a/functions.c
+++ b/functions.c
@@ -502,7 +502,9 @@ int query_rtnl_link(int ifindex, nl_recv
if (ret < 0)
goto err_free_msg;
- nl_recvmsgs(sock, cb);
+ ret = nl_recvmsgs(sock, cb);
+ if (ret < 0)
+ err = -EIO;
err_free_msg:
nlmsg_free(msg);
@@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 11:46:19 +0200
Subject: batctl: netlink: detect receive errors in netlink_simple_request
netlink_simple_request() ignores the return value of nl_recvmsgs(). Once
nl_send_auto_complete() succeeds, the local err stays 0 no matter what
happens while receiving the RTM_GETLINK dump, so a failed or truncated dump
is reported as success.
Set err to -EIO on an receive error to let the caller handle it as actual
error.
Fixes: dd2bbe182780 ("batctl: Add command to create/destroy batman-adv interface")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=c2a77e573b63eaa22d3a7096296164a9aa190eab
--- a/functions.c
+++ b/functions.c
@@ -567,7 +567,9 @@ int netlink_simple_request(struct nl_msg
// ack_errno_handler sets err on errors
err = 0;
- nl_recvmsgs(sock, cb);
+ ret = nl_recvmsgs(sock, cb);
+ if (ret < 0)
+ err = ret;
err_free_cb:
nl_cb_put(cb);
@@ -0,0 +1,157 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 11:47:52 +0200
Subject: batctl: netlink: detect receive errors in query_rtnl_link_single
With the exception of nl_socket_alloc(), query_rtnl_link_single() always
returns 0, no matter what happens. All callers rely solely on the *_found
flags in link_data to decide what an interface is.
Return proper negative errno codes from the setup error paths, mirroring
the sibling helper query_rtnl_link(). These need to be handled also by the
callers.
Fixes: 07967cd19702 ("batctl: Support checking of meshif without sysfs")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=f8a48604bd0f135404e4be74a406b3efca8740c0
--- a/functions.c
+++ b/functions.c
@@ -673,6 +673,7 @@ static int query_rtnl_link_single(int me
};
struct nl_cb *cb = NULL;
struct nl_sock *sock;
+ int err = 0;
int ret;
link_data->kind_found = false;
@@ -682,42 +683,55 @@ static int query_rtnl_link_single(int me
sock = nl_socket_alloc();
if (!sock)
- return -1;
+ return -ENOMEM;
ret = nl_connect(sock, NETLINK_ROUTE);
- if (ret < 0)
+ if (ret < 0) {
+ err = -ENOMEM;
goto free_sock;
+ }
ret = nl_send_simple(sock, RTM_GETLINK, NLM_F_REQUEST,
&ifinfo, sizeof(ifinfo));
- if (ret < 0)
+ if (ret < 0) {
+ err = -EIO;
goto free_sock;
+ }
cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (!cb)
+ if (!cb) {
+ err = -ENOMEM;
goto free_sock;
+ }
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, query_rtnl_link_single_parse,
link_data);
- nl_recvmsgs(sock, cb);
+
+ ret = nl_recvmsgs(sock, cb);
+ if (ret < 0)
+ err = -EIO;
nl_cb_put(cb);
free_sock:
nl_socket_free(sock);
- return 0;
+ return err;
}
int translate_vlan_iface(struct state *state, const char *vlandev)
{
struct rtnl_link_iface_data link_data;
unsigned int arg_ifindex;
+ int ret;
arg_ifindex = if_nametoindex(vlandev);
if (arg_ifindex == 0)
return -ENODEV;
- query_rtnl_link_single(arg_ifindex, &link_data);
+ ret = query_rtnl_link_single(arg_ifindex, &link_data);
+ if (ret < 0)
+ return ret;
+
if (!link_data.vid_found)
return -ENODEV;
@@ -791,12 +805,16 @@ int translate_hard_iface(struct state *s
{
struct rtnl_link_iface_data link_data;
unsigned int arg_ifindex;
+ int ret;
arg_ifindex = if_nametoindex(hardif);
if (arg_ifindex == 0)
return -ENODEV;
- query_rtnl_link_single(arg_ifindex, &link_data);
+ ret = query_rtnl_link_single(arg_ifindex, &link_data);
+ if (ret < 0)
+ return ret;
+
if (!link_data.master_found)
return -ENOLINK;
@@ -812,8 +830,12 @@ int translate_hard_iface(struct state *s
static int check_mesh_iface_netlink(unsigned int ifindex)
{
struct rtnl_link_iface_data link_data;
+ int ret;
+
+ ret = query_rtnl_link_single(ifindex, &link_data);
+ if (ret < 0)
+ return ret;
- query_rtnl_link_single(ifindex, &link_data);
if (!link_data.kind_found)
return -1;
@@ -827,12 +849,15 @@ int guess_netdev_type(const char *netdev
{
struct rtnl_link_iface_data link_data;
unsigned int netdev_ifindex;
+ int ret;
netdev_ifindex = if_nametoindex(netdev);
if (netdev_ifindex == 0)
return -ENODEV;
- query_rtnl_link_single(netdev_ifindex, &link_data);
+ ret = query_rtnl_link_single(netdev_ifindex, &link_data);
+ if (ret < 0)
+ return ret;
if (link_data.kind_found && strcmp(link_data.kind, "batadv") == 0) {
*type = SP_MESHIF;
@@ -866,12 +891,16 @@ int check_mesh_iface_ownership(struct st
{
struct rtnl_link_iface_data link_data;
unsigned int hardif_index;
+ int ret;
hardif_index = if_nametoindex(hard_iface);
if (hardif_index == 0)
return EXIT_FAILURE;
- query_rtnl_link_single(hardif_index, &link_data);
+ ret = query_rtnl_link_single(hardif_index, &link_data);
+ if (ret < 0)
+ return EXIT_FAILURE;
+
if (!link_data.master_found)
return EXIT_FAILURE;
@@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 21 Jun 2026 15:01:15 +0200
Subject: batctl: netlink: report error on query_rtnl_link send failure
When nl_send_auto_complete() fails, an explicit error must be set or
otherwise query_rtnl_link() will return 0 (no error).
Fixes: 60e519bfeaa3 ("batctl: Use rtnl to query list of softif devices")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=51aa9290b0a9dd2a7178cd38b14764fa031cdf5f
--- a/functions.c
+++ b/functions.c
@@ -499,8 +499,10 @@ int query_rtnl_link(int ifindex, nl_recv
}
ret = nl_send_auto_complete(sock, msg);
- if (ret < 0)
+ if (ret < 0) {
+ err = -EIO;
goto err_free_msg;
+ }
ret = nl_recvmsgs(sock, cb);
if (ret < 0)
@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 3 Jul 2026 22:09:32 +0200
Subject: batctl: netlink: use kernel-style error codes for nl_recvmsgs
When nl_recvmsgs() fails, it doesn't return a kernel/errno style error
codes. It is instead using negative NLE_* return codes. Since the rest of
the batctl code uses kernel style codes, just handle it as EIO error.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=63c5a4724ab9c825604092ae83615968023b553d
--- a/functions.c
+++ b/functions.c
@@ -571,7 +571,7 @@ int netlink_simple_request(struct nl_msg
err = 0;
ret = nl_recvmsgs(sock, cb);
if (ret < 0)
- err = ret;
+ err = -EIO;
err_free_cb:
nl_cb_put(cb);
--- a/netlink.c
+++ b/netlink.c
@@ -681,7 +681,8 @@ int netlink_query_common(struct state *s
ret = nl_recvmsgs(state->sock, cb);
if (ret < 0) {
- query_opts->err = ret;
+ if (query_opts->err == 0)
+ query_opts->err = -EIO;
goto err_free_cb;
}
@@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sat, 18 Jul 2026 14:38:49 +0200
Subject: debug: drop stray debug printf line
Fixes: 46aca094072a ("batctl: debug: avoid endless getopt loop for attached '-w' argument")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Origin: upstream, https://git.open-mesh.org/batctl.git/commit/?id=475062a00e17225d0193e415ab2062ed20e93f78
--- a/debug.c
+++ b/debug.c
@@ -54,7 +54,6 @@ int handle_debug_table(struct state *sta
int err;
while ((optchar = getopt(argc, argv, "hnw::t:Humi:")) != -1) {
- printf("%c\n", optchar);
switch (optchar) {
case 'h':
debug_table_usage(state);
+1 -5
View File
@@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=batman-adv
PKG_VERSION:=2024.3
PKG_RELEASE:=11
PKG_RELEASE:=13
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION)
@@ -53,10 +53,6 @@ define KernelPackage/batman-adv/config
source "$(SOURCE)/Config.in"
endef
define Package/kmod-batman-adv/conffiles
/etc/config/batman-adv
endef
PKG_EXTRA_KCONFIG:= \
CONFIG_BATMAN_ADV=m \
CONFIG_BATMAN_ADV_DEBUG=$(if $(CONFIG_BATMAN_ADV_DEBUG),y,n) \
@@ -17,7 +17,7 @@ proto_batadv_to_batadv_hardif() {
config_get routing_algo "${section}" routing_algo
if [ -z "$mesh" -o "${proto}" != "batadv" ]; then
continue
return
fi
uci set network."${section}".proto="batadv_hardif"
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Date: Thu, 6 Apr 2023 18:05:50 -0500
Subject: fix batadv_is_cfg80211_netdev
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 2 Feb 2024 22:49:48 +0100
Subject: Revert "batman-adv: Switch to linux/array_size.h"
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Remi Pommarel <repk@triplefau.lt>
Date: Fri, 22 Nov 2024 16:52:48 +0100
Subject: batman-adv: Do not send uninitialized TT changes
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Remi Pommarel <repk@triplefau.lt>
Date: Fri, 22 Nov 2024 16:52:49 +0100
Subject: batman-adv: Remove uninitialized data in full table TT response
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Remi Pommarel <repk@triplefau.lt>
Date: Fri, 22 Nov 2024 16:52:50 +0100
Subject: batman-adv: Do not let TT changes list grows indefinitely
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andy Strohman <andrew@andrewstrohman.com>
Date: Thu, 9 Jan 2025 02:27:56 +0000
Subject: batman-adv: fix panic during interface removal
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Wed, 22 Jan 2025 21:51:20 +0100
Subject: batman-adv: Ignore neighbor throughput metrics in error case
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Wed, 22 Jan 2025 21:51:21 +0100
Subject: batman-adv: Drop unmanaged ELP metric worker
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 2 Feb 2025 17:04:13 +0100
Subject: batman-adv: Ignore own maximum aggregation size during RX
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Wed, 16 Apr 2025 20:37:56 +0200
Subject: batman-adv: fix duplicate MAC address check
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Stanislav Fort <stanislav.fort@aisle.com>
Date: Sun, 31 Aug 2025 16:56:23 +0200
Subject: batman-adv: fix OOB read/write in network-coding decode
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Mon, 16 Feb 2026 20:05:55 +0100
Subject: batman-adv: Avoid double-rtnl_lock ELP metric worker
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yang Yang <n05ec@lzu.edu.cn>
Date: Sat, 14 Mar 2026 07:11:27 +0000
Subject: batman-adv: avoid OGM aggregation when skb tailroom is insufficient
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ruide Cao <caoruide123@gmail.com>
Date: Thu, 2 Apr 2026 23:12:31 +0800
Subject: batman-adv: reject oversized global TT response buffers
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Haoze Xie <royenheart@gmail.com>
Date: Mon, 6 Apr 2026 21:17:28 +0800
Subject: batman-adv: hold claim backbone gateways by reference
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lyes Bourennani <lbourennani@fuzzinglabs.com>
Date: Wed, 22 Apr 2026 00:20:22 +0200
Subject: batman-adv: fix integer overflow on buff_pos
@@ -1,3 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jiexun Wang <wangjiexun2025@gmail.com>
Date: Mon, 27 Apr 2026 14:43:33 +0800
Subject: batman-adv: reject new tp_meter sessions during teardown
Loaded 100 of 185 files, more files were not shown because too many files have changed in this diff. Show more