oping(8): Document the new `-f' option.
[liboping.git] / src / liboping.c
index 0f4c595..51071ad 100644 (file)
@@ -25,7 +25,6 @@
 # include <stdlib.h>
 # include <stdio.h>
 # include <string.h>
-# include <stdint.h>
 # include <inttypes.h>
 # include <errno.h>
 # include <assert.h>
 # 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
@@ -61,6 +64,7 @@
 #if HAVE_SYS_SOCKET_H
 # include <sys/socket.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 */
-char *sstrerror (int errnum, char *buf, size_t buflen)
+static char *sstrerror (int errnum, char *buf, size_t buflen)
 {
        buf[0] = 0;
 
@@ -339,6 +343,9 @@ static pinghost_t *ping_receive_ipv4 (pinghost_t *ph, char *buffer, size_t buffe
                                ident, seq);
        }
 
+       if (ptr != NULL)
+               ptr->recv_ttl = ip_hdr->ip_ttl;
+
        return (ptr);
 }
 
@@ -425,7 +432,6 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
 {
        struct timeval diff;
        pinghost_t *host = NULL;
-       int family;
        int recv_ttl;
        
        /*
@@ -454,6 +460,9 @@ 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;
+#ifdef MSG_XPG4_2
+       msghdr.msg_flags |= MSG_XPG4_2;
+#endif
 
        payload_buffer_len = recvmsg (fd, &msghdr, /* flags = */ 0);
        if (payload_buffer_len < 0)
@@ -468,15 +477,17 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
        dprintf ("Read %zi bytes from fd = %i\n", payload_buffer_len, fd);
 
        /* Iterate over all auxiliary data in msghdr */
-       family = -1;
        recv_ttl = -1;
+       ph->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),
@@ -489,9 +500,11 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
                                                cmsg->cmsg_type);
                        }
                } /* }}} */
-               else if (cmsg->cmsg_level == IPPROTO_IPV6) /* {{{ */
+               else if (ph->addrfamily == AF_INET6) /* {{{ */
                {
-                       family = AF_INET6;
+                       if (cmsg->cmsg_level != IPPROTO_IPV6)
+                               continue;
+
                        if (cmsg->cmsg_type == IPV6_HOPLIMIT)
                        {
                                memcpy (&recv_ttl, CMSG_DATA (cmsg),
@@ -512,13 +525,13 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
                }
        } /* }}} for (cmsg) */
 
-       if (family == AF_INET)
+       if (ph->addrfamily == AF_INET)
        {
                host = ping_receive_ipv4 (ph, payload_buffer, payload_buffer_len);
                if (host == NULL)
                        return (-1);
        }
-       else if (family == AF_INET6)
+       else if (ph->addrfamily == AF_INET6)
        {
                host = ping_receive_ipv6 (ph, payload_buffer, payload_buffer_len);
                if (host == NULL)
@@ -527,7 +540,7 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
        else
        {
                dprintf ("ping_receive_one: Unknown address family %i.\n",
-                               family);
+                               ph->addrfamily);
                return (-1);
        }
 
@@ -548,11 +561,12 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
                        (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->recv_ttl = recv_ttl;
-
        timerclear (host->timer);
 
        return (0);
@@ -872,11 +886,15 @@ static int ping_set_ttl (pinghost_t *ph, int ttl)
 
        if (ph->addrfamily == AF_INET)
        {
-               ret = setsockopt (ph->fd, IPPROTO_IP, IP_TTL, &ttl, sizeof (ttl));
+               dprintf ("Setting TTLv4 to %i\n", ttl);
+               ret = setsockopt (ph->fd, IPPROTO_IP, IP_TTL,
+                               &ttl, sizeof (ttl));
        }
        else if (ph->addrfamily == AF_INET6)
        {
-               ret = setsockopt (ph->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof (ttl));
+               dprintf ("Setting TTLv6 to %i\n", ttl);
+               ret = setsockopt (ph->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+                               &ttl, sizeof (ttl));
        }
 
        return (ret);
@@ -1037,6 +1055,13 @@ int ping_setopt (pingobj_t *obj, int option, void *value)
                                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:
@@ -1327,6 +1352,7 @@ int ping_host_add (pingobj_t *obj, const char *host)
                        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;
@@ -1334,6 +1360,7 @@ int ping_host_add (pingobj_t *obj, const char *host)
                        setsockopt (ph->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
                                        &opt, sizeof (opt));
                }
+#endif
 
                break;
        }