Skip to content

Multiping! #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 80 additions & 57 deletions src/liboping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -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);
}

Expand All @@ -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
{
Expand All @@ -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);
Expand All @@ -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)
Expand Down
16 changes: 14 additions & 2 deletions src/mans/ping_host_add.pod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ ping_host_add - Add a host to a liboping object

#include <oping.h>

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

Expand All @@ -21,6 +22,13 @@ The I<host> 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<ping_setopt(3)>, 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<ping_host_add_multi> extends the B<ping_host_add> function to
permit adding up to I<max_hosts> DNS results (IPv4 and IPv6, or multiple
IPv4 / IPv6 records) to the liboping object. If I<max_hosts> is 0, there
is no limit = add all records returned by DNS.

The B<ping_host_remove> method looks for I<host> within I<obj> and remove it if
found. It will close the socket and deallocate the memory, too.

Expand All @@ -33,6 +41,10 @@ If B<ping_host_add> 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<ping_get_error(3)>.

If B<ping_host_add_multi> 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<ping_get_error(3)>.

B<ping_host_remove> 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<ping_get_error(3)> to receive the error message.
Expand Down
17 changes: 12 additions & 5 deletions src/oping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -855,6 +856,10 @@ static int read_options (int argc, char **argv) /* {{{ */
break;
}

case 'a':
opt_max_hosts = -1; /* all */
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation specifies "all" as zero, this code here uses -1.

break;

case 'h':
usage_exit (argv[0], 0);
break;
Expand Down Expand Up @@ -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);

Expand All @@ -1953,7 +1959,7 @@ int main (int argc, char **argv) /* {{{ */
}
else
{
host_num++;
host_num+=n;
}
}

Expand Down Expand Up @@ -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);

Expand All @@ -1993,7 +2000,7 @@ int main (int argc, char **argv) /* {{{ */
}
else
{
host_num++;
host_num+=n;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/oping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down