liboping-1.8.0/0000755037772200116100000000000012433400211010325 500000000000000liboping-1.8.0/TODO0000644037772200116100000000032512432375456010762 00000000000000* Buffer the last 1000 (or so) replies, calculate percentile from that. * Add to the Prettyping graph to the right, let it shift to the left. * Redraw the entire line when pressing 'g'. 12+12+1 = 25 11+11+2 = 24 liboping-1.8.0/NEWS0000644037772200116100000000000011536627627010763 00000000000000liboping-1.8.0/src/0000755037772200116100000000000012433400211011114 500000000000000liboping-1.8.0/src/liboping.c0000644037772200116100000011502512411751420013016 00000000000000/** * Object oriented C module to send ICMP and ICMPv6 `echo's. * Copyright (C) 2006-2011 Florian octo Forster * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef __APPLE__ #define __APPLE_USE_RFC_3542 #endif #if HAVE_CONFIG_H # include #endif #if STDC_HEADERS # include # include # include # include # include # include #else # error "You don't have the standard C99 header files installed" #endif /* STDC_HEADERS */ #ifdef HAVE_STDINT_H # include #endif #if HAVE_UNISTD_H # include #endif #if HAVE_FCNTL_H # include #endif #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #if HAVE_SYS_SOCKET_H # include #endif #if HAVE_NETDB_H # include #endif #if HAVE_NETINET_IN_SYSTM_H # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_NETINET_IP_H # include #endif #if HAVE_NETINET_IP_ICMP_H # include #endif #ifdef HAVE_NETINET_IP_VAR_H # include #endif #if HAVE_NETINET_IP6_H # include #endif #if HAVE_NETINET_ICMP6_H # include #endif #include "oping.h" #if WITH_DEBUG # define dprintf(...) printf ("%s[%4i]: %-20s: ", __FILE__, __LINE__, __FUNCTION__); printf (__VA_ARGS__) #else # define dprintf(...) /**/ #endif #define PING_ERRMSG_LEN 256 struct pinghost { /* username: name passed in by the user */ char *username; /* hostname: name returned by the reverse lookup */ char *hostname; struct sockaddr_storage *addr; socklen_t addrlen; int addrfamily; int fd; int ident; int sequence; struct timeval *timer; double latency; uint32_t dropped; int recv_ttl; uint8_t recv_qos; char *data; void *context; struct pinghost *next; }; struct pingobj { double timeout; int ttl; int addrfamily; uint8_t qos; char *data; struct sockaddr *srcaddr; socklen_t srcaddrlen; char *device; char errmsg[PING_ERRMSG_LEN]; pinghost_t *head; }; /* * 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 */ static 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, sizeof (obj->errmsg), "%s: %s", function, message); obj->errmsg[sizeof (obj->errmsg) - 1] = 0; } static void ping_set_errno (pingobj_t *obj, int error_number) { sstrerror (error_number, obj->errmsg, sizeof (obj->errmsg)); } static int ping_timeval_add (struct timeval *tv1, struct timeval *tv2, struct timeval *res) { res->tv_sec = tv1->tv_sec + tv2->tv_sec; res->tv_usec = tv1->tv_usec + tv2->tv_usec; while (res->tv_usec > 1000000) { res->tv_usec -= 1000000; res->tv_sec++; } return (0); } static int ping_timeval_sub (struct timeval *tv1, struct timeval *tv2, struct timeval *res) { if ((tv1->tv_sec < tv2->tv_sec) || ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec < tv2->tv_usec))) return (-1); res->tv_sec = tv1->tv_sec - tv2->tv_sec; res->tv_usec = tv1->tv_usec - tv2->tv_usec; assert ((res->tv_sec > 0) || ((res->tv_sec == 0) && (res->tv_usec >= 0))); while (res->tv_usec < 0) { res->tv_usec += 1000000; res->tv_sec--; } return (0); } static uint16_t ping_icmp4_checksum (char *buf, size_t len) { uint32_t sum = 0; uint16_t ret = 0; uint16_t *ptr; for (ptr = (uint16_t *) buf; len > 1; ptr++, len -= 2) sum += *ptr; if (len == 1) { *(char *) &ret = *(char *) ptr; sum += ret; } /* Do this twice to get all possible carries.. */ sum = (sum >> 16) + (sum & 0xFFFF); sum = (sum >> 16) + (sum & 0xFFFF); ret = ~sum; return (ret); } static pinghost_t *ping_receive_ipv4 (pingobj_t *obj, char *buffer, size_t buffer_len) { struct ip *ip_hdr; struct icmp *icmp_hdr; size_t ip_hdr_len; uint16_t recv_checksum; uint16_t calc_checksum; uint16_t ident; uint16_t seq; pinghost_t *ptr; if (buffer_len < sizeof (struct ip)) return (NULL); ip_hdr = (struct ip *) buffer; ip_hdr_len = ip_hdr->ip_hl << 2; if (buffer_len < ip_hdr_len) return (NULL); buffer += ip_hdr_len; buffer_len -= ip_hdr_len; if (buffer_len < sizeof (struct icmp)) return (NULL); icmp_hdr = (struct icmp *) buffer; buffer += sizeof (struct icmp); buffer_len -= sizeof (struct icmp); if (icmp_hdr->icmp_type != ICMP_ECHOREPLY) { dprintf ("Unexpected ICMP type: %i\n", icmp_hdr->icmp_type); return (NULL); } recv_checksum = icmp_hdr->icmp_cksum; icmp_hdr->icmp_cksum = 0; calc_checksum = ping_icmp4_checksum ((char *) icmp_hdr, sizeof (struct icmp) + buffer_len); if (recv_checksum != calc_checksum) { dprintf ("Checksum missmatch: Got 0x%04"PRIx16", " "calculated 0x%04"PRIx16"\n", recv_checksum, calc_checksum); return (NULL); } ident = ntohs (icmp_hdr->icmp_id); seq = ntohs (icmp_hdr->icmp_seq); /* We have to iterate over all hosts, since ICMPv4 packets may * be received on any raw v4 socket. */ for (ptr = obj->head; ptr != NULL; ptr = ptr->next) { dprintf ("hostname = %s, ident = 0x%04x, seq = %i\n", ptr->hostname, ptr->ident, ((ptr->sequence - 1) & 0xFFFF)); if (ptr->addrfamily != AF_INET) continue; if (!timerisset (ptr->timer)) continue; if (ptr->ident != ident) continue; if (((ptr->sequence - 1) & 0xFFFF) != seq) continue; dprintf ("Match found: hostname = %s, ident = 0x%04"PRIx16", " "seq = %"PRIu16"\n", ptr->hostname, ident, seq); break; } if (ptr == NULL) { dprintf ("No match found for ident = 0x%04"PRIx16", seq = %"PRIu16"\n", ident, seq); } if (ptr != NULL){ ptr->recv_ttl = (int) ip_hdr->ip_ttl; ptr->recv_qos = (uint8_t) ip_hdr->ip_tos; } return (ptr); } #ifndef ICMP6_ECHO_REQUEST # ifdef ICMP6_ECHO /* AIX netinet/ip6_icmp.h */ # define ICMP6_ECHO_REQUEST ICMP6_ECHO # else # define ICMP6_ECHO_REQUEST 128 # endif #endif #ifndef ICMP6_ECHO_REPLY # ifdef ICMP6_ECHOREPLY /* AIX netinet/ip6_icmp.h */ # define ICMP6_ECHO_REPLY ICMP6_ECHOREPLY # else # define ICMP6_ECHO_REPLY 129 # endif #endif static pinghost_t *ping_receive_ipv6 (pingobj_t *obj, char *buffer, size_t buffer_len) { struct icmp6_hdr *icmp_hdr; uint16_t ident; uint16_t seq; pinghost_t *ptr; if (buffer_len < sizeof (struct icmp6_hdr)) return (NULL); icmp_hdr = (struct icmp6_hdr *) buffer; buffer += sizeof (struct icmp); buffer_len -= sizeof (struct icmp); if (icmp_hdr->icmp6_type != ICMP6_ECHO_REPLY) { dprintf ("Unexpected ICMP type: %02x\n", icmp_hdr->icmp6_type); return (NULL); } if (icmp_hdr->icmp6_code != 0) { dprintf ("Unexpected ICMP code: %02x\n", icmp_hdr->icmp6_code); return (NULL); } ident = ntohs (icmp_hdr->icmp6_id); seq = ntohs (icmp_hdr->icmp6_seq); /* We have to iterate over all hosts, since ICMPv6 packets may * be received on any raw v6 socket. */ for (ptr = obj->head; ptr != NULL; ptr = ptr->next) { dprintf ("hostname = %s, ident = 0x%04x, seq = %i\n", ptr->hostname, ptr->ident, ((ptr->sequence - 1) & 0xFFFF)); if (ptr->addrfamily != AF_INET6) continue; if (!timerisset (ptr->timer)) continue; if (ptr->ident != ident) continue; if (((ptr->sequence - 1) & 0xFFFF) != seq) continue; dprintf ("Match found: hostname = %s, ident = 0x%04"PRIx16", " "seq = %"PRIu16"\n", ptr->hostname, ident, seq); break; } if (ptr == NULL) { dprintf ("No match found for ident = 0x%04"PRIx16", " "seq = %"PRIu16"\n", ident, seq); } return (ptr); } static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph, struct timeval *now) { /* Note: 'ph' is not necessarily the host object for which we receive a * reply. The right object will be returned by ping_receive_ipv*(). For * now, we can only rely on ph->fd and ph->addrfamily. */ struct timeval diff, pkt_now = *now; pinghost_t *host = NULL; int recv_ttl; uint8_t recv_qos; /* * Set up the receive buffer.. */ struct msghdr msghdr; struct cmsghdr *cmsg; char payload_buffer[4096]; ssize_t payload_buffer_len; char control_buffer[4096]; struct iovec payload_iovec; memset (&payload_iovec, 0, sizeof (payload_iovec)); payload_iovec.iov_base = payload_buffer; payload_iovec.iov_len = sizeof (payload_buffer); memset (&msghdr, 0, sizeof (msghdr)); /* unspecified source address */ msghdr.msg_name = NULL; msghdr.msg_namelen = 0; /* output buffer vector, see readv(2) */ msghdr.msg_iov = &payload_iovec; msghdr.msg_iovlen = 1; /* output buffer for control messages */ msghdr.msg_control = control_buffer; 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 (ph->fd, &msghdr, /* flags = */ 0); if (payload_buffer_len < 0) { #if WITH_DEBUG char errbuf[PING_ERRMSG_LEN]; dprintf ("recvfrom: %s\n", sstrerror (errno, errbuf, sizeof (errbuf))); #endif return (-1); } dprintf ("Read %zi bytes from fd = %i\n", payload_buffer_len, ph->fd); /* Iterate over all auxiliary data in msghdr */ recv_ttl = -1; recv_qos = 0; for (cmsg = CMSG_FIRSTHDR (&msghdr); /* {{{ */ cmsg != NULL; cmsg = CMSG_NXTHDR (&msghdr, cmsg)) { if (cmsg->cmsg_level == SOL_SOCKET) { #ifdef SO_TIMESTAMP if (cmsg->cmsg_type == SO_TIMESTAMP) memcpy (&pkt_now, CMSG_DATA (cmsg), sizeof (pkt_now)); #endif /* SO_TIMESTAMP */ } else if (ph->addrfamily == AF_INET) /* {{{ */ { if (cmsg->cmsg_level != IPPROTO_IP) continue; if (cmsg->cmsg_type == IP_TOS) { memcpy (&recv_qos, CMSG_DATA (cmsg), sizeof (recv_qos)); dprintf ("TOSv4 = 0x%02"PRIx8";\n", recv_qos); } else if (cmsg->cmsg_type == IP_TTL) { memcpy (&recv_ttl, CMSG_DATA (cmsg), sizeof (recv_ttl)); dprintf ("TTLv4 = %i;\n", recv_ttl); } else { dprintf ("Not handling option %i.\n", cmsg->cmsg_type); } } /* }}} */ else if (ph->addrfamily == AF_INET6) /* {{{ */ { if (cmsg->cmsg_level != IPPROTO_IPV6) continue; if (cmsg->cmsg_type == IPV6_TCLASS) { memcpy (&recv_qos, CMSG_DATA (cmsg), sizeof (recv_qos)); dprintf ("TOSv6 = 0x%02"PRIx8";\n", recv_qos); } else #ifdef IPV6_HOPLIMIT if (cmsg->cmsg_type == IPV6_HOPLIMIT) { memcpy (&recv_ttl, CMSG_DATA (cmsg), sizeof (recv_ttl)); dprintf ("TTLv6 = %i;\n", recv_ttl); } else #endif #ifdef IPV6_UNICAST_HOPS if (cmsg->cmsg_type == IPV6_UNICAST_HOPS) { memcpy (&recv_ttl, CMSG_DATA (cmsg), sizeof (recv_ttl)); dprintf ("TTLv6 = %i;\n", recv_ttl); } else #endif #ifdef IPV6_MULTICAST_HOPS if (cmsg->cmsg_type == IPV6_MULTICAST_HOPS) { memcpy (&recv_ttl, CMSG_DATA (cmsg), sizeof (recv_ttl)); dprintf ("TTLv6 = %i;\n", recv_ttl); } else #endif { dprintf ("Not handling option %i.\n", cmsg->cmsg_type); } } /* }}} */ else { dprintf ("Don't know how to handle " "unknown protocol %i.\n", cmsg->cmsg_level); } } /* }}} for (cmsg) */ if (ph->addrfamily == AF_INET) { host = ping_receive_ipv4 (obj, payload_buffer, payload_buffer_len); if (host == NULL) return (-1); } else if (ph->addrfamily == AF_INET6) { host = ping_receive_ipv6 (obj, payload_buffer, payload_buffer_len); if (host == NULL) return (-1); } else { dprintf ("ping_receive_one: Unknown address family %i.\n", ph->addrfamily); return (-1); } dprintf ("rcvd: %12i.%06i\n", (int) pkt_now.tv_sec, (int) pkt_now.tv_usec); dprintf ("sent: %12i.%06i\n", (int) host->timer->tv_sec, (int) host->timer->tv_usec); if (ping_timeval_sub (&pkt_now, host->timer, &diff) < 0) { timerclear (host->timer); return (-1); } dprintf ("diff: %12i.%06i\n", (int) diff.tv_sec, (int) diff.tv_usec); if (recv_ttl >= 0) host->recv_ttl = recv_ttl; host->recv_qos = recv_qos; host->latency = ((double) diff.tv_usec) / 1000.0; host->latency += ((double) diff.tv_sec) * 1000.0; timerclear (host->timer); return (0); } /* Blocks until a packet was received from all hosts or the timeout is reached. * When interrupted, (-EINTR) is returned. On error, -1 is returned. On * success, returns zero. */ static int ping_receive_all (pingobj_t *obj) { fd_set read_fds; fd_set err_fds; int num_fds; int max_fd; pinghost_t *ph; pinghost_t *ptr; struct timeval endtime; struct timeval nowtime; struct timeval timeout; int status; int ret; ph = obj->head; ret = 0; for (ptr = ph; ptr != NULL; ptr = ptr->next) { ptr->latency = -1.0; ptr->recv_ttl = -1; } if (gettimeofday (&nowtime, NULL) == -1) { ping_set_errno (obj, errno); return (-1); } /* Set up timeout */ timeout.tv_sec = (time_t) obj->timeout; timeout.tv_usec = (suseconds_t) (1000000 * (obj->timeout - ((double) timeout.tv_sec))); dprintf ("Set timeout to %i.%06i seconds\n", (int) timeout.tv_sec, (int) timeout.tv_usec); ping_timeval_add (&nowtime, &timeout, &endtime); while (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, &read_fds); FD_SET (ptr->fd, &err_fds); num_fds++; if (max_fd < ptr->fd) max_fd = ptr->fd; } if (num_fds == 0) break; if (gettimeofday (&nowtime, NULL) == -1) { ping_set_errno (obj, errno); return (-1); } if (ping_timeval_sub (&endtime, &nowtime, &timeout) == -1) break; dprintf ("Waiting on %i sockets for %i.%06i seconds\n", num_fds, (int) timeout.tv_sec, (int) timeout.tv_usec); status = select (max_fd + 1, &read_fds, NULL, &err_fds, &timeout); if (gettimeofday (&nowtime, NULL) == -1) { ping_set_errno (obj, errno); return (-1); } if ((status == -1) && (errno == EINTR)) { dprintf ("select was interrupted by signal..\n"); ping_set_errno (obj, EINTR); return (-EINTR); } else if (status < 0) { #if WITH_DEBUG char errbuf[PING_ERRMSG_LEN]; dprintf ("select: %s\n", sstrerror (errno, errbuf, sizeof (errbuf))); #endif break; } else if (status == 0) { dprintf ("select timed out\n"); for (ptr = ph; ptr != NULL; ptr = ptr->next) if (ptr->latency < 0.0) ptr->dropped++; break; } for (ptr = ph; ptr != NULL; ptr = ptr->next) { 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) */ return (ret); } /* int ping_receive_all */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Sending functions: * * * * ping_send_all * * +-> ping_send_one_ipv4 * * `-> ping_send_one_ipv6 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static ssize_t ping_sendto (pingobj_t *obj, pinghost_t *ph, const void *buf, size_t buflen) { ssize_t ret; if (gettimeofday (ph->timer, NULL) == -1) { timerclear (ph->timer); return (-1); } ret = sendto (ph->fd, buf, buflen, 0, (struct sockaddr *) ph->addr, ph->addrlen); if (ret < 0) { #if defined(EHOSTUNREACH) if (errno == EHOSTUNREACH) return (0); #endif #if defined(ENETUNREACH) if (errno == ENETUNREACH) return (0); #endif ping_set_errno (obj, errno); } return (ret); } static int ping_send_one_ipv4 (pingobj_t *obj, pinghost_t *ph) { struct icmp *icmp4; int status; char buf[4096]; int buflen; char *data; int datalen; dprintf ("ph->hostname = %s\n", ph->hostname); memset (buf, '\0', sizeof (buf)); icmp4 = (struct icmp *) buf; data = (char *) (icmp4 + 1); icmp4->icmp_type = ICMP_ECHO; icmp4->icmp_code = 0; icmp4->icmp_cksum = 0; icmp4->icmp_id = htons (ph->ident); icmp4->icmp_seq = htons (ph->sequence); buflen = 4096 - sizeof (struct icmp); strncpy (data, ph->data, buflen); datalen = strlen (data); buflen = datalen + sizeof (struct icmp); icmp4->icmp_cksum = ping_icmp4_checksum (buf, buflen); dprintf ("Sending ICMPv4 package with ID 0x%04x\n", ph->ident); status = ping_sendto (obj, ph, buf, buflen); if (status < 0) { perror ("ping_sendto"); return (-1); } dprintf ("sendto: status = %i\n", status); return (0); } static int ping_send_one_ipv6 (pingobj_t *obj, pinghost_t *ph) { struct icmp6_hdr *icmp6; int status; char buf[4096]; int buflen; char *data; int datalen; dprintf ("ph->hostname = %s\n", ph->hostname); memset (buf, '\0', sizeof (buf)); icmp6 = (struct icmp6_hdr *) buf; data = (char *) (icmp6 + 1); icmp6->icmp6_type = ICMP6_ECHO_REQUEST; icmp6->icmp6_code = 0; /* The checksum will be calculated by the TCP/IP stack. */ /* FIXME */ icmp6->icmp6_cksum = 0; icmp6->icmp6_id = htons (ph->ident); icmp6->icmp6_seq = htons (ph->sequence); buflen = 4096 - sizeof (struct icmp6_hdr); strncpy (data, ph->data, buflen); datalen = strlen (data); buflen = datalen + sizeof (struct icmp6_hdr); dprintf ("Sending ICMPv6 package with ID 0x%04x\n", ph->ident); status = ping_sendto (obj, ph, buf, buflen); if (status < 0) { perror ("ping_sendto"); return (-1); } dprintf ("sendto: status = %i\n", status); return (0); } static int ping_send_all (pingobj_t *obj) { pinghost_t *ph; pinghost_t *ptr; int ret; ret = 0; ph = obj->head; for (ptr = ph; ptr != NULL; ptr = ptr->next) { /* start timer.. The GNU `ping6' starts the timer before * sending the packet, so I will do that too */ if (gettimeofday (ptr->timer, NULL) == -1) { #if WITH_DEBUG char errbuf[PING_ERRMSG_LEN]; dprintf ("gettimeofday: %s\n", sstrerror (errno, errbuf, sizeof (errbuf))); #endif timerclear (ptr->timer); ret--; continue; } else { dprintf ("timer set for hostname = %s\n", ptr->hostname); } if (ptr->addrfamily == AF_INET6) { dprintf ("Sending ICMPv6 echo request to `%s'\n", ptr->hostname); if (ping_send_one_ipv6 (obj, ptr) != 0) { timerclear (ptr->timer); ret--; continue; } } else if (ptr->addrfamily == AF_INET) { dprintf ("Sending ICMPv4 echo request to `%s'\n", ptr->hostname); if (ping_send_one_ipv4 (obj, ptr) != 0) { timerclear (ptr->timer); ret--; continue; } } else /* this should not happen */ { dprintf ("Unknown address family: %i\n", ptr->addrfamily); timerclear (ptr->timer); ret--; continue; } ptr->sequence++; } return (ret); } /* * Set the TTL of a socket protocol independently. */ static int ping_set_ttl (pinghost_t *ph, int ttl) { int ret = -2; if (ph->addrfamily == AF_INET) { dprintf ("Setting TTLv4 to %i\n", ttl); ret = setsockopt (ph->fd, IPPROTO_IP, IP_TTL, &ttl, sizeof (ttl)); } else if (ph->addrfamily == AF_INET6) { dprintf ("Setting TTLv6 to %i\n", ttl); ret = setsockopt (ph->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof (ttl)); } return (ret); } /* * Set the TOS of a socket protocol independently. * * Using SOL_SOCKET / SO_PRIORITY might be a protocol independent way to * set this. See socket(7) for details. */ static int ping_set_qos (pingobj_t *obj, pinghost_t *ph, uint8_t qos) { int ret = EINVAL; char errbuf[PING_ERRMSG_LEN]; if (ph->addrfamily == AF_INET) { dprintf ("Setting TP_TOS to %#04"PRIx8"\n", qos); ret = setsockopt (ph->fd, IPPROTO_IP, IP_TOS, &qos, sizeof (qos)); if (ret != 0) { ret = errno; ping_set_error (obj, "ping_set_qos", sstrerror (ret, errbuf, sizeof (errbuf))); dprintf ("Setting TP_TOS failed: %s\n", errbuf); } } else if (ph->addrfamily == AF_INET6) { /* IPV6_TCLASS requires an "int". */ int tmp = (int) qos; dprintf ("Setting IPV6_TCLASS to %#04"PRIx8" (%i)\n", qos, tmp); ret = setsockopt (ph->fd, IPPROTO_IPV6, IPV6_TCLASS, &tmp, sizeof (tmp)); if (ret != 0) { ret = errno; ping_set_error (obj, "ping_set_qos", sstrerror (ret, errbuf, sizeof (errbuf))); dprintf ("Setting IPV6_TCLASS failed: %s\n", errbuf); } } return (ret); } static int ping_get_ident (void) { int fd; static int did_seed = 0; int retval; if (did_seed == 0) { if ((fd = open ("/dev/urandom", O_RDONLY)) != -1) { unsigned int seed; if (read (fd, &seed, sizeof (seed)) != -1) { did_seed = 1; dprintf ("Random seed: %#x\n", seed); srandom (seed); } close (fd); } #if WITH_DEBUG else { char errbuf[PING_ERRMSG_LEN]; dprintf ("open (/dev/urandom): %s\n", sstrerror (errno, errbuf, sizeof (errbuf))); } #endif } retval = (int) random (); dprintf ("Random number: %#x\n", retval); return (retval); } static pinghost_t *ping_alloc (void) { pinghost_t *ph; size_t ph_size; ph_size = sizeof (pinghost_t) + sizeof (struct sockaddr_storage) + sizeof (struct timeval); ph = (pinghost_t *) malloc (ph_size); if (ph == NULL) return (NULL); memset (ph, '\0', ph_size); ph->timer = (struct timeval *) (ph + 1); ph->addr = (struct sockaddr_storage *) (ph->timer + 1); ph->addrlen = sizeof (struct sockaddr_storage); ph->fd = -1; ph->latency = -1.0; ph->dropped = 0; ph->ident = ping_get_ident () & 0xFFFF; return (ph); } static void ping_free (pinghost_t *ph) { if (ph->fd >= 0) close (ph->fd); if (ph->username != NULL) free (ph->username); if (ph->hostname != NULL) free (ph->hostname); if (ph->data != NULL) free (ph->data); free (ph); } /* * public methods */ const char *ping_get_error (pingobj_t *obj) { if (obj == NULL) return (NULL); return (obj->errmsg); } pingobj_t *ping_construct (void) { pingobj_t *obj; if ((obj = (pingobj_t *) malloc (sizeof (pingobj_t))) == NULL) return (NULL); memset (obj, 0, sizeof (pingobj_t)); obj->timeout = PING_DEF_TIMEOUT; obj->ttl = PING_DEF_TTL; obj->addrfamily = PING_DEF_AF; obj->data = strdup (PING_DEF_DATA); obj->qos = 0; return (obj); } void ping_destroy (pingobj_t *obj) { pinghost_t *current; pinghost_t *next; if (obj == NULL) return; current = obj->head; next = NULL; while (current != NULL) { next = current->next; ping_free (current); current = next; } if (obj->data != NULL) free (obj->data); if (obj->srcaddr != NULL) free (obj->srcaddr); if (obj->device != NULL) free (obj->device); free (obj); return; } int ping_setopt (pingobj_t *obj, int option, void *value) { int ret = 0; if ((obj == NULL) || (value == NULL)) return (-1); switch (option) { case PING_OPT_QOS: { pinghost_t *ph; obj->qos = *((uint8_t *) value); for (ph = obj->head; ph != NULL; ph = ph->next) ping_set_qos (obj, ph, obj->qos); break; } case PING_OPT_TIMEOUT: obj->timeout = *((double *) value); if (obj->timeout < 0.0) { obj->timeout = PING_DEF_TIMEOUT; ret = -1; } break; case PING_OPT_TTL: obj->ttl = *((int *) value); if ((obj->ttl < 1) || (obj->ttl > 255)) { 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: obj->addrfamily = *((int *) value); if ((obj->addrfamily != AF_UNSPEC) && (obj->addrfamily != AF_INET) && (obj->addrfamily != AF_INET6)) { obj->addrfamily = PING_DEF_AF; ret = -1; } if (obj->srcaddr != NULL) { free (obj->srcaddr); obj->srcaddr = NULL; } break; case PING_OPT_DATA: if (obj->data != NULL) { free (obj->data); obj->data = NULL; } obj->data = strdup ((const char *) value); break; case PING_OPT_SOURCE: { char *hostname = (char *) value; struct addrinfo ai_hints; struct addrinfo *ai_list; int status; #if WITH_DEBUG if (obj->addrfamily != AF_UNSPEC) { dprintf ("Resetting obj->addrfamily to AF_UNSPEC.\n"); } #endif memset ((void *) &ai_hints, '\0', sizeof (ai_hints)); ai_hints.ai_family = obj->addrfamily = AF_UNSPEC; #if defined(AI_ADDRCONFIG) ai_hints.ai_flags = AI_ADDRCONFIG; #endif 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) ? sstrerror (errno, errbuf, sizeof (errbuf)) : #endif gai_strerror (status)); ret = -1; break; } #if WITH_DEBUG if (ai_list->ai_next != NULL) { dprintf ("hostname = `%s' is ambiguous.\n", hostname); } #endif if (obj->srcaddr == NULL) { obj->srcaddrlen = 0; obj->srcaddr = malloc (sizeof (struct sockaddr_storage)); if (obj->srcaddr == NULL) { ping_set_errno (obj, errno); ret = -1; freeaddrinfo (ai_list); break; } } 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); obj->srcaddrlen = ai_list->ai_addrlen; obj->addrfamily = ai_list->ai_family; freeaddrinfo (ai_list); } /* 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) */ return (ret); } /* int ping_setopt */ int ping_send (pingobj_t *obj) { if (obj == NULL) return (-1); if (ping_send_all (obj) < 0) return (-1); return (ping_receive_all (obj)); } static pinghost_t *ping_host_search (pinghost_t *ph, const char *host) { while (ph != NULL) { if (strcasecmp (ph->username, host) == 0) break; ph = ph->next; } return (ph); } int ping_host_add (pingobj_t *obj, const char *host) { pinghost_t *ph; struct addrinfo ai_hints; 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) return (0); memset (&ai_hints, '\0', sizeof (ai_hints)); ai_hints.ai_flags = 0; #ifdef AI_ADDRCONFIG ai_hints.ai_flags |= AI_ADDRCONFIG; #endif #ifdef AI_CANONNAME ai_hints.ai_flags |= AI_CANONNAME; #endif ai_hints.ai_family = obj->addrfamily; ai_hints.ai_socktype = SOCK_RAW; if ((ph = ping_alloc ()) == NULL) { dprintf ("Out of memory!\n"); return (-1); } if ((ph->username = strdup (host)) == NULL) { dprintf ("Out of memory!\n"); ping_set_errno (obj, errno); ping_free (ph); return (-1); } if ((ph->hostname = strdup (host)) == NULL) { dprintf ("Out of memory!\n"); ping_set_errno (obj, errno); ping_free (ph); return (-1); } /* obj->data is not garuanteed to be != NULL */ if ((ph->data = strdup (obj->data == NULL ? PING_DEF_DATA : obj->data)) == NULL) { dprintf ("Out of memory!\n"); ping_set_errno (obj, 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) ? sstrerror (errno, errbuf, sizeof (errbuf)) : #endif gai_strerror (ai_return)); ping_free (ph); return (-1); } if (ai_list == NULL) ping_set_error (obj, "getaddrinfo", "No hosts returned"); for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { ph->fd = -1; if (ai_ptr->ai_family == AF_INET) { ai_ptr->ai_socktype = SOCK_RAW; ai_ptr->ai_protocol = IPPROTO_ICMP; } else if (ai_ptr->ai_family == AF_INET6) { ai_ptr->ai_socktype = SOCK_RAW; ai_ptr->ai_protocol = IPPROTO_ICMPV6; } else { char errmsg[PING_ERRMSG_LEN]; snprintf (errmsg, PING_ERRMSG_LEN, "Unknown `ai_family': %i", ai_ptr->ai_family); errmsg[PING_ERRMSG_LEN - 1] = '\0'; dprintf ("%s", errmsg); ping_set_error (obj, "getaddrinfo", errmsg); continue; } /* TODO: Move this to a static function `ping_open_socket' and * call it whenever the socket dies. */ ph->fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); if (ph->fd == -1) { #if WITH_DEBUG char errbuf[PING_ERRMSG_LEN]; dprintf ("socket: %s\n", sstrerror (errno, errbuf, sizeof (errbuf))); #endif ping_set_errno (obj, errno); continue; } if (obj->srcaddr != NULL) { assert (obj->srcaddrlen > 0); assert (obj->srcaddrlen <= sizeof (struct sockaddr_storage)); if (bind (ph->fd, obj->srcaddr, obj->srcaddrlen) == -1) { #if WITH_DEBUG char errbuf[PING_ERRMSG_LEN]; dprintf ("bind: %s\n", sstrerror (errno, errbuf, sizeof (errbuf))); #endif ping_set_errno (obj, errno); close (ph->fd); ph->fd = -1; continue; } } #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 (SO_BINDTODEVICE): %s\n", sstrerror (errno, errbuf, sizeof (errbuf))); #endif ping_set_errno (obj, errno); close (ph->fd); ph->fd = -1; continue; } } #endif /* SO_BINDTODEVICE */ #ifdef SO_TIMESTAMP if (1) /* {{{ */ { int status; int opt = 1; status = setsockopt (ph->fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof (opt)); if (status != 0) { #if WITH_DEBUG char errbuf[PING_ERRMSG_LEN]; dprintf ("setsockopt (SO_TIMESTAMP): %s\n", sstrerror (errno, errbuf, sizeof (errbuf))); #endif ping_set_errno (obj, errno); close (ph->fd); ph->fd = -1; continue; } } /* }}} if (1) */ #endif /* SO_TIMESTAMP */ 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); ph->addrlen = ai_ptr->ai_addrlen; ph->addrfamily = ai_ptr->ai_family; #ifdef AI_CANONNAME if ((ai_ptr->ai_canonname != NULL) && (strcmp (ph->hostname, ai_ptr->ai_canonname) != 0)) { char *old_hostname; dprintf ("ph->hostname = %s; ai_ptr->ai_canonname = %s;\n", ph->hostname, ai_ptr->ai_canonname); old_hostname = ph->hostname; if ((ph->hostname = strdup (ai_ptr->ai_canonname)) == NULL) { /* strdup failed, falling back to old hostname */ ph->hostname = old_hostname; } else if (old_hostname != NULL) { free (old_hostname); } } #endif /* AI_CANONNAME */ if (ph->addrfamily == AF_INET) { int opt; #ifdef IP_RECVTOS /* Enable receiving the TOS field */ opt = 1; setsockopt (ph->fd, IPPROTO_IP, IP_RECVTOS, &opt, sizeof (opt)); #endif /* IP_RECVTOS */ /* Enable receiving the TTL field */ opt = 1; setsockopt (ph->fd, IPPROTO_IP, IP_RECVTTL, &opt, sizeof (opt)); } #if defined(IPV6_RECVHOPLIMIT) || defined(IPV6_RECVTCLASS) else if (ph->addrfamily == AF_INET6) { int opt; # if defined(IPV6_RECVHOPLIMIT) /* For details see RFC 3542, section 6.3. */ opt = 1; setsockopt (ph->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &opt, sizeof (opt)); # endif /* IPV6_RECVHOPLIMIT */ # if defined(IPV6_RECVTCLASS) /* For details see RFC 3542, section 6.5. */ opt = 1; setsockopt (ph->fd, IPPROTO_IPV6, IPV6_RECVTCLASS, &opt, sizeof (opt)); # endif /* IPV6_RECVTCLASS */ } #endif /* IPV6_RECVHOPLIMIT || IPV6_RECVTCLASS */ break; } /* for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) */ freeaddrinfo (ai_list); if (ph->fd < 0) { ping_free (ph); return (-1); } /* * Adding in the front is much easier, but then the iterator will * return the host that was added last as first host. That's just not * nice. -octo */ if (obj->head == NULL) { obj->head = ph; } else { pinghost_t *hptr; hptr = obj->head; while (hptr->next != NULL) hptr = hptr->next; assert ((hptr != NULL) && (hptr->next == NULL)); hptr->next = ph; } ping_set_ttl (ph, obj->ttl); ping_set_qos (obj, ph, obj->qos); return (0); } /* int ping_host_add */ 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; while (cur != NULL) { if (strcasecmp (host, cur->username) == 0) break; pre = cur; cur = cur->next; } if (cur == NULL) { ping_set_error (obj, "ping_host_remove", "Host not found"); return (-1); } if (pre == NULL) obj->head = cur->next; else pre->next = cur->next; ping_free (cur); return (0); } 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); } int ping_iterator_get_info (pingobj_iter_t *iter, int info, void *buffer, size_t *buffer_len) { int ret = EINVAL; 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: ret = ENOMEM; *buffer_len = strlen (iter->username) + 1; if (orig_buffer_len <= *buffer_len) break; /* Since (orig_buffer_len > *buffer_len) `strncpy' * will copy `*buffer_len' and pad the rest of * `buffer' with null-bytes */ strncpy (buffer, iter->username, orig_buffer_len); ret = 0; break; case PING_INFO_HOSTNAME: ret = ENOMEM; *buffer_len = strlen (iter->hostname) + 1; if (orig_buffer_len < *buffer_len) break; /* Since (orig_buffer_len > *buffer_len) `strncpy' * will copy `*buffer_len' and pad the rest of * `buffer' with null-bytes */ strncpy (buffer, iter->hostname, orig_buffer_len); ret = 0; break; case PING_INFO_ADDRESS: ret = getnameinfo ((struct sockaddr *) iter->addr, iter->addrlen, (char *) buffer, *buffer_len, NULL, 0, NI_NUMERICHOST); if (ret != 0) { if ((ret == EAI_MEMORY) #ifdef EAI_OVERFLOW || (ret == EAI_OVERFLOW) #endif ) ret = ENOMEM; #if defined(EAI_SYSTEM) else if (ret == EAI_SYSTEM) ret = errno; #endif else ret = EINVAL; } break; case PING_INFO_FAMILY: ret = ENOMEM; *buffer_len = sizeof (int); if (orig_buffer_len < sizeof (int)) break; *((int *) buffer) = iter->addrfamily; ret = 0; break; case PING_INFO_LATENCY: ret = ENOMEM; *buffer_len = sizeof (double); if (orig_buffer_len < sizeof (double)) break; *((double *) buffer) = iter->latency; ret = 0; break; case PING_INFO_DROPPED: ret = ENOMEM; *buffer_len = sizeof (uint32_t); if (orig_buffer_len < sizeof (uint32_t)) break; *((uint32_t *) buffer) = iter->dropped; ret = 0; break; case PING_INFO_SEQUENCE: ret = ENOMEM; *buffer_len = sizeof (unsigned int); if (orig_buffer_len < sizeof (unsigned int)) break; *((unsigned int *) buffer) = (unsigned int) iter->sequence; ret = 0; break; case PING_INFO_IDENT: ret = ENOMEM; *buffer_len = sizeof (uint16_t); if (orig_buffer_len < sizeof (uint16_t)) break; *((uint16_t *) buffer) = (uint16_t) iter->ident; ret = 0; break; case PING_INFO_DATA: ret = ENOMEM; *buffer_len = strlen (iter->data); if (orig_buffer_len < *buffer_len) break; strncpy ((char *) buffer, iter->data, orig_buffer_len); ret = 0; break; case PING_INFO_RECV_TTL: ret = ENOMEM; *buffer_len = sizeof (int); if (orig_buffer_len < sizeof (int)) break; *((int *) buffer) = iter->recv_ttl; ret = 0; break; case PING_INFO_RECV_QOS: ret = ENOMEM; if (*buffer_len>sizeof(unsigned)) *buffer_len=sizeof(unsigned); if (!*buffer_len) *buffer_len=1; if (orig_buffer_len < *buffer_len) break; memcpy(buffer,&iter->recv_qos,*buffer_len); ret = 0; break; } return (ret); } /* ping_iterator_get_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; } liboping-1.8.0/src/Makefile.am0000644037772200116100000000351212411751420013100 00000000000000AUTOMAKE_OPTIONS = foreign no-dependencies SUBDIRS = mans if COMPILER_IS_GCC AM_CFLAGS = -Wall -Werror endif include_HEADERS = oping.h lib_LTLIBRARIES = liboping.la # version-info: current:revision:age # # * If the library source code has changed at all since the last update, then # increment revision (‘c:r:a’ becomes ‘c:r+1:a’). # * If any interfaces have been added, removed, or changed since the last # update, increment current, and set revision to 0. # * If any interfaces have been added since the last public release, then # increment age. # * If any interfaces have been removed since the last public release, then # set age to 0. # # liboping_la_SOURCES = oping.h liboping.c liboping_la_CPPFLAGS = $(AM_CPPFLAGS) liboping_la_LDFLAGS = $(AM_LDFLAGS) -version-info @LIBOPING_CURRENT@:@LIBOPING_REVISION@:@LIBOPING_AGE@ liboping_la_LIBADD = $(LIBOPING_PC_LIBS_PRIVATE) pkgconfig_DATA = liboping.pc MOSTLYCLEANFILES = $(pkgconfig_DATA) bin_PROGRAMS = oping oping_SOURCES = oping.c oping_LDADD = liboping.la -lm if BUILD_WITH_LIBRT oping_LDADD += -lrt endif if BUILD_WITH_LIBNCURSES bin_PROGRAMS += noping noping_SOURCES = oping.c noping_CPPFLAGS = $(AM_CPPFLAGS) -DUSE_NCURSES=1 noping_LDADD = liboping.la -lm $(NCURSES_LIB) if BUILD_WITH_LIBRT noping_LDADD += -lrt endif endif # BUILD_WITH_LIBNCURSES install-exec-hook: @if test "x0" = "x$$UID"; then \ if test "xLinux" = "x`uname -s`"; then \ echo "Setting CAP_NET_RAW capability on binaries."; \ setcap cap_net_raw=ep $(DESTDIR)$(bindir)/oping || true; \ setcap cap_net_raw=ep $(DESTDIR)$(bindir)/noping || true; \ else \ echo "Setting set-UID bit on binaries."; \ chmod u+s $(DESTDIR)$(bindir)/oping || true; \ chmod u+s $(DESTDIR)$(bindir)/noping || true; \ fi; \ fi liboping-1.8.0/src/mans/0000755037772200116100000000000012433400211012052 500000000000000liboping-1.8.0/src/mans/ping_get_error.30000644037772200116100000001076311631537212015105 00000000000000.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "ping_get_error 3" .TH ping_get_error 3 "2011-09-06" "1.6.2" "liboping" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" ping_get_error \- Return the last error message .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& #include \& \& const char *ping_get_error (pingobj_t *obj); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \fBping_get_error\fR method returns an error message indicating the last error encountered. \fBThis method is not thread safe whatsoever.\fR .SH "RETURN VALUE" .IX Header "RETURN VALUE" A \f(CW\*(C`const\*(C'\fR string representing the last error or an empty string if no error was encountered yet. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIliboping\fR\|(3) .SH "AUTHOR" .IX Header "AUTHOR" liboping is written by Florian \*(L"octo\*(R" Forster . Its homepage can be found at . .PP Copyright (c) 2005\-2011 by Florian \*(L"octo\*(R" Forster. liboping-1.8.0/src/mans/ping_send.pod0000644037772200116100000000250111631533276014463 00000000000000=head1 NAME ping_send - Send ICMP echo requests to all associated hosts and wait for ICMP echo responses to arrive =head1 SYNOPSIS #include int ping_send (pingobj_t *obj); =head1 DESCRIPTION The B method is the actual workhorse of this library. It crafts ICMP packets for the hosts associated with I and sends them via the corresponding sockets. It then waits for echo responses and receives them, writing latency information for each host. The method returns after all echo replies have been read or the timeout (set with L) is reached. After this function returns you will most likely iterate over all hosts using L and ping_iterator_next (described in the same manual page) and call L on each host. =head1 RETURN VALUE B returns the number of echo replies received or a value less than zero if an error occurred. Use L to receive an error message. =head1 SEE ALSO L, L, L, L, L, L =head1 AUTHOR liboping is written by Florian "octo" Forster Eocto at verplant.orgE. Its homepage can be found at L. Copyright (c) 2005-2011 by Florian "octo" Forster. liboping-1.8.0/src/mans/ping_iterator_get.pod0000644037772200116100000000244111631533276016225 00000000000000=head1 NAME ping_iterator_get, ping_iterator_next - Iterate over all hosts of a liboping object =head1 SYNOPSIS #include pingobj_iter_t *ping_iterator_get (pingobj_t *obj); pingobj_iter_t *ping_iterator_next (pingobj_iter_t *iter) =head1 DESCRIPTION These two functions can be used to iterate over all hosts associated with a liboping object. You can use these methods as follows: pingobj_iter_t *iter; for (iter = ping_iterator_get (obj); iter != NULL; iter = ping_iterator_next (iter)) { ...; } To get usable information from an iterator object (which is also an opaque data type, just like the liboping object itself) use L and L. =head1 RETURN VALUE The B returns an iterator for I or NULL if no host is associated with I. The B returns an iterator for the host following I or NULL if the last host has been reached. =head1 SEE ALSO L, L, L, L =head1 AUTHOR liboping is written by Florian "octo" Forster Eocto at verplant.orgE. Its homepage can be found at L. Copyright (c) 2005-2011 by Florian "octo" Forster. liboping-1.8.0/src/mans/ping_send.30000644037772200116100000001230611631537212014041 00000000000000.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "ping_send 3" .TH ping_send 3 "2011-09-06" "1.6.2" "liboping" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" ping_send \- Send ICMP echo requests to all associated hosts and wait for ICMP echo responses to arrive .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& #include \& \& int ping_send (pingobj_t *obj); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \fBping_send\fR method is the actual workhorse of this library. It crafts \s-1ICMP\s0 packets for the hosts associated with \fIobj\fR and sends them via the corresponding sockets. It then waits for echo responses and receives them, writing latency information for each host. The method returns after all echo replies have been read or the timeout (set with \fIping_setopt\fR\|(3)) is reached. .PP After this function returns you will most likely iterate over all hosts using \&\fIping_iterator_get\fR\|(3) and ping_iterator_next (described in the same manual page) and call \fIping_iterator_get_info\fR\|(3) on each host. .SH "RETURN VALUE" .IX Header "RETURN VALUE" \&\fBping_send\fR returns the number of echo replies received or a value less than zero if an error occurred. Use \fIping_get_error\fR\|(3) to receive an error message. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIping_construct\fR\|(3), \&\fIping_setopt\fR\|(3), \&\fIping_iterator_get\fR\|(3), \&\fIping_iterator_get_info\fR\|(3), \&\fIping_get_error\fR\|(3), \&\fIliboping\fR\|(3) .SH "AUTHOR" .IX Header "AUTHOR" liboping is written by Florian \*(L"octo\*(R" Forster . Its homepage can be found at . .PP Copyright (c) 2005\-2011 by Florian \*(L"octo\*(R" Forster. liboping-1.8.0/src/mans/ping_get_error.pod0000644037772200116100000000123511631533276015525 00000000000000=head1 NAME ping_get_error - Return the last error message =head1 SYNOPSIS #include const char *ping_get_error (pingobj_t *obj); =head1 DESCRIPTION The B method returns an error message indicating the last error encountered. B =head1 RETURN VALUE A C string representing the last error or an empty string if no error was encountered yet. =head1 SEE ALSO L =head1 AUTHOR liboping is written by Florian "octo" Forster Eocto at verplant.orgE. Its homepage can be found at L. Copyright (c) 2005-2011 by Florian "octo" Forster. liboping-1.8.0/src/mans/Makefile.am0000644037772200116100000000124211536627627014056 00000000000000man_PODS = liboping.pod ping_construct.pod ping_setopt.pod ping_host_add.pod \ ping_send.pod ping_get_error.pod ping_iterator_get.pod \ ping_iterator_get_info.pod ping_iterator_get_context.pod oping.pod man_MANS = liboping.3 ping_construct.3 ping_setopt.3 ping_host_add.3 \ ping_send.3 ping_get_error.3 ping_iterator_get.3 \ ping_iterator_get_info.3 ping_iterator_get_context.3 oping.8 EXTRA_DIST = $(man_MANS) $(man_PODS) .pod.1: pod2man --section=1 --release=$(VERSION) --center=$(PACKAGE) $< >$@ .pod.3: pod2man --section=3 --release=$(VERSION) --center=$(PACKAGE) $< >$@ .pod.8: pod2man --section=8 --release=$(VERSION) --center=$(PACKAGE) $< >$@ liboping-1.8.0/src/mans/oping.pod0000644037772200116100000002236412433377745013652 00000000000000=head1 NAME oping - send ICMP ECHO_REQUEST to network hosts =head1 SYNOPSIS B [B<-4> | B<-6>] [B<-c> I] [B<-i> I] I [I [I ...]] B [B<-4> | B<-6>] [B<-c> I] [B<-i> I] B<-f> I B [B<-4> | B<-6>] [B<-c> I] [B<-i> I] I [I [I ...]] B [B<-4> | B<-6>] [B<-c> I] [B<-i> I] B<-f> I =head1 DESCRIPTION B uses ICMPv4 or ICMPv6 ECHO_REQUEST packets to measure a hosts reachability and the network latency. In contrast to the original L utility B can send ICMP packets to multiple hosts in parallel and wait for all ECHO_RESPONSE packets to arrive. In contrast to the B utility (URL is listed in L<"SEE ALSO">) B can use both, IPv4 and IPv6 transparently and side by side. B is an ncurses-based front-end to I which displays ping statistics online and highlights aberrant round-trip times if the terminal supports colors. =head1 OPTIONS =over 4 =item B<-4> Force the use of IPv4. =item B<-6> Force the use of IPv6. =item B<-c> I Send (and receive) I ICMP packets, then stop and exit. =item B<-i> I Send one ICMP packet (per host) each I seconds. This can be a floating-point number to specify sub-second precision. =item B<-t> I Set the IP Time to Live to I. This must be a number between (and including) 1EandE255. If omitted, the value B<64> is used. =item B<-I> I
Set the source address to use. You may either specify an IP number or a hostname. You B pass the interface name, as you can with GNU's L - use the B<-D> option for that purpose. =item B<-D> I Set the outgoing network device to use. =item B<-f> I Instead of specifying hostnames on the command line, read them from I. If I is B<->, read from C. If I is installed with the SetUID-bit, it will set the effective UID to the real UID before opening the file. In the special (but common) case that I is owned by the super-user (UIDE0), this means that privileges are temporarily dropped before opening the file, in order to prevent users from reading arbitrary files on the system. If your system doesn't provide I (this was an optional feature before POSIXE2001), the behavior is different because it is not possible to I drop privileges. The alternative behavior is: If the real user ID (as returned by L) and the effective user ID (as returned by L) differ, the only argument allowed for this option is "-" (i.e. standard input). =item B<-Q> I Specify the I (QoS) for outgoing packets. This is a somewhat tricky option, since the meaning of the bits in the IPv4 header has been revised several times. The currently recommended method is I which is used in IPv6 headers as well. There are shortcuts for various predefined I (PHBs): =over 4 =item B Selects the I behavior. This is the default behavior. =item B Selects the I (EF) per-hop behavior, as defined in I3246>. This PHB is characterised by low delay, low loss and low jitter, i.e. high priority traffic. =item B Selects the I (VA) per-hop behavior, as defined in I5865>. This traffic class is meant for I (VoIP) traffic which uses I (CAC) for reserving network capacity. =item BII

Selects one of 12Edifferentiated services code points (DSCPs), which are organized in four I with three I each. Therefore, I must be a number betweenE1 throughE4 and I

must be a number betweenE1 throughE3, for example "af13", "af22" and "af41". In each class, the lower priority number takes precedence over the higher priority number. =item BI Selects one of the eight I PHBs. I is a number betweenE0 throughE7. The class selectors have been defined to be compatible to the I field in the IPv4 header as defined in I791>. Please note that "cs0" is synonymous to "be". =back The old definition of the same bits in the IPv4 header was as I (ToS) field, specified in I1349>. It defined four possible values which have appropriate aliases. Please note that this use of the bits is B and the meaning is limited to IPv4! =over 4 =item B Minimize delay =item B Maximize throughput =item B Maximize reliability =item B Minimize monetary cost =back Alternatively, you can also specify the byte manually. You can use either a decimal number (0-255), a hexadecimal number (0x00-0xff) or an octal number (00-0377) using the usual "0x" and "0" prefixes for hexadecimal and octal respectively. The printed lines will contain information about the QoS field of received packets if either a non-standard QoS setting was used on outgoing packets or if the QoS byte of incoming packets is not zero. In other words, the QoS information is omitted if both, the outgoing and the incoming QoS bytes are zero. The received byte is always interpreted as I (DSCP) and I (ECN), even if the deprecated I (ToS) aliases were used to specify the bits of outgoing packets. =item B<-u>|B<-U> I B<-u> forces UTF-8 output, B<-U> disables UTF-8 output. If neither is given, the codeset is automatically determined from the locale. =item B<-g> B|B|B|B I Selects the graph to display. =over 4 =item B Do not show a graph. =item B Show a graph with time on the x-axis, the y-axis shows the round-trip time. This is the default graph. If your terminal supports unicode and colors, they are used to improve the precision of the data shown: a green box is drawn for round-trip times up to one third of the configured timeout, the height representing the RTT. Longer RTTs will start to fill the box yellow (with a green background) and then red (with a yellow background). Lost packages are drawn as a bold red explamation mark. =item B Show a I where the x-axis, i.e. the width of the window, is the round-trip time. The entire width of the window it the ping interval, set with the B<-i> option. The box is sized so it contains 50% of the replies. The vertical line shows the median. The whiskers are sized to contain 95% of the replies -- 2.5% below the whiskers and 2.5% above. |----------[#####|##########]--------------------------------------------| ^ ^ ^ ^ ^ 2.75% 25% 50% 75% 97.5% =item B Show a I of the round-trip times. The width of the window is taken as round-trip time from 0ms on the left to the I (the B<-i> option, default 1000ms) on the right. The height of the graph is scaled so that the most-used buckets vertically fills the line. The buckets are colored green up to and including the 80th percentile, yellow up to and including the 95th percentile and red for the remainder. =back =item B<-P> I Configures the latency percentile to report. I must be a number between zero and 100, exclusively in both cases. In general, defaults to B<95>. If B<-c> is given and a number less than 20, this would be the same as the maximum. In this case the default is chosen so that it excludes the maximum, e.g. if B<-cE5> is given, the default is I<80>. The calculated percentile is based on the last 900 packets (15 minutes with the default interval). =item B<-Z> I If any hosts have a drop rate higher than I, where I is a number between zero and 100 inclusively, exit with a non-zero exit status. Since it is not possible to have a higher drop rate than 100%, passing this limit will effectively disable the feature (the default). Setting the option to zero means that the exit status will only be zero if I replies for I hosts have been received. The exit status will indicate the number of hosts with more than I packets lost, up to a number of 255 failing hosts. =back =head1 COLORS If supported by the terminal, I will highlight the round-trip times (RTT) using the colors green, yellow and red. Green signals RTTs that are in the "expected" range, yellow marks moderately unusual times and times that differ a lot from the expected value are printed in red. The information used to categorize round-trip times is the I. RTTs in the 80th percentile are considered to be "normal" and are printed in green. RTTs within the 95th percentile are considered "moderately unusual" and are printed in yellow. RTTs above that are considered to be "unusual" and are printed in red. =head1 SEE ALSO L, L, L =head1 AUTHOR liboping is written by Florian "octo" Forster Eff at octo.itE. Its homepage can be found at L. Copyright (c) 2005-2011 by Florian "octo" Forster. liboping-1.8.0/src/mans/ping_setopt.pod0000644037772200116100000000673311631533276015063 00000000000000=head1 NAME ping_setopt - Set options for a liboping object =head1 SYNOPSIS #include int ping_setopt (pingobj_t *obj, int opt, void *val); =head1 DESCRIPTION The B method sets options that apply to all hosts associated with the object I and hosts that are yet to be added to the object. The I argument is a pointer to an I object, as returned by L. The I argument specifies the option to set. Use one of the following constants. You can check if the required constant is supported by the library at compile time using C<#ifdef>. It is recommended to check for desired features using the C define. =over 4 =item B The time to wait for a "echo reply" to be received; in seconds. In this case the memory pointed to by I is interpreted as a double value and must be greater than zero. The default is B. =item B The value written into the time-to-live (= TTL) field of generated ICMP packets. The memory pointed to by I is interpreted as an integer. Valid values are 1 through 255. Default is B. =item B The address family to use. The memory pointed to by I is interpreted as an integer and must be either B, B, or B. This option only affects hosts that are being added B this option has been set. Default is B. If you change this option, and a source address is set (see B) that setting will be reset. =item B Set the data to send. The value passed must be a char-pointer to a null-terminated string. By default a 56 byte long string is used so that the packet size of an ICMPv4 packet is exactly 64 bytes. That's the behavior of the L command. =item B Set the source address to use. The value passed must be a char-pointer to a null-terminated string specifying either a numerical network address or network hostname. This option will ignore the address family setting (as set with B) and will set the object's address family according to the source address assigned. =item B Set the outgoing network device to be used. The value passed must be a char-pointer to a null-terminated string specifying an interface name (e.Eg. C). Please note that this might not be supported by all operating systems. In that case, B sets the error to C. =item B Sets the I flags that should be used when crafting ICMP and ICMPv6 packets. The memory pointed to by I is interpreted as a C. The byte is passed to L without modification, using the C (IPv4) or C (IPv6) option. It is the caller's responsibility to chose a valid bit combination. For details, read the L and L manual pages, as well as I2474>. =back The I argument is a pointer to the new value. It must not be NULL. It is dereferenced depending on the value of the I argument, see above. The memory pointed to by I is not changed. =head1 RETURN VALUE B returns zero upon success or less than zero upon failure. =head1 SEE ALSO L, L =head1 AUTHOR liboping is written by Florian "octo" Forster Eocto at verplant.orgE. Its homepage can be found at L. Copyright (c) 2005-2011 by Florian "octo" Forster. liboping-1.8.0/src/mans/liboping.pod0000644037772200116100000000563611631533276014334 00000000000000=head1 NAME liboping - Library to send ICMPv4/ICMPv6 echo packets to multiple hosts =head1 DESCRIPTION This is an overview of liboping, a C library to send ICMP ECHO_REQUEST packets to remote hosts and measure the time it takes for replies to be received. This method, often simply called "ping", is a common way to measure network latency and/or host reachability. The goals of this library are to provide the above functionality in a platform and protocol independent manner. The interface is simple, object oriented and (hopefully) ANSI-C compliant. =head1 GENERAL USAGE There are two main types that are used by applications. Both are "opaque types", meaning they are structures that are B completely defined in the header file, so you cannot access the structures' members. You don't need to, don't do it. These structures are subject to change without notice. =over 4 =item C A ping-object. You can set specific options for this object, add and remove hosts to/from it and send ICMP packets to all associated hosts. This is often called a "handle". =item C An iterator over the hosts associated with a C object. This iterator can be used to query more information about a host, for example the hostname, the measured latency or the current ICMP sequence. =back Upon startup you usually create one or more C objects and add hosts to it using the C method (see below). You periodically send "echo requests" using the C method, iterate over all hosts using C and C. For each host you call C to read the current latency and do something with it. If an error occurs you can use C so get information on what failed. =head1 LINKING WITH LIBOPING Depending on you platform you don't need any extra libraries (e.g. GNU/Linux) or C (using C<-lsocket>) if the C function is not in the C-library. The latter is the case for the Solaris operating system. =head1 SYMBOL NAMES All "official" function or method names are prefixed with "ping_". Don't use any other functions or methods. Although no such functions should exist. =head1 THREAD SAFETY liboping has been designed to be as thread safe a possible. However, this has not been tested and may need some additional work. Use at your own risk and please report back any problems or success messages. Thank you :) =head1 SEE ALSO L, L, L, L, L, L, L, L =head1 LICENSE liboping is licensed under the GPLv2. No other version of the license is applicable. =head1 AUTHOR liboping is written by Florian "octo" Forster Eocto at verplant.orgE. Its homepage can be found at L. Copyright (c) 2005-2011 by Florian "octo" Forster. liboping-1.8.0/src/mans/Makefile.in0000644037772200116100000004230512433400077014055 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/mans DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man8dir)" man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDINGS = @BINDINGS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBOPING_AGE = @LIBOPING_AGE@ LIBOPING_CURRENT = @LIBOPING_CURRENT@ LIBOPING_MAJOR = @LIBOPING_MAJOR@ LIBOPING_MINOR = @LIBOPING_MINOR@ LIBOPING_PATCH = @LIBOPING_PATCH@ LIBOPING_PC_LIBS_PRIVATE = @LIBOPING_PC_LIBS_PRIVATE@ LIBOPING_REVISION = @LIBOPING_REVISION@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NCURSES_LIB = @NCURSES_LIB@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_BINDINGS_OPTIONS = @PERL_BINDINGS_OPTIONS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ man_PODS = liboping.pod ping_construct.pod ping_setopt.pod ping_host_add.pod \ ping_send.pod ping_get_error.pod ping_iterator_get.pod \ ping_iterator_get_info.pod ping_iterator_get_context.pod oping.pod man_MANS = liboping.3 ping_construct.3 ping_setopt.3 ping_host_add.3 \ ping_send.3 ping_get_error.3 ping_iterator_get.3 \ ping_iterator_get_info.3 ping_iterator_get_context.3 oping.8 EXTRA_DIST = $(man_MANS) $(man_PODS) all: all-am .SUFFIXES: .SUFFIXES: .1 .3 .8 .pod $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/mans/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/mans/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man3: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man3dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.3[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) installdirs: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man3 install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man3 uninstall-man8 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man3 install-man8 install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-man uninstall-man3 uninstall-man8 .pod.1: pod2man --section=1 --release=$(VERSION) --center=$(PACKAGE) $< >$@ .pod.3: pod2man --section=3 --release=$(VERSION) --center=$(PACKAGE) $< >$@ .pod.8: pod2man --section=8 --release=$(VERSION) --center=$(PACKAGE) $< >$@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: liboping-1.8.0/src/mans/ping_iterator_get_info.pod0000644037772200116100000001070411631533276017241 00000000000000=head1 NAME ping_iterator_get_info - Receive information about a host =head1 SYNOPSIS #include int ping_iterator_get_info (pingobj_iter_t *iter, int info, void *buffer, size_t *buffer_len); =head1 DESCRIPTION The B method can be used on an host iterator to return various information about the current host. The I argument is an iterator as returned by L or L. The I argument specifies the type of information returned. Use the following defines: =over 4 =item B Return the hostname of the host the iterator points to as supplied by the user. This is the name you passed to L and which you need to pass to C, too. =item B Return the hostname of the host the iterator points to. Since the name is looked up using the socket address this may differ from the hostname passed to L. The hostname is actually looked up every time you call this method, no cache is involved within I. It is recommended to include C and allocate B bytes of buffer. =item B Return the address used in ASCII (i.e. human readable) format. The address is looked up every time you call this method. 40 bytes should be sufficient for the buffer (16 octets in hex format, seven colons and one null byte), but more won't hurt. =item B Returns the address family of the host. The buffer should be big enough to hold an integer. The value is either B or B. =item B Return the last measured latency or less than zero if the timeout occurred before a echo response was received. The buffer should be big enough to hold a double value. =item B Return the number of times that no response was received within the timeout. This value is only increased but may wrap around at the 32Ebit boundary. The buffer should be big enough to hold a 32Ebit integer, e.Eg. an C. =item B Return the last sequence number sent. This number is increased regardless of echo responses being received or not. The buffer should hold an integer. =item B Return the ident that is put into every ICMP packet sent to this host. Per convention this usually is the PID of the sending process, but since I can handle several hosts in parallel it uses a (pseudo-)random number here. The buffer should be big enough to hold an integer value. =item B Returns the I