src/liboping.c: Remove dead code which broke strict aliasing rules.
[liboping.git] / src / liboping.c
index ec66a95..4393baf 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * Object oriented C module to send ICMP and ICMPv6 `echo's.
- * Copyright (C) 2006-2008  Florian octo Forster <octo at verplant.org>
+ * Copyright (C) 2006-2009  Florian octo Forster <octo at verplant.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -126,7 +126,7 @@ struct pingobj
        int                      addrfamily;
        char                    *data;
 
-       struct sockaddr_storage *srcaddr;
+       struct sockaddr         *srcaddr;
        socklen_t                srcaddrlen;
 
        char                     errmsg[PING_ERRMSG_LEN];
@@ -137,11 +137,60 @@ struct pingobj
 /*
  * private (static) functions
  */
+/* 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)
+{
+       buf[0] = 0;
+
+#if !HAVE_STRERROR_R
+       {
+               snprintf (buf, buflen, "Error %i (%#x)", errnum, errnum);
+       }
+/* #endif !HAVE_STRERROR_R */
+
+#elif STRERROR_R_CHAR_P
+       {
+               char *temp;
+               temp = strerror_r (errnum, buf, buflen);
+               if (buf[0] == 0)
+               {
+                       if ((temp != NULL) && (temp != buf) && (temp[0] != 0))
+                               strncpy (buf, temp, buflen);
+                       else
+                               strncpy (buf, "strerror_r did not return "
+                                               "an error message", buflen);
+               }
+       }
+/* #endif STRERROR_R_CHAR_P */
+
+#else
+       if (strerror_r (errnum, buf, buflen) != 0)
+       {
+               snprintf (buf, buflen, "Error %i (%#x); "
+                               "Additionally, strerror_r failed.",
+                               errnum, errnum);
+       }
+#endif /* STRERROR_R_CHAR_P */
+
+       buf[buflen - 1] = 0;
+
+       return (buf);
+} /* char *sstrerror */
+
 static void ping_set_error (pingobj_t *obj, const char *function,
                const char *message)
 {
-       snprintf (obj->errmsg, PING_ERRMSG_LEN, "%s: %s", function, message);
-       obj->errmsg[PING_ERRMSG_LEN - 1] = '\0';
+       snprintf (obj->errmsg, sizeof (obj->errmsg),
+                       "%s: %s", function, message);
+       obj->errmsg[sizeof (obj->errmsg) - 1] = 0;
+}
+
+static void ping_set_errno (pingobj_t *obj, const char *function,
+               int error_number)
+{
+       sstrerror (error_number, obj->errmsg, sizeof (obj->errmsg));
 }
 
 static int ping_timeval_add (struct timeval *tv1, struct timeval *tv2,
@@ -375,7 +424,7 @@ static pinghost_t *ping_receive_ipv6 (pinghost_t *ph, char *buffer, size_t buffe
 static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
 {
        char   buffer[4096];
-       size_t buffer_len;
+       ssize_t buffer_len;
 
        struct timeval diff;
 
@@ -388,13 +437,17 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
 
        buffer_len = recvfrom (fd, buffer, sizeof (buffer), 0,
                        (struct sockaddr *) &sa, &sa_len);
-       if (buffer_len == -1)
+       if (buffer_len < 0)
        {
-               dprintf ("recvfrom: %s\n", strerror (errno));
+#if WITH_DEBUG
+               char errbuf[PING_ERRMSG_LEN];
+               dprintf ("recvfrom: %s\n",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif
                return (-1);
        }
 
-       dprintf ("Read %u bytes from fd = %i\n", (unsigned int) buffer_len, fd);
+       dprintf ("Read %zi bytes from fd = %i\n", buffer_len, fd);
 
        if (sa.ss_family == AF_INET)
        {
@@ -456,7 +509,7 @@ static int ping_receive_all (pingobj_t *obj)
 
        if (gettimeofday (&nowtime, NULL) == -1)
        {
-               ping_set_error (obj, "gettimeofday", strerror (errno));
+               ping_set_errno (obj, "gettimeofday", errno);
                return (-1);
        }
 
@@ -493,7 +546,7 @@ static int ping_receive_all (pingobj_t *obj)
 
                if (gettimeofday (&nowtime, NULL) == -1)
                {
-                       ping_set_error (obj, "gettimeofday", strerror (errno));
+                       ping_set_errno (obj, "gettimeofday", errno);
                        return (-1);
                }
 
@@ -508,7 +561,7 @@ static int ping_receive_all (pingobj_t *obj)
 
                if (gettimeofday (&nowtime, NULL) == -1)
                {
-                       ping_set_error (obj, "gettimeofday", strerror (errno));
+                       ping_set_errno (obj, "gettimeofday", errno);
                        return (-1);
                }
                
@@ -519,7 +572,11 @@ static int ping_receive_all (pingobj_t *obj)
                }
                else if (status < 0)
                {
-                       dprintf ("select: %s\n", strerror (errno));
+#if WITH_DEBUG
+                       char errbuf[PING_ERRMSG_LEN];
+                       dprintf ("select: %s\n",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif
                        break;
                }
                else if (status == 0)
@@ -573,7 +630,7 @@ static ssize_t ping_sendto (pingobj_t *obj, pinghost_t *ph,
                if (errno == ENETUNREACH)
                        return (0);
 #endif
-               ping_set_error (obj, "sendto", strerror (errno));
+               ping_set_errno (obj, "sendto", errno);
        }
 
        return (ret);
@@ -685,7 +742,11 @@ static int ping_send_all (pingobj_t *obj)
                 * sending the packet, so I will do that too */
                if (gettimeofday (ptr->timer, NULL) == -1)
                {
-                       dprintf ("gettimeofday: %s\n", strerror (errno));
+#if WITH_DEBUG
+                       char errbuf[PING_ERRMSG_LEN];
+                       dprintf ("gettimeofday: %s\n",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif
                        timerclear (ptr->timer);
                        ret--;
                        continue;
@@ -770,10 +831,14 @@ static int ping_get_ident (void)
 
                        close (fd);
                }
+#if WITH_DEBUG
                else
                {
-                       dprintf ("open (/dev/urandom): %s\n", strerror (errno));
+                       char errbuf[PING_ERRMSG_LEN];
+                       dprintf ("open (/dev/urandom): %s\n",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
                }
+#endif
        }
 
        retval = (int) random ();
@@ -946,10 +1011,13 @@ int ping_setopt (pingobj_t *obj, int option, void *value)
                        status = getaddrinfo (hostname, NULL, &ai_hints, &ai_list);
                        if (status != 0)
                        {
+#if defined(EAI_SYSTEM)
+                               char errbuf[PING_ERRMSG_LEN];
+#endif
                                ping_set_error (obj, "getaddrinfo",
 #if defined(EAI_SYSTEM)
                                                (status == EAI_SYSTEM)
-                                               ? strerror (errno) :
+                                               ? sstrerror (errno, errbuf, sizeof (errbuf)) :
 #endif
                                                gai_strerror (status));
                                ret = -1;
@@ -964,17 +1032,16 @@ int ping_setopt (pingobj_t *obj, int option, void *value)
                        if (obj->srcaddr == NULL)
                        {
                                obj->srcaddrlen = 0;
-                               obj->srcaddr = (struct sockaddr_storage *) malloc (sizeof (struct sockaddr_storage));
+                               obj->srcaddr = malloc (sizeof (struct sockaddr_storage));
                                if (obj->srcaddr == NULL)
                                {
-                                       ping_set_error (obj, "malloc",
-                                                       strerror (errno));
+                                       ping_set_errno (obj, "malloc", errno);
                                        ret = -1;
                                        freeaddrinfo (ai_list);
                                        break;
                                }
                        }
-                       memset ((void *) obj->srcaddr, '\0', sizeof (struct sockaddr_storage));
+                       memset ((void *) obj->srcaddr, 0, sizeof (struct sockaddr_storage));
                        assert (ai_list->ai_addrlen <= sizeof (struct sockaddr_storage));
                        memcpy ((void *) obj->srcaddr, (const void *) ai_list->ai_addr,
                                        ai_list->ai_addrlen);
@@ -1023,9 +1090,6 @@ int ping_host_add (pingobj_t *obj, const char *host)
 {
        pinghost_t *ph;
 
-       struct sockaddr_storage sockaddr;
-       socklen_t               sockaddr_len;
-
        struct addrinfo  ai_hints;
        struct addrinfo *ai_list, *ai_ptr;
        int              ai_return;
@@ -1055,7 +1119,7 @@ int ping_host_add (pingobj_t *obj, const char *host)
        if ((ph->username = strdup (host)) == NULL)
        {
                dprintf ("Out of memory!\n");
-               ping_set_error (obj, "strdup", strerror (errno));
+               ping_set_errno (obj, "strdup", errno);
                ping_free (ph);
                return (-1);
        }
@@ -1063,7 +1127,7 @@ int ping_host_add (pingobj_t *obj, const char *host)
        if ((ph->hostname = strdup (host)) == NULL)
        {
                dprintf ("Out of memory!\n");
-               ping_set_error (obj, "strdup", strerror (errno));
+               ping_set_errno (obj, "strdup", errno);
                ping_free (ph);
                return (-1);
        }
@@ -1072,18 +1136,21 @@ int ping_host_add (pingobj_t *obj, const char *host)
        if ((ph->data = strdup (obj->data == NULL ? PING_DEF_DATA : obj->data)) == NULL)
        {
                dprintf ("Out of memory!\n");
-               ping_set_error (obj, "strdup", strerror (errno));
+               ping_set_errno (obj, "strdup", errno);
                ping_free (ph);
                return (-1);
        }
 
        if ((ai_return = getaddrinfo (host, NULL, &ai_hints, &ai_list)) != 0)
        {
+#if defined(EAI_SYSTEM)
+               char errbuf[PING_ERRMSG_LEN];
+#endif
                dprintf ("getaddrinfo failed\n");
                ping_set_error (obj, "getaddrinfo",
 #if defined(EAI_SYSTEM)
                                                (ai_return == EAI_SYSTEM)
-                                               ? strerror (errno) :
+                                               ? sstrerror (errno, errbuf, sizeof (errbuf)) :
 #endif
                                gai_strerror (ai_return));
                ping_free (ph);
@@ -1097,30 +1164,13 @@ int ping_host_add (pingobj_t *obj, const char *host)
        {
                ph->fd = -1;
 
-               sockaddr_len = sizeof (sockaddr);
-               memset (&sockaddr, '\0', sockaddr_len);
-
                if (ai_ptr->ai_family == AF_INET)
                {
-                       struct sockaddr_in *si;
-
-                       si = (struct sockaddr_in *) &sockaddr;
-                       si->sin_family = AF_INET;
-                       si->sin_port   = htons (ph->ident);
-                       si->sin_addr.s_addr = htonl (INADDR_ANY);
-
                        ai_ptr->ai_socktype = SOCK_RAW;
                        ai_ptr->ai_protocol = IPPROTO_ICMP;
                }
                else if (ai_ptr->ai_family == AF_INET6)
                {
-                       struct sockaddr_in6 *si;
-
-                       si = (struct sockaddr_in6 *) &sockaddr;
-                       si->sin6_family = AF_INET6;
-                       si->sin6_port   = htons (ph->ident);
-                       si->sin6_addr   = in6addr_any;
-
                        ai_ptr->ai_socktype = SOCK_RAW;
                        ai_ptr->ai_protocol = IPPROTO_ICMPV6;
                }
@@ -1141,8 +1191,12 @@ int ping_host_add (pingobj_t *obj, const char *host)
                ph->fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
                if (ph->fd == -1)
                {
-                       dprintf ("socket: %s\n", strerror (errno));
-                       ping_set_error (obj, "socket", strerror (errno));
+#if WITH_DEBUG
+                       char errbuf[PING_ERRMSG_LEN];
+                       dprintf ("socket: %s\n",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif
+                       ping_set_errno (obj, "socket", errno);
                        continue;
                }
 
@@ -1151,10 +1205,14 @@ int ping_host_add (pingobj_t *obj, const char *host)
                        assert (obj->srcaddrlen > 0);
                        assert (obj->srcaddrlen <= sizeof (struct sockaddr_storage));
 
-                       if (bind (ph->fd, (struct sockaddr *) obj->srcaddr, obj->srcaddrlen) == -1)
+                       if (bind (ph->fd, obj->srcaddr, obj->srcaddrlen) == -1)
                        {
-                               dprintf ("bind: %s\n", strerror (errno));
-                               ping_set_error (obj, "bind", strerror (errno));
+#if WITH_DEBUG
+                               char errbuf[PING_ERRMSG_LEN];
+                               dprintf ("bind: %s\n",
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif
+                               ping_set_errno (obj, "bind", errno);
                                close (ph->fd);
                                ph->fd = -1;
                                continue;