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

Reply via email to