diff --git a/src/liboping.c b/src/liboping.c index bf9e059..1d44571 100644 --- a/src/liboping.c +++ b/src/liboping.c @@ -1550,13 +1550,23 @@ static pinghost_t *ping_host_search (pinghost_t *ph, const char *host) return (ph); } +/* wrapper around ping_host_add_multi() to preserve existing + * calling / return convention + */ int ping_host_add (pingobj_t *obj, const char *host) +{ + int n = ping_host_add_multi( obj, host, 1 ); + return n < 0 ? n: 0; +} + +int ping_host_add_multi (pingobj_t *obj, const char *host, int max_hosts) { pinghost_t *ph; struct addrinfo ai_hints; struct addrinfo *ai_list, *ai_ptr; int ai_return; + int hosts_added = 0; if ((obj == NULL) || (host == NULL)) return (-1); @@ -1577,37 +1587,6 @@ int ping_host_add (pingobj_t *obj, const char *host) 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) @@ -1620,7 +1599,6 @@ int ping_host_add (pingobj_t *obj, const char *host) ? sstrerror (errno, errbuf, sizeof (errbuf)) : #endif gai_strerror (ai_return)); - ping_free (ph); return (-1); } @@ -1629,15 +1607,41 @@ int ping_host_add (pingobj_t *obj, const char *host) for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { + 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); + } + + /* 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); + } + + char * afi_str = NULL; if (ai_ptr->ai_family == AF_INET) { ai_ptr->ai_socktype = SOCK_RAW; ai_ptr->ai_protocol = IPPROTO_ICMP; + afi_str = "v4"; } else if (ai_ptr->ai_family == AF_INET6) { ai_ptr->ai_socktype = SOCK_RAW; ai_ptr->ai_protocol = IPPROTO_ICMPV6; + afi_str = "v6"; } else { @@ -1648,9 +1652,19 @@ int ping_host_add (pingobj_t *obj, const char *host) dprintf ("%s", errmsg); ping_set_error (obj, "getaddrinfo", errmsg); + ping_free (ph); continue; } + if ((ph->hostname = malloc ( strlen(host)+4) ) == NULL) + { + dprintf ("Out of memory!\n"); + ping_set_errno (obj, errno); + ping_free (ph); + return (-1); + } + sprintf( ph->hostname, "%s/%s", host, afi_str ); + 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); @@ -1667,46 +1681,55 @@ int ping_host_add (pingobj_t *obj, const char *host) ph->hostname, ai_ptr->ai_canonname); old_hostname = ph->hostname; - if ((ph->hostname = strdup (ai_ptr->ai_canonname)) == NULL) + if ((ph->hostname = malloc( strlen(ai_ptr->ai_canonname)+4 )) == NULL) { /* strdup failed, falling back to old hostname */ ph->hostname = old_hostname; } - else if (old_hostname != NULL) + else { + sprintf( ph->hostname, "%s/%s", + ai_ptr->ai_canonname, afi_str ); free (old_hostname); } } #endif /* AI_CANONNAME */ - } /* for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) */ - freeaddrinfo (ai_list); + /* + * 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; - /* - * 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; - hptr = obj->head; - while (hptr->next != NULL) - hptr = hptr->next; + assert ((hptr != NULL) && (hptr->next == NULL)); + hptr->next = ph; + } - assert ((hptr != NULL) && (hptr->next == NULL)); - hptr->next = ph; - } + ph->table_next = obj->table[ph->ident % PING_TABLE_LEN]; + obj->table[ph->ident % PING_TABLE_LEN] = ph; + hosts_added++; - ph->table_next = obj->table[ph->ident % PING_TABLE_LEN]; - obj->table[ph->ident % PING_TABLE_LEN] = ph; + if ( max_hosts > 0 && hosts_added >= max_hosts ) + { + break; + } - return (0); + } /* for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) */ + + freeaddrinfo (ai_list); + + return (hosts_added); } /* int ping_host_add */ int ping_host_remove (pingobj_t *obj, const char *host) diff --git a/src/mans/ping_host_add.pod b/src/mans/ping_host_add.pod index f874771..3a3f44a 100644 --- a/src/mans/ping_host_add.pod +++ b/src/mans/ping_host_add.pod @@ -6,8 +6,9 @@ ping_host_add - Add a host to a liboping object #include - int ping_host_add (pingobj_t *obj, const char *host); - int ping_host_remove (pingobj_t *obj, const char *host); + int ping_host_add (pingobj_t *obj, const char *host); + int ping_host_add_multi (pingobj_t *obj, const char *host, int max_hosts); + int ping_host_remove (pingobj_t *obj, const char *host); =head1 DESCRIPTION @@ -21,6 +22,13 @@ The I parameter is a '\0' terminated string which is interpreted as a hostname or an IP address. Depending on the address family setting, set with L, the hostname is resolved to an IPv4 or IPv6 address. +If more than one result is returned by DNS, only the first result is used. + +The B extends the B function to +permit adding up to I DNS results (IPv4 and IPv6, or multiple +IPv4 / IPv6 records) to the liboping object. If I is 0, there +is no limit = add all records returned by DNS. + The B method looks for I within I and remove it if found. It will close the socket and deallocate the memory, too. @@ -33,6 +41,10 @@ If B succeeds it returns zero. If an error occurs a value less than zero is returned and the last error is saved internally. You can receive the error message using L. +If B succeeds it returns the number of hosts added. If +an error occurs a value less than zero is returned and the last error is +saved internally. You can receive the error message using L. + B returns zero upon success and less than zero if it failed. Currently the only reason for failure is that the host isn't found, but this is subject to change. Use L to receive the error message. diff --git a/src/oping.c b/src/oping.c index c087c80..683a1b2 100644 --- a/src/oping.c +++ b/src/oping.c @@ -220,6 +220,7 @@ static int opt_utf8 = 0; #endif static char *opt_outfile = NULL; static int opt_bell = 0; +static int opt_max_hosts = 1; static int host_num = 0; static FILE *outfile = NULL; @@ -682,7 +683,7 @@ static int read_options (int argc, char **argv) /* {{{ */ while (1) { - optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:Z:O:P:m:w:b" + optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:Z:O:P:m:w:ba" #if USE_NCURSES "uUg:H:" #endif @@ -855,6 +856,10 @@ static int read_options (int argc, char **argv) /* {{{ */ break; } + case 'a': + opt_max_hosts = -1; /* all */ + break; + case 'h': usage_exit (argv[0], 0); break; @@ -1944,7 +1949,8 @@ int main (int argc, char **argv) /* {{{ */ if ((host[0] == 0) || (host[0] == '#')) continue; - if (ping_host_add(ping, host) < 0) + int n = ping_host_add_multi(ping, host, opt_max_hosts); + if (n < 0) { const char *errmsg = ping_get_error (ping); @@ -1953,7 +1959,7 @@ int main (int argc, char **argv) /* {{{ */ } else { - host_num++; + host_num+=n; } } @@ -1984,7 +1990,8 @@ int main (int argc, char **argv) /* {{{ */ for (i = optind; i < argc; i++) { - if (ping_host_add (ping, argv[i]) < 0) + int n = ping_host_add_multi (ping, argv[i], opt_max_hosts); + if (n < 0) { const char *errmsg = ping_get_error (ping); @@ -1993,7 +2000,7 @@ int main (int argc, char **argv) /* {{{ */ } else { - host_num++; + host_num+=n; } } diff --git a/src/oping.h b/src/oping.h index ff144e8..2ed8630 100644 --- a/src/oping.h +++ b/src/oping.h @@ -71,6 +71,7 @@ int ping_setopt (pingobj_t *obj, int option, void *value); int ping_send (pingobj_t *obj); int ping_host_add (pingobj_t *obj, const char *host); +int ping_host_add_multi (pingobj_t *obj, const char *host, int max_hosts); int ping_host_remove (pingobj_t *obj, const char *host); pingobj_iter_t *ping_iterator_get (pingobj_t *obj);