diff --git a/src/liboping.c b/src/liboping.c
index dc2b4494ee61cfce3e5af4c3e6b3a0c29a5aca0d..e80ea294d660f75fcb98b5c0d02f95b184d7207d 100644 (file)
--- a/src/liboping.c
+++ b/src/liboping.c
struct sockaddr *srcaddr;
socklen_t srcaddrlen;
+ char *device;
+
char errmsg[PING_ERRMSG_LEN];
pinghost_t *head;
static int ping_receive_all (pingobj_t *obj)
{
- fd_set readfds;
- int num_readfds;
- int max_readfds;
+ fd_set read_fds;
+ fd_set err_fds;
+ int num_fds;
+ int max_fd;
pinghost_t *ph;
pinghost_t *ptr;
while (1)
{
- FD_ZERO (&readfds);
- num_readfds = 0;
- max_readfds = -1;
+ FD_ZERO (&read_fds);
+ FD_ZERO (&err_fds);
+ num_fds = 0;
+ max_fd = -1;
for (ptr = ph; ptr != NULL; ptr = ptr->next)
{
if (!timerisset (ptr->timer))
continue;
- FD_SET (ptr->fd, &readfds);
- num_readfds++;
+ FD_SET (ptr->fd, &read_fds);
+ FD_SET (ptr->fd, &err_fds);
+ num_fds++;
- if (max_readfds < ptr->fd)
- max_readfds = ptr->fd;
+ if (max_fd < ptr->fd)
+ max_fd = ptr->fd;
}
- if (num_readfds == 0)
+ if (num_fds == 0)
break;
if (gettimeofday (&nowtime, NULL) == -1)
if (ping_timeval_sub (&endtime, &nowtime, &timeout) == -1)
break;
- dprintf ("Waiting on %i sockets for %i.%06i seconds\n", num_readfds,
+ dprintf ("Waiting on %i sockets for %i.%06i seconds\n", num_fds,
(int) timeout.tv_sec,
(int) timeout.tv_usec);
- status = select (max_readfds + 1, &readfds, NULL, NULL, &timeout);
+ status = select (max_fd + 1, &read_fds, NULL, &err_fds, &timeout);
if (gettimeofday (&nowtime, NULL) == -1)
{
for (ptr = ph; ptr != NULL; ptr = ptr->next)
{
- if (FD_ISSET (ptr->fd, &readfds))
+ if (FD_ISSET (ptr->fd, &read_fds))
+ {
if (ping_receive_one (obj, ptr, &nowtime) == 0)
ret++;
+ }
+ else if (FD_ISSET (ptr->fd, &err_fds))
+ {
+ /* clear the timer in this case so that we
+ * don't run into an endless loop. */
+ /* TODO: Set an error flag in this case. */
+ timerclear (ptr->timer);
+ }
}
} /* while (1) */
if (obj->srcaddr != NULL)
free (obj->srcaddr);
+ if (obj->device != NULL)
+ free (obj->device);
+
free (obj);
return;
} /* case PING_OPT_SOURCE */
break;
+ case PING_OPT_DEVICE:
+ {
+#ifdef SO_BINDTODEVICE
+ char *device = strdup ((char *) value);
+
+ if (device == NULL)
+ {
+ ping_set_errno (obj, errno);
+ ret = -1;
+ break;
+ }
+
+ if (obj->device != NULL)
+ free (obj->device);
+ obj->device = device;
+#else /* ! SO_BINDTODEVICE */
+ ping_set_errno (obj, ENOTSUP);
+ ret = -1;
+#endif /* ! SO_BINDTODEVICE */
+ } /* case PING_OPT_DEVICE */
+ break;
+
default:
ret = -2;
} /* switch (option) */
}
}
+#ifdef SO_BINDTODEVICE
+ if (obj->device != NULL)
+ {
+ if (setsockopt (ph->fd, SOL_SOCKET, SO_BINDTODEVICE,
+ obj->device, strlen (obj->device) + 1) != 0)
+ {
+#if WITH_DEBUG
+ char errbuf[PING_ERRMSG_LEN];
+ dprintf ("setsockopt: %s\n",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif
+ ping_set_errno (obj, errno);
+ close (ph->fd);
+ ph->fd = -1;
+ continue;
+ }
+ }
+#endif /* SO_BINDTODEVICE */
+
assert (sizeof (struct sockaddr_storage) >= ai_ptr->ai_addrlen);
memset (ph->addr, '\0', sizeof (struct sockaddr_storage));
memcpy (ph->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
size_t orig_buffer_len = *buffer_len;
- if ((iter == NULL) || (buffer == NULL) || (buffer_len == NULL))
+ if ((iter == NULL) || (buffer_len == NULL))
+ return (-1);
+
+ if ((buffer == NULL) && (*buffer_len != 0 ))
return (-1);
switch (info)