[PATCH 02/11] batctl: icmp_helper: return proper errno on syscall failures

Sven Eckelmann <[email protected]> Tue, 07 Jul 2026 20:46:44 +0200
Newsgroups org.open-mesh.lists.batman
Message-ID <[email protected]>
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 <[email protected]>
---
 icmp_helper.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/icmp_helper.c b/icmp_helper.c
index 15bae9a..65a2005 100644
--- a/icmp_helper.c
+++ b/icmp_helper.c
@@ -154,7 +154,7 @@ static int icmp_interface_filter(int sock, int uid)
 
 	if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter,
 		       sizeof(filter)))
-		return -1;
+		return -errno;
 
 	return 0;
 }
@@ -348,6 +348,7 @@ static int icmp_interface_send(struct batadv_icmp_header *icmp_packet,
 {
 	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);
@@ -358,7 +359,11 @@ static int icmp_interface_send(struct batadv_icmp_header *icmp_packet,
 	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,
@@ -494,9 +499,12 @@ ssize_t icmp_interface_read(struct batadv_icmp_header *icmp_packet, size_t len,
 	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)
@@ -509,7 +517,7 @@ ssize_t icmp_interface_read(struct batadv_icmp_header *icmp_packet, size_t len,
 
 	read_len = readv(read_sock, vector, 2);
 	if (read_len < 0)
-		return read_len;
+		return -errno;
 
 	if (read_len < ETH_HLEN)
 		goto retry;

-- 
2.47.3