projects
/
liboping.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
src/liboping.c: Fixed the handling of multiple hosts.
[liboping.git]
/
src
/
liboping.c
diff --git
a/src/liboping.c
b/src/liboping.c
index
65b2ef5
..
87aa654
100644
(file)
--- a/
src/liboping.c
+++ b/
src/liboping.c
@@
-25,7
+25,6
@@
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
-# include <stdint.h>
# include <inttypes.h>
# include <errno.h>
# include <assert.h>
# include <inttypes.h>
# include <errno.h>
# include <assert.h>
@@
-33,6
+32,10
@@
# error "You don't have the standard C99 header files installed"
#endif /* STDC_HEADERS */
# error "You don't have the standard C99 header files installed"
#endif /* STDC_HEADERS */
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
@@
-61,6
+64,7
@@
#if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
+
#if HAVE_NETDB_H
# include <netdb.h>
#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
@@
-141,7
+145,7
@@
struct pingobj
/* Even though Posix requires "strerror_r" to return an "int",
* some systems (e.g. the GNU libc) return a "char *" _and_
* ignore the second argument ... -tokkee */
/* Even though Posix requires "strerror_r" to return an "int",
* some systems (e.g. the GNU libc) return a "char *" _and_
* ignore the second argument ... -tokkee */
-char *sstrerror (int errnum, char *buf, size_t buflen)
+
static
char *sstrerror (int errnum, char *buf, size_t buflen)
{
buf[0] = 0;
{
buf[0] = 0;
@@
-255,7
+259,8
@@
static uint16_t ping_icmp4_checksum (char *buf, size_t len)
return (ret);
}
return (ret);
}
-static pinghost_t *ping_receive_ipv4 (pinghost_t *ph, char *buffer, size_t buffer_len)
+static pinghost_t *ping_receive_ipv4 (pingobj_t *obj, char *buffer,
+ size_t buffer_len)
{
struct ip *ip_hdr;
struct icmp *icmp_hdr;
{
struct ip *ip_hdr;
struct icmp *icmp_hdr;
@@
-310,7
+315,9
@@
static pinghost_t *ping_receive_ipv4 (pinghost_t *ph, char *buffer, size_t buffe
ident = ntohs (icmp_hdr->icmp_id);
seq = ntohs (icmp_hdr->icmp_seq);
ident = ntohs (icmp_hdr->icmp_id);
seq = ntohs (icmp_hdr->icmp_seq);
- for (ptr = ph; ptr != NULL; ptr = ptr->next)
+ /* We have to iterate over all hosts, since ICMPv4 packets may
+ * be received on any raw v4 socket. */
+ for (ptr = obj->head; ptr != NULL; ptr = ptr->next)
{
dprintf ("hostname = %s, ident = 0x%04x, seq = %i\n",
ptr->hostname, ptr->ident, ((ptr->sequence - 1) & 0xFFFF));
{
dprintf ("hostname = %s, ident = 0x%04x, seq = %i\n",
ptr->hostname, ptr->ident, ((ptr->sequence - 1) & 0xFFFF));
@@
-339,6
+346,9
@@
static pinghost_t *ping_receive_ipv4 (pinghost_t *ph, char *buffer, size_t buffe
ident, seq);
}
ident, seq);
}
+ if (ptr != NULL)
+ ptr->recv_ttl = ip_hdr->ip_ttl;
+
return (ptr);
}
return (ptr);
}
@@
-358,7
+368,8
@@
static pinghost_t *ping_receive_ipv4 (pinghost_t *ph, char *buffer, size_t buffe
# endif
#endif
# endif
#endif
-static pinghost_t *ping_receive_ipv6 (pinghost_t *ph, char *buffer, size_t buffer_len)
+static pinghost_t *ping_receive_ipv6 (pingobj_t *obj, char *buffer,
+ size_t buffer_len)
{
struct icmp6_hdr *icmp_hdr;
{
struct icmp6_hdr *icmp_hdr;
@@
-389,7
+400,9
@@
static pinghost_t *ping_receive_ipv6 (pinghost_t *ph, char *buffer, size_t buffe
ident = ntohs (icmp_hdr->icmp6_id);
seq = ntohs (icmp_hdr->icmp6_seq);
ident = ntohs (icmp_hdr->icmp6_id);
seq = ntohs (icmp_hdr->icmp6_seq);
- for (ptr = ph; ptr != NULL; ptr = ptr->next)
+ /* We have to iterate over all hosts, since ICMPv6 packets may
+ * be received on any raw v6 socket. */
+ for (ptr = obj->head; ptr != NULL; ptr = ptr->next)
{
dprintf ("hostname = %s, ident = 0x%04x, seq = %i\n",
ptr->hostname, ptr->ident, ((ptr->sequence - 1) & 0xFFFF));
{
dprintf ("hostname = %s, ident = 0x%04x, seq = %i\n",
ptr->hostname, ptr->ident, ((ptr->sequence - 1) & 0xFFFF));
@@
-421,11
+434,15
@@
static pinghost_t *ping_receive_ipv6 (pinghost_t *ph, char *buffer, size_t buffe
return (ptr);
}
return (ptr);
}
-static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
+static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph,
+ struct timeval *now)
{
{
+ /* Note: 'ph' is not necessarily the host object for which we receive a
+ * reply. The right object will be returned by ping_receive_ipv*(). For
+ * now, we can only rely on ph->fd and ph->addrfamily. */
+
struct timeval diff;
pinghost_t *host = NULL;
struct timeval diff;
pinghost_t *host = NULL;
- int family;
int recv_ttl;
/*
int recv_ttl;
/*
@@
-454,8
+471,11
@@
static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
msghdr.msg_controllen = sizeof (control_buffer);
/* flags; this is an output only field.. */
msghdr.msg_flags = 0;
msghdr.msg_controllen = sizeof (control_buffer);
/* flags; this is an output only field.. */
msghdr.msg_flags = 0;
+#ifdef MSG_XPG4_2
+ msghdr.msg_flags |= MSG_XPG4_2;
+#endif
- payload_buffer_len = recvmsg (fd, &msghdr, /* flags = */ 0);
+ payload_buffer_len = recvmsg (
ph->
fd, &msghdr, /* flags = */ 0);
if (payload_buffer_len < 0)
{
#if WITH_DEBUG
if (payload_buffer_len < 0)
{
#if WITH_DEBUG
@@
-465,18
+485,19
@@
static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
#endif
return (-1);
}
#endif
return (-1);
}
- dprintf ("Read %zi bytes from fd = %i\n", payload_buffer_len, fd);
+ dprintf ("Read %zi bytes from fd = %i\n", payload_buffer_len,
ph->
fd);
/* Iterate over all auxiliary data in msghdr */
/* Iterate over all auxiliary data in msghdr */
- family = -1;
recv_ttl = -1;
for (cmsg = CMSG_FIRSTHDR (&msghdr); /* {{{ */
cmsg != NULL;
cmsg = CMSG_NXTHDR (&msghdr, cmsg))
{
recv_ttl = -1;
for (cmsg = CMSG_FIRSTHDR (&msghdr); /* {{{ */
cmsg != NULL;
cmsg = CMSG_NXTHDR (&msghdr, cmsg))
{
- if (
cmsg->cmsg_level == IPPROTO_IP
) /* {{{ */
+ if (
ph->addrfamily == AF_INET
) /* {{{ */
{
{
- family = AF_INET;
+ if (cmsg->cmsg_level != IPPROTO_IP)
+ continue;
+
if (cmsg->cmsg_type == IP_TTL)
{
memcpy (&recv_ttl, CMSG_DATA (cmsg),
if (cmsg->cmsg_type == IP_TTL)
{
memcpy (&recv_ttl, CMSG_DATA (cmsg),
@@
-489,9
+510,11
@@
static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
cmsg->cmsg_type);
}
} /* }}} */
cmsg->cmsg_type);
}
} /* }}} */
- else if (
cmsg->cmsg_level == IPPROTO_IPV
6) /* {{{ */
+ else if (
ph->addrfamily == AF_INET
6) /* {{{ */
{
{
- family = AF_INET6;
+ if (cmsg->cmsg_level != IPPROTO_IPV6)
+ continue;
+
if (cmsg->cmsg_type == IPV6_HOPLIMIT)
{
memcpy (&recv_ttl, CMSG_DATA (cmsg),
if (cmsg->cmsg_type == IPV6_HOPLIMIT)
{
memcpy (&recv_ttl, CMSG_DATA (cmsg),
@@
-512,22
+535,22
@@
static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
}
} /* }}} for (cmsg) */
}
} /* }}} for (cmsg) */
- if (family == AF_INET)
+ if (
ph->addr
family == AF_INET)
{
{
- host = ping_receive_ipv4 (
ph
, payload_buffer, payload_buffer_len);
+ host = ping_receive_ipv4 (
obj
, payload_buffer, payload_buffer_len);
if (host == NULL)
return (-1);
}
if (host == NULL)
return (-1);
}
- else if (family == AF_INET6)
+ else if (
ph->addr
family == AF_INET6)
{
{
- host = ping_receive_ipv6 (
ph
, payload_buffer, payload_buffer_len);
+ host = ping_receive_ipv6 (
obj
, payload_buffer, payload_buffer_len);
if (host == NULL)
return (-1);
}
else
{
dprintf ("ping_receive_one: Unknown address family %i.\n",
if (host == NULL)
return (-1);
}
else
{
dprintf ("ping_receive_one: Unknown address family %i.\n",
- family);
+
ph->addr
family);
return (-1);
}
return (-1);
}
@@
-548,11
+571,12
@@
static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
(int) diff.tv_sec,
(int) diff.tv_usec);
(int) diff.tv_sec,
(int) diff.tv_usec);
+ if (recv_ttl >= 0)
+ host->recv_ttl = recv_ttl;
+
host->latency = ((double) diff.tv_usec) / 1000.0;
host->latency += ((double) diff.tv_sec) * 1000.0;
host->latency = ((double) diff.tv_usec) / 1000.0;
host->latency += ((double) diff.tv_sec) * 1000.0;
- host->recv_ttl = recv_ttl;
-
timerclear (host->timer);
return (0);
timerclear (host->timer);
return (0);
@@
-578,7
+602,10
@@
static int ping_receive_all (pingobj_t *obj)
ret = 0;
for (ptr = ph; ptr != NULL; ptr = ptr->next)
ret = 0;
for (ptr = ph; ptr != NULL; ptr = ptr->next)
- ptr->latency = -1.0;
+ {
+ ptr->latency = -1.0;
+ ptr->recv_ttl = -1;
+ }
if (gettimeofday (&nowtime, NULL) == -1)
{
if (gettimeofday (&nowtime, NULL) == -1)
{
@@
-664,7
+691,7
@@
static int ping_receive_all (pingobj_t *obj)
for (ptr = ph; ptr != NULL; ptr = ptr->next)
{
if (FD_ISSET (ptr->fd, &readfds))
for (ptr = ph; ptr != NULL; ptr = ptr->next)
{
if (FD_ISSET (ptr->fd, &readfds))
- if (ping_receive_one (
ptr->fd, ph
, &nowtime) == 0)
+ if (ping_receive_one (
obj, ptr
, &nowtime) == 0)
ret++;
}
} /* while (1) */
ret++;
}
} /* while (1) */
@@
-1041,6
+1068,13
@@
int ping_setopt (pingobj_t *obj, int option, void *value)
obj->ttl = PING_DEF_TTL;
ret = -1;
}
obj->ttl = PING_DEF_TTL;
ret = -1;
}
+ else
+ {
+ pinghost_t *ph;
+
+ for (ph = obj->head; ph != NULL; ph = ph->next)
+ ping_set_ttl (ph, obj->ttl);
+ }
break;
case PING_OPT_AF:
break;
case PING_OPT_AF:
@@
-1331,6
+1365,7
@@
int ping_host_add (pingobj_t *obj, const char *host)
setsockopt (ph->fd, IPPROTO_IP, IP_RECVTTL,
&opt, sizeof (opt));
}
setsockopt (ph->fd, IPPROTO_IP, IP_RECVTTL,
&opt, sizeof (opt));
}
+#if defined(IPPROTO_IPV6) && defined(IPV6_RECVHOPLIMIT)
else if (ph->addrfamily == AF_INET6)
{
int opt = 1;
else if (ph->addrfamily == AF_INET6)
{
int opt = 1;
@@
-1338,6
+1373,7
@@
int ping_host_add (pingobj_t *obj, const char *host)
setsockopt (ph->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
&opt, sizeof (opt));
}
setsockopt (ph->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
&opt, sizeof (opt));
}
+#endif
break;
}
break;
}