X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fliboping.c;h=e80ea294d660f75fcb98b5c0d02f95b184d7207d;hb=d68caf850e2b270fc3962b35ee483503ce243a4f;hp=dc2b4494ee61cfce3e5af4c3e6b3a0c29a5aca0d;hpb=9ae85a09d919777c9be52e55b23c08bf2c8c1d0e;p=liboping.git diff --git a/src/liboping.c b/src/liboping.c index dc2b449..e80ea29 100644 --- a/src/liboping.c +++ b/src/liboping.c @@ -134,6 +134,8 @@ struct pingobj struct sockaddr *srcaddr; socklen_t srcaddrlen; + char *device; + char errmsg[PING_ERRMSG_LEN]; pinghost_t *head; @@ -588,9 +590,10 @@ static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph, 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; @@ -629,23 +632,25 @@ static int ping_receive_all (pingobj_t *obj) 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) @@ -657,11 +662,11 @@ static int ping_receive_all (pingobj_t *obj) 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) { @@ -694,9 +699,18 @@ static int ping_receive_all (pingobj_t *obj) 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) */ @@ -1050,6 +1064,9 @@ void ping_destroy (pingobj_t *obj) if (obj->srcaddr != NULL) free (obj->srcaddr); + if (obj->device != NULL) + free (obj->device); + free (obj); return; @@ -1175,6 +1192,28 @@ int ping_setopt (pingobj_t *obj, int option, void *value) } /* 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) */ @@ -1348,6 +1387,25 @@ int ping_host_add (pingobj_t *obj, const char *host) } } +#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); @@ -1486,7 +1544,10 @@ int ping_iterator_get_info (pingobj_iter_t *iter, int info, 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)