tags 745026 + patch thanks On Mon, Oct 12, 2015 at 01:39:32PM +0100, Barak A. Pearlmutter wrote: > I was figuring I'd be able to start with your quick hack and clean it up. > Ah well. > Anyway, thanks for the bug report.
This should be a proper fix, AFAIK. /* Steinar */ -- Homepage: https://www.sesse.net/
>From b9b8811d7167d5583eedc57737f523a97c531e70 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" <se...@google.com> Date: Fri, 25 Mar 2016 20:25:30 +0100 Subject: [PATCH 1/1] Add checks for replies coming from the right source address. Due to the use of randomized 16-bit IDs, they can easily collide. Thus, we need to check that the ping replies come from the right source address, or we will get replies spuriously attributed to the wrong host, even if that host is down. Fixes Debian bug #745026. --- src/liboping.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/liboping.c b/src/liboping.c index dd9da46..0e9736d 100644 --- a/src/liboping.c +++ b/src/liboping.c @@ -270,7 +270,7 @@ static uint16_t ping_icmp4_checksum (char *buf, size_t len) return (ret); } -static pinghost_t *ping_receive_ipv4 (pingobj_t *obj, char *buffer, +static pinghost_t *ping_receive_ipv4 (pingobj_t *obj, struct sockaddr_in *addr, char *buffer, size_t buffer_len) { struct ip *ip_hdr; @@ -346,6 +346,9 @@ static pinghost_t *ping_receive_ipv4 (pingobj_t *obj, char *buffer, if (((ptr->sequence - 1) & 0xFFFF) != seq) continue; + if (((struct sockaddr_in *)ptr->addr)->sin_addr.s_addr != addr->sin_addr.s_addr) + continue; + dprintf ("Match found: hostname = %s, ident = 0x%04"PRIx16", " "seq = %"PRIu16"\n", ptr->hostname, ident, seq); @@ -382,7 +385,7 @@ static pinghost_t *ping_receive_ipv4 (pingobj_t *obj, char *buffer, # endif #endif -static pinghost_t *ping_receive_ipv6 (pingobj_t *obj, char *buffer, +static pinghost_t *ping_receive_ipv6 (pingobj_t *obj, struct sockaddr_in6 *addr, char *buffer, size_t buffer_len) { struct icmp6_hdr *icmp_hdr; @@ -433,6 +436,10 @@ static pinghost_t *ping_receive_ipv6 (pingobj_t *obj, char *buffer, if (((ptr->sequence - 1) & 0xFFFF) != seq) continue; + if (memcmp(&((struct sockaddr_in6 *)ptr->addr)->sin6_addr, + &addr->sin6_addr, sizeof(struct sockaddr_in6)) != 0) + continue; + dprintf ("Match found: hostname = %s, ident = 0x%04"PRIx16", " "seq = %"PRIu16"\n", ptr->hostname, ident, seq); @@ -594,13 +601,13 @@ static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph, if (ph->addrfamily == AF_INET) { - host = ping_receive_ipv4 (obj, payload_buffer, payload_buffer_len); + host = ping_receive_ipv4 (obj, (struct sockaddr_in *)ph->addr, payload_buffer, payload_buffer_len); if (host == NULL) return (-1); } else if (ph->addrfamily == AF_INET6) { - host = ping_receive_ipv6 (obj, payload_buffer, payload_buffer_len); + host = ping_receive_ipv6 (obj, (struct sockaddr_in6 *)ph->addr, payload_buffer, payload_buffer_len); if (host == NULL) return (-1); } -- 2.8.0.rc3.226.g39d4020