X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fliboping.c;h=e80ea294d660f75fcb98b5c0d02f95b184d7207d;hb=d68caf850e2b270fc3962b35ee483503ce243a4f;hp=36a3a3ef623d00c68f68d6fe1bdc241c89d5890e;hpb=30ee957b4843140d0d3bae39859d5624824b8feb;p=liboping.git diff --git a/src/liboping.c b/src/liboping.c index 36a3a3e..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) */ @@ -1005,6 +1019,8 @@ static void ping_free (pinghost_t *ph) */ const char *ping_get_error (pingobj_t *obj) { + if (obj == NULL) + return (NULL); return (obj->errmsg); } @@ -1029,6 +1045,9 @@ void ping_destroy (pingobj_t *obj) pinghost_t *current; pinghost_t *next; + if (obj == NULL) + return; + current = obj->head; next = NULL; @@ -1045,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; @@ -1054,7 +1076,7 @@ int ping_setopt (pingobj_t *obj, int option, void *value) { int ret = 0; - if (value == NULL) + if ((obj == NULL) || (value == NULL)) return (-1); switch (option) @@ -1170,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) */ @@ -1182,6 +1226,9 @@ int ping_send (pingobj_t *obj) { int ret; + if (obj == NULL) + return (-1); + if (ping_send_all (obj) < 0) return (-1); @@ -1212,6 +1259,9 @@ int ping_host_add (pingobj_t *obj, const char *host) struct addrinfo *ai_list, *ai_ptr; int ai_return; + if ((obj == NULL) || (host == NULL)) + return (-1); + dprintf ("host = %s\n", host); if (ping_host_search (obj->head, host) != NULL) @@ -1337,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); @@ -1423,6 +1492,9 @@ int ping_host_remove (pingobj_t *obj, const char *host) { pinghost_t *pre, *cur; + if ((obj == NULL) || (host == NULL)) + return (-1); + pre = NULL; cur = obj->head; @@ -1453,11 +1525,15 @@ int ping_host_remove (pingobj_t *obj, const char *host) pingobj_iter_t *ping_iterator_get (pingobj_t *obj) { + if (obj == NULL) + return (NULL); return ((pingobj_iter_t *) obj->head); } pingobj_iter_t *ping_iterator_next (pingobj_iter_t *iter) { + if (iter == NULL) + return (NULL); return ((pingobj_iter_t *) iter->next); } @@ -1468,6 +1544,12 @@ int ping_iterator_get_info (pingobj_iter_t *iter, int info, size_t orig_buffer_len = *buffer_len; + if ((iter == NULL) || (buffer_len == NULL)) + return (-1); + + if ((buffer == NULL) && (*buffer_len != 0 )) + return (-1); + switch (info) { case PING_INFO_USERNAME: @@ -1587,10 +1669,14 @@ int ping_iterator_get_info (pingobj_iter_t *iter, int info, void *ping_iterator_get_context (pingobj_iter_t *iter) { + if (iter == NULL) + return (NULL); return (iter->context); } void ping_iterator_set_context (pingobj_iter_t *iter, void *context) { + if (iter == NULL) + return; iter->context = context; }