hosts.c
Go to the documentation of this file.
/* SPDX-FileCopyrightText: 2013-2023 Greenbone AG
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "hosts.h"
#include "networking.h" /* for ipv4_as_ipv6, addr6_as_str, gvm_resolve */
#include <arpa/inet.h> /* for inet_pton, inet_ntop */
#include <assert.h> /* for assert */
#include <ctype.h> /* for isdigit */
#include <malloc.h>
#include <netdb.h> /* for getnameinfo, NI_NAMEREQD */
#include <stdint.h> /* for uint8_t, uint32_t */
#include <stdio.h> /* for sscanf, perror */
#include <stdlib.h> /* for strtol, atoi */
#include <string.h> /* for strchr, memcpy, memcmp, bzero, strcasecmp */
#include <sys/socket.h> /* for AF_INET, AF_INET6, sockaddr */
#include <unistd.h> /* for usleep() */
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libgvm base"
/* Static variables */
gchar *host_type_str[HOST_TYPE_MAX] = {
[HOST_TYPE_NAME] = "Hostname",
[HOST_TYPE_IPV4] = "IPv4",
[HOST_TYPE_IPV6] = "IPv6",
[HOST_TYPE_CIDR_BLOCK] = "IPv4 CIDR block",
[HOST_TYPE_RANGE_SHORT] = "IPv4 short range",
[HOST_TYPE_RANGE_LONG] = "IPv4 long range"};
/* Function definitions */
static int
is_ipv4_address (const char *str)
{
struct sockaddr_in sa;
return inet_pton (AF_INET, str, &(sa.sin_addr)) == 1;
}
static int
is_ipv6_address (const char *str)
{
struct sockaddr_in6 sa6;
return inet_pton (AF_INET6, str, &(sa6.sin6_addr)) == 1;
}
static int
is_cidr_block (const char *str)
{
long block;
char *addr_str, *block_str, *p;
addr_str = g_strdup (str);
block_str = strchr (addr_str, '/');
if (block_str == NULL)
{
g_free (addr_str);
return 0;
}
/* Separate the address from the block value. */
*block_str = '\0';
block_str++;
if (!is_ipv4_address (addr_str) || !isdigit (*block_str))
{
g_free (addr_str);
return 0;
}
p = NULL;
block = strtol (block_str, &p, 10);
if (*p || block <= 0 || block > 30)
{
g_free (addr_str);
return 0;
}
g_free (addr_str);
return 1;
}
static int
cidr_get_block (const char *str, unsigned int *block)
{
if (str == NULL || block == NULL)
return -1;
if (sscanf (str, "%*[0-9.]/%2u", block) != 1)
return -1;
return 0;
}
static int
cidr_get_ip (const char *str, struct in_addr *addr)
{
gchar *addr_str, *tmp;
if (str == NULL || addr == NULL)
return -1;
addr_str = g_strdup (str);
tmp = strchr (addr_str, '/');
if (tmp == NULL)
{
g_free (addr_str);
return -1;
}
*tmp = '\0';
if (inet_pton (AF_INET, addr_str, addr) != 1)
return -1;
g_free (addr_str);
return 0;
}
static int
cidr_block_ips (const char *str, struct in_addr *first, struct in_addr *last)
{
unsigned int block;
if (str == NULL || first == NULL || last == NULL)
return -1;
/* Get IP and block values. */
if (cidr_get_block (str, &block) == -1)
return -1;
if (cidr_get_ip (str, first) == -1)
return -1;
/* First IP: And with mask and increment. */
first->s_addr &= htonl (0xffffffff ^ ((1 << (32 - block)) - 1));
first->s_addr = htonl (ntohl (first->s_addr) + 1);
/* Last IP: First IP + Number of usable hosts - 1. */
last->s_addr = htonl (ntohl (first->s_addr) + (1 << (32 - block)) - 3);
return 0;
}
static int
is_long_range_network (const char *str)
{
char *first_str, *second_str;
int ret;
first_str = g_strdup (str);
second_str = strchr (first_str, '-');
if (second_str == NULL)
{
g_free (first_str);
return 0;
}
/* Separate the addresses. */
*second_str = '\0';
second_str++;
ret = is_ipv4_address (first_str) && is_ipv4_address (second_str);
g_free (first_str);
return ret;
}
static int
long_range_network_ips (const char *str, struct in_addr *first,
struct in_addr *last)
{
char *first_str, *last_str;
if (str == NULL || first == NULL || last == NULL)
return -1;
first_str = g_strdup (str);
last_str = strchr (first_str, '-');
if (last_str == NULL)
{
g_free (first_str);
return -1;
}
/* Separate the two IPs. */
*last_str = '\0';
last_str++;
if (inet_pton (AF_INET, first_str, first) != 1
|| inet_pton (AF_INET, last_str, last) != 1)
{
g_free (first_str);
return -1;
}
g_free (first_str);
return 0;
}
static int
is_short_range_network (const char *str)
{
long end;
char *ip_str, *end_str, *p;
ip_str = g_strdup (str);
end_str = strchr (ip_str, '-');
if (end_str == NULL)
{
g_free (ip_str);
return 0;
}
/* Separate the addresses. */
*end_str = '\0';
end_str++;
if (!is_ipv4_address (ip_str) || !isdigit (*end_str))
{
g_free (ip_str);
return 0;
}
p = NULL;
end = strtol (end_str, &p, 10);
if (*p || end < 0 || end > 255)
{
g_free (ip_str);
return 0;
}
g_free (ip_str);
return 1;
}
static int
short_range_network_ips (const char *str, struct in_addr *first,
struct in_addr *last)
{
char *first_str, *last_str;
int end;
if (str == NULL || first == NULL || last == NULL)
return -1;
first_str = g_strdup (str);
last_str = strchr (first_str, '-');
if (last_str == NULL)
{
g_free (first_str);
return -1;
}
/* Separate the two IPs. */
*last_str = '\0';
last_str++;
end = atoi (last_str);
/* Get the first IP */
if (inet_pton (AF_INET, first_str, first) != 1)
{
g_free (first_str);
return -1;
}
/* Get the last IP */
last->s_addr = htonl ((ntohl (first->s_addr) & 0xffffff00) + end);
g_free (first_str);
return 0;
}
static int
is_hostname (const char *str)
{
gchar *copy, **point, **split;
/* From
* https://stackoverflow.com/questions/2532053/validate-a-hostname-string. */
/* Remove one dot from the end. */
copy = g_strdup (str);
if (copy[strlen (copy) - 1] == '.')
copy[strlen (copy) - 1] = '\0';
/* Check length. */
if (strlen (copy) == 0 || strlen (copy) > 253)
{
g_free (copy);
return 0;
}
/* Split on dots. */
point = split = g_strsplit (copy, ".", 0);
g_free (copy);
/* Last part (TLD) may not be an integer. */
if (*point)
{
gchar *last;
while (*(point + 1))
point++;
last = *point;
if (strlen (last))
{
while (*last && isdigit (*last))
last++;
if (*last == '\0')
{
g_strfreev (split);
return 0;
}
}
}
/* Check each part. */
point = split;
while (*point)
if (g_regex_match_simple ("^(?!-)[a-z0-9_-]{1,63}(?<!-)$", *point,
G_REGEX_CASELESS, 0)
== 0)
{
g_strfreev (split);
return 0;
}
else
point++;
g_strfreev (split);
return 1;
}
int
gvm_is_cidr6_block (const char *str)
{
long block;
char *addr6_str, *block_str, *p;
addr6_str = g_strdup (str);
block_str = strchr (addr6_str, '/');
if (block_str == NULL)
{
g_free (addr6_str);
return 0;
}
/* Separate the address from the block value. */
*block_str = '\0';
block_str++;
if (!is_ipv6_address (addr6_str) || !isdigit (*block_str))
{
g_free (addr6_str);
return 0;
}
p = NULL;
block = strtol (block_str, &p, 10);
if (*p || block <= 0 || block > 128)
{
g_free (addr6_str);
return 0;
}
g_free (addr6_str);
return 1;
}
int
gvm_cidr6_get_block (const char *str, unsigned int *block)
{
if (str == NULL || block == NULL)
return -1;
if (sscanf (str, "%*[0-9a-fA-F.:]/%3u", block) != 1)
return -1;
return 0;
}
int
gvm_cidr6_get_ip (const char *str, struct in6_addr *addr6)
{
gchar *addr6_str, *tmp;
if (str == NULL || addr6 == NULL)
return -1;
addr6_str = g_strdup (str);
tmp = strchr (addr6_str, '/');
if (tmp == NULL)
{
g_free (addr6_str);
return -1;
}
*tmp = '\0';
if (inet_pton (AF_INET6, addr6_str, addr6) != 1)
return -1;
g_free (addr6_str);
return 0;
}
int
gvm_cidr6_block_ips (const char *str, struct in6_addr *first,
struct in6_addr *last)
{
unsigned int block;
int i, j;
if (str == NULL || first == NULL || last == NULL)
return -1;
/* Get IP and block values. */
if (gvm_cidr6_get_block (str, &block) == -1)
return -1;
if (gvm_cidr6_get_ip (str, first) == -1)
return -1;
memcpy (&last->s6_addr, &first->s6_addr, 16);
/* /128 => Specified address is the first and last one. */
if (block == 128)
return 0;
/* First IP: And with mask and increment to skip network address. */
j = 15;
for (i = (128 - block) / 8; i > 0; i--)
{
first->s6_addr[j] = 0;
j--;
}
first->s6_addr[j] &= 0xff ^ ((1 << ((128 - block) % 8)) - 1);
/* Last IP: Broadcast address - 1. */
j = 15;
for (i = (128 - block) / 8; i > 0; i--)
{
last->s6_addr[j] = 0xff;
j--;
}
last->s6_addr[j] |= (1 << ((128 - block) % 8)) - 1;
/* /127 => Only two addresses. Don't skip network / broadcast addresses.*/
if (block == 127)
return 0;
/* Increment first IP. */
for (i = 15; i >= 0; --i)
if (first->s6_addr[i] < 255)
{
first->s6_addr[i]++;
break;
}
else
first->s6_addr[i] = 0;
/* Decrement last IP. */
for (i = 15; i >= 0; --i)
if (last->s6_addr[i] > 0)
{
last->s6_addr[i]--;
break;
}
else
last->s6_addr[i] = 0xff;
return 0;
}
static int
is_long_range6_network (const char *str)
{
char *first_str, *second_str;
int ret;
first_str = g_strdup (str);
second_str = strchr (first_str, '-');
if (second_str == NULL)
{
g_free (first_str);
return 0;
}
/* Separate the addresses. */
*second_str = '\0';
second_str++;
ret = is_ipv6_address (first_str) && is_ipv6_address (second_str);
g_free (first_str);
return ret;
}
static int
long_range6_network_ips (const char *str, struct in6_addr *first,
struct in6_addr *last)
{
char *first_str, *last_str;
if (str == NULL || first == NULL || last == NULL)
return -1;
first_str = g_strdup (str);
last_str = strchr (first_str, '-');
if (last_str == NULL)
{
g_free (first_str);
return -1;
}
/* Separate the two IPs. */
*last_str = '\0';
last_str++;
if (inet_pton (AF_INET6, first_str, first) != 1
|| inet_pton (AF_INET6, last_str, last) != 1)
{
g_free (first_str);
return -1;
}
g_free (first_str);
return 0;
}
static int
is_short_range6_network (const char *str)
{
char *ip_str, *end_str, *p;
ip_str = g_strdup (str);
end_str = strchr (ip_str, '-');
if (end_str == NULL)
{
g_free (ip_str);
return 0;
}
/* Separate the addresses. */
*end_str = '\0';
end_str++;
if (!is_ipv6_address (ip_str) || *end_str == '\0')
{
g_free (ip_str);
return 0;
}
p = end_str;
/* Check that the 2nd part is at most 4 hexadecimal characters. */
while (isxdigit (*p) && p++)
;
if (*p || p - end_str > 4)
{
g_free (ip_str);
return 0;
}
g_free (ip_str);
return 1;
}
static int
short_range6_network_ips (const char *str, struct in6_addr *first,
struct in6_addr *last)
{
char *first_str, *last_str;
long int end;
if (str == NULL || first == NULL || last == NULL)
return -1;
first_str = g_strdup (str);
last_str = strchr (first_str, '-');
if (last_str == NULL)
{
g_free (first_str);
return -1;
}
/* Separate the first IP. */
*last_str = '\0';
last_str++;
if (inet_pton (AF_INET6, first_str, first) != 1)
{
g_free (first_str);
return -1;
}
/* Calculate the last IP. */
memcpy (last, first, sizeof (*last));
end = strtol (last_str, NULL, 16);
memcpy (&last->s6_addr[15], &end, 1);
memcpy (&last->s6_addr[14], ((char *) &end) + 1, 1);
g_free (first_str);
return 0;
}
int
gvm_get_host_type (const gchar *str_stripped)
{
/*
* We have a single element with no leading or trailing
* white spaces. This element could represent different host
* definitions: single IPs, host names, CIDR-expressed blocks,
* range-expressed networks, IPv6 addresses.
*/
/* Null or empty string. */
if (str_stripped == NULL || *str_stripped == '\0')
return -1;
/* Check for regular single IPv4 address. */
if (is_ipv4_address (str_stripped))
return HOST_TYPE_IPV4;
/* Check for regular single IPv6 address. */
if (is_ipv6_address (str_stripped))
return HOST_TYPE_IPV6;
/* Check for regular IPv4 CIDR-expressed block like "192.168.12.0/24" */
if (is_cidr_block (str_stripped))
return HOST_TYPE_CIDR_BLOCK;
/* Check for short range-expressed networks "192.168.12.5-40" */
if (is_short_range_network (str_stripped))
return HOST_TYPE_RANGE_SHORT;
/* Check for long range-expressed networks "192.168.1.0-192.168.3.44" */
if (is_long_range_network (str_stripped))
return HOST_TYPE_RANGE_LONG;
/* Check for regular IPv6 CIDR-expressed block like "2620:0:2d0:200::7/120" */
if (gvm_is_cidr6_block (str_stripped))
return HOST_TYPE_CIDR6_BLOCK;
/* Check for short range-expressed networks "::1-ef12" */
if (is_short_range6_network (str_stripped))
return HOST_TYPE_RANGE6_SHORT;
/* Check for long IPv6 range-expressed networks like "::1:20:7-::1:25:3" */
if (is_long_range6_network (str_stripped))
return HOST_TYPE_RANGE6_LONG;
/* Check for hostname. */
if (is_hostname (str_stripped))
return HOST_TYPE_NAME;
return -1;
}
gvm_vhost_t *
gvm_vhost_new (char *value, char *source)
{
gvm_vhost_t *vhost;
vhost = g_malloc0 (sizeof (gvm_vhost_t));
vhost->value = value;
vhost->source = source;
return vhost;
}
static void
gvm_vhost_free (gpointer vhost)
{
if (vhost)
{
g_free (((gvm_vhost_t *) vhost)->value);
g_free (((gvm_vhost_t *) vhost)->source);
}
g_free (vhost);
}
gpointer
gvm_duplicate_vhost (gconstpointer vhost, gpointer data)
{
(void) (data);
gvm_vhost_t *ret = NULL;
if (!vhost)
return NULL;
ret = gvm_vhost_new (g_strdup (((gvm_vhost_t *) vhost)->value),
g_strdup (((gvm_vhost_t *) vhost)->source));
return ret;
}
static gvm_host_t *
gvm_host_new ()
{
gvm_host_t *host;
host = g_malloc0 (sizeof (gvm_host_t));
return host;
}
void
gvm_host_free (gpointer host)
{
gvm_host_t *h = host;
if (h == NULL)
return;
/* If host of type hostname, free the name buffer, first. */
if (h->type == HOST_TYPE_NAME)
g_free (h->name);
g_slist_free_full (h->vhosts, gvm_vhost_free);
g_free (h);
}
void
gvm_hosts_add (gvm_hosts_t *hosts, gvm_host_t *host)
{
if (hosts->count == hosts->max_size)
{
hosts->max_size *= 4;
hosts->hosts =
g_realloc_n (hosts->hosts, hosts->max_size, sizeof (*hosts->hosts));
memset (hosts->hosts + hosts->count, '\0',
(hosts->max_size - hosts->count) * sizeof (gvm_host_t *));
}
hosts->hosts[hosts->count] = host;
hosts->count++;
}
static gvm_hosts_t *
gvm_hosts_init (const char *hosts_str)
{
gvm_hosts_t *hosts;
hosts = g_malloc0 (sizeof (gvm_hosts_t));
hosts->max_size = 1024;
hosts->hosts = g_malloc0_n (hosts->max_size, sizeof (gvm_host_t *));
hosts->orig_str = g_strdup (hosts_str);
return hosts;
}
static void
gvm_hosts_fill_gaps (gvm_hosts_t *hosts)
{
size_t i;
if (!hosts)
return;
for (i = 0; i < hosts->max_size; i++)
{
if (!hosts->hosts[i])
{
size_t j;
/* Fill the gap with the closest host entry, in order to keep the
* sequential ordering. */
for (j = i + 1; j < hosts->max_size; j++)
{
if (hosts->hosts[j])
{
hosts->hosts[i] = hosts->hosts[j];
hosts->hosts[j] = NULL;
break;
}
}
/* No more entries left, ie. the empty space between count and
* max_size. */
if (!hosts->hosts[i])
return;
}
}
}
static void
gvm_hosts_deduplicate (gvm_hosts_t *hosts)
{
GHashTable *name_table;
size_t i, duplicates = 0;
if (hosts == NULL)
return;
name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < hosts->count; i++)
{
gchar *name;
name = gvm_host_value_str (hosts->hosts[i]);
if (name)
{
gvm_host_t *host, *removed = hosts->hosts[i];
host = g_hash_table_lookup (name_table, name);
if (host)
{
/* Remove duplicate host. Add its vhosts to the original host. */
host->vhosts = g_slist_concat (host->vhosts, removed->vhosts);
removed->vhosts = NULL;
gvm_host_free (removed);
hosts->hosts[i] = NULL;
duplicates++;
g_free (name);
}
else
g_hash_table_insert (name_table, name, hosts->hosts[i]);
}
}
if (duplicates)
gvm_hosts_fill_gaps (hosts);
g_hash_table_destroy (name_table);
hosts->count -= duplicates;
hosts->duplicated += duplicates;
hosts->current = 0;
#ifdef __GLIBC__
malloc_trim (0);
#endif
}
gvm_hosts_t *
gvm_hosts_new_with_max (const gchar *hosts_str, unsigned int max_hosts)
{
gvm_hosts_t *hosts;
gchar **host_element, **split;
gchar *str;
if (hosts_str == NULL)
return NULL;
/* Normalize separator: Transform newlines into commas. */
hosts = gvm_hosts_init (hosts_str);
str = hosts->orig_str;
while (*str)
{
if (*str == '\n')
*str = ',';
str++;
}
/* Split comma-separated list into single host-specifications */
split = g_strsplit (hosts->orig_str, ",", 0);
/* first element of the split list */
host_element = split;
while (*host_element)
{
int host_type;
gchar *stripped = g_strstrip (*host_element);
if (stripped == NULL || *stripped == '\0')
{
host_element++;
continue;
}
/* IPv4, hostname, IPv6, collection (short/long range, cidr block) etc,. ?
*/
/* -1 if error. */
host_type = gvm_get_host_type (stripped);
switch (host_type)
{
case HOST_TYPE_NAME:
case HOST_TYPE_IPV4:
case HOST_TYPE_IPV6:
{
/* New host. */
gvm_host_t *host = gvm_host_new ();
host->type = host_type;
if (host_type == HOST_TYPE_NAME)
host->name = g_ascii_strdown (stripped, -1);
else if (host_type == HOST_TYPE_IPV4)
{
if (inet_pton (AF_INET, stripped, &host->addr) != 1)
break;
}
else if (host_type == HOST_TYPE_IPV6)
{
if (inet_pton (AF_INET6, stripped, &host->addr6) != 1)
break;
}
gvm_hosts_add (hosts, host);
break;
}
case HOST_TYPE_CIDR_BLOCK:
case HOST_TYPE_RANGE_SHORT:
case HOST_TYPE_RANGE_LONG:
{
struct in_addr first, last;
uint32_t current;
int (*ips_func) (const char *, struct in_addr *, struct in_addr *);
if (host_type == HOST_TYPE_CIDR_BLOCK)
ips_func = cidr_block_ips;
else if (host_type == HOST_TYPE_RANGE_SHORT)
ips_func = short_range_network_ips;
else
ips_func = long_range_network_ips;
if (ips_func (stripped, &first, &last) == -1)
break;
/* Make sure that first actually comes before last */
if (ntohl (first.s_addr) > ntohl (last.s_addr))
break;
/* Add addresses from first to last as single hosts. */
current = first.s_addr;
while (ntohl (current) <= ntohl (last.s_addr))
{
gvm_host_t *host;
if (max_hosts > 0 && hosts->count > max_hosts)
{
g_strfreev (split);
gvm_hosts_free (hosts);
return NULL;
}
host = gvm_host_new ();
host->type = HOST_TYPE_IPV4;
host->addr.s_addr = current;
gvm_hosts_add (hosts, host);
/* Next IP address. */
current = htonl (ntohl (current) + 1);
}
break;
}
case HOST_TYPE_CIDR6_BLOCK:
case HOST_TYPE_RANGE6_LONG:
case HOST_TYPE_RANGE6_SHORT:
{
struct in6_addr first, last;
unsigned char current[16];
int (*ips_func) (const char *, struct in6_addr *,
struct in6_addr *);
if (host_type == HOST_TYPE_CIDR6_BLOCK)
ips_func = gvm_cidr6_block_ips;
else if (host_type == HOST_TYPE_RANGE6_SHORT)
ips_func = short_range6_network_ips;
else
ips_func = long_range6_network_ips;
if (ips_func (stripped, &first, &last) == -1)
break;
/* Make sure the first comes before the last. */
if (memcmp (&first.s6_addr, &last.s6_addr, 16) > 0)
break;
/* Add addresses from first to last as single hosts. */
memcpy (current, &first.s6_addr, 16);
while (memcmp (current, &last.s6_addr, 16) <= 0)
{
int i;
gvm_host_t *host;
if (max_hosts > 0 && hosts->count > max_hosts)
{
g_strfreev (split);
gvm_hosts_free (hosts);
return NULL;
}
host = gvm_host_new ();
host->type = HOST_TYPE_IPV6;
memcpy (host->addr6.s6_addr, current, 16);
gvm_hosts_add (hosts, host);
/* Next IPv6 address. */
for (i = 15; i >= 0; --i)
if (current[i] < 255)
{
current[i]++;
break;
}
else
current[i] = 0;
}
break;
}
case -1:
default:
/* Invalid host string. */
g_strfreev (split);
gvm_hosts_free (hosts);
return NULL;
}
host_element++; /* move on to next element of split list */
if (max_hosts > 0 && hosts->count > max_hosts)
{
g_strfreev (split);
gvm_hosts_free (hosts);
return NULL;
}
}
/* No need to check for duplicates when a hosts string contains a
* single (IP/Hostname/Range/Subnetwork) entry. */
if (g_strv_length (split) > 1)
gvm_hosts_deduplicate (hosts);
g_strfreev (split);
#ifdef __GLIBC__
malloc_trim (0);
#endif
return hosts;
}
gvm_hosts_t *
gvm_hosts_new (const gchar *hosts_str)
{
return gvm_hosts_new_with_max (hosts_str, 0);
}
gvm_host_t *
gvm_hosts_next (gvm_hosts_t *hosts)
{
if (!hosts || hosts->current == hosts->count)
return NULL;
return hosts->hosts[hosts->current++];
}
void
gvm_hosts_move_current_host_to_end (gvm_hosts_t *hosts)
{
void *host_tmp;
size_t i;
if (!hosts)
return;
// Keep in mind that gvm_hosts_next will return the current host and then
// increment hosts->current.
if (hosts->current == hosts->count)
{
// We're on the last host, just make the previous host current.
// TODO what happens when current is 0?
hosts->current -= 1;
return;
}
// Make the previous host current. This makes sure that gvm_hosts_next will
// return the host that has replaced the current host.
// TODO what happens when current is 0?
hosts->current -= 1;
// Get the host to be moved.
host_tmp = hosts->hosts[hosts->current];
// Shift all the others down. Start from current + 1 because we're assigning
// into the previous slot (i - 1). It's safe to do this because we already
// checked if current == count above.
for (i = hosts->current + 1; i < hosts->count; i++)
hosts->hosts[i - 1] = hosts->hosts[i];
// Put the moved host on the end.
hosts->hosts[hosts->count - 1] = host_tmp;
}
void
gvm_hosts_free (gvm_hosts_t *hosts)
{
size_t i;
if (hosts == NULL)
return;
g_free (hosts->orig_str);
for (i = 0; i < hosts->count; i++)
gvm_host_free (hosts->hosts[i]);
g_free (hosts->hosts);
g_free (hosts);
hosts = NULL;
}
void
gvm_hosts_shuffle (gvm_hosts_t *hosts)
{
size_t i = 0;
GRand *rand;
if (hosts == NULL)
return;
/* Shuffle the array. */
rand = g_rand_new ();
for (i = 0; i < hosts->count; i++)
{
void *tmp;
int j = g_rand_int_range (rand, 0, hosts->count);
tmp = hosts->hosts[i];
hosts->hosts[i] = hosts->hosts[j];
hosts->hosts[j] = tmp;
}
hosts->current = 0;
g_rand_free (rand);
}
void
gvm_hosts_reverse (gvm_hosts_t *hosts)
{
size_t i, j;
if (hosts == NULL)
return;
for (i = 0, j = hosts->count - 1; i < j; i++, j--)
{
gvm_host_t *tmp = hosts->hosts[i];
hosts->hosts[i] = hosts->hosts[j];
hosts->hosts[j] = tmp;
}
hosts->current = 0;
}
GSList *
gvm_hosts_resolve (gvm_hosts_t *hosts)
{
size_t i, new_entries = 0, resolved = 0;
GSList *unresolved = NULL;
for (i = 0; i < hosts->count; i++)
{
GSList *list, *tmp;
gvm_host_t *host = hosts->hosts[i];
if (host->type != HOST_TYPE_NAME)
continue;
list = tmp = gvm_resolve_list (host->name);
while (tmp)
{
/* Create a new host for each IP address. */
gvm_host_t *new;
struct in6_addr *ip6 = tmp->data;
gvm_vhost_t *vhost;
new = gvm_host_new ();
if (ip6->s6_addr32[0] != 0 || ip6->s6_addr32[1] != 0
|| ip6->s6_addr32[2] != htonl (0xffff))
{
new->type = HOST_TYPE_IPV6;
memcpy (&new->addr6, ip6, sizeof (new->addr6));
}
else
{
new->type = HOST_TYPE_IPV4;
memcpy (&new->addr6, &ip6->s6_addr32[3], sizeof (new->addr));
}
vhost =
gvm_vhost_new (g_strdup (host->name), g_strdup ("Forward-DNS"));
new->vhosts = g_slist_prepend (new->vhosts, vhost);
gvm_hosts_add (hosts, new);
tmp = tmp->next;
new_entries = 1;
}
/* Remove hostname from list, as it was either replaced by IPs, or
* is unresolvable. */
hosts->hosts[i] = NULL;
resolved++;
if (!list)
unresolved = g_slist_prepend (unresolved, g_strdup (host->name));
gvm_host_free (host);
g_slist_free_full (list, g_free);
}
if (resolved)
gvm_hosts_fill_gaps (hosts);
hosts->count -= resolved;
hosts->removed += resolved;
if (new_entries)
gvm_hosts_deduplicate (hosts);
hosts->current = 0;
return unresolved;
}
int
gvm_vhosts_exclude (gvm_host_t *host, const char *excluded_str)
{
GSList *vhost;
char **excluded;
int ret = 0;
if (!host || !excluded_str)
return ret;
vhost = host->vhosts;
excluded = g_strsplit (excluded_str, ",", 0);
if (!excluded || !*excluded)
{
g_strfreev (excluded);
return ret;
}
while (vhost)
{
char **tmp = excluded;
char *value = ((gvm_vhost_t *) vhost->data)->value;
while (*tmp)
{
if (!strcasecmp (value, g_strstrip (*tmp)))
{
gvm_vhost_free (vhost->data);
host->vhosts = vhost = g_slist_delete_link (host->vhosts, vhost);
ret++;
break;
}
tmp++;
if (!*tmp)
{
vhost = vhost->next;
break;
}
}
}
g_strfreev (excluded);
return ret;
}
int
gvm_hosts_exclude_with_max (gvm_hosts_t *hosts, const char *excluded_str,
unsigned int max_hosts)
{
gvm_hosts_t *excluded_hosts;
GHashTable *name_table;
size_t excluded = 0, i;
if (hosts == NULL || excluded_str == NULL)
return -1;
excluded_hosts = gvm_hosts_new_with_max (excluded_str, max_hosts);
if (excluded_hosts == NULL)
return -1;
if (gvm_hosts_count (excluded_hosts) == 0)
{
gvm_hosts_free (excluded_hosts);
return 0;
}
/* Hash host values from excluded hosts list. */
name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < excluded_hosts->count; i++)
{
gchar *name;
name = gvm_host_value_str (excluded_hosts->hosts[i]);
if (name)
g_hash_table_insert (name_table, name, hosts);
}
/* Check for hosts values in hash table. */
for (i = 0; i < hosts->count; i++)
{
gchar *name;
name = gvm_host_value_str (hosts->hosts[i]);
if (name)
{
if (g_hash_table_lookup (name_table, name))
{
gvm_host_free (hosts->hosts[i]);
hosts->hosts[i] = NULL;
excluded++;
g_free (name);
continue;
}
g_free (name);
}
}
/* Cleanup. */
if (excluded)
gvm_hosts_fill_gaps (hosts);
hosts->count -= excluded;
hosts->removed += excluded;
hosts->current = 0;
g_hash_table_destroy (name_table);
gvm_hosts_free (excluded_hosts);
return excluded;
}
GSList *
gvm_hosts_allowed_only (gvm_hosts_t *hosts, const char *deny_hosts_str,
const char *allow_hosts_str)
{
gvm_hosts_t *allowed_hosts, *denied_hosts;
GHashTable *name_allow_table = NULL, *name_deny_table = NULL;
GSList *removed = NULL;
size_t excluded = 0, i;
if (hosts == NULL || (deny_hosts_str == NULL && allow_hosts_str == NULL))
return NULL;
// Prepare list of denied and allowed hosts
denied_hosts = gvm_hosts_new_with_max (deny_hosts_str, 0);
allowed_hosts = gvm_hosts_new_with_max (allow_hosts_str, 0);
if (denied_hosts == NULL && allowed_hosts == NULL)
return NULL;
if (gvm_hosts_count (denied_hosts) == 0)
gvm_hosts_free (denied_hosts);
else
{
/* Hash host values from denied hosts list. */
name_deny_table =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < denied_hosts->count; i++)
{
gchar *name;
name = gvm_host_value_str (denied_hosts->hosts[i]);
if (name)
g_hash_table_insert (name_deny_table, name, hosts);
}
}
if (gvm_hosts_count (allowed_hosts) == 0)
gvm_hosts_free (allowed_hosts);
else
{
/* Hash host values from allowed hosts list. */
name_allow_table =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < allowed_hosts->count; i++)
{
gchar *name;
name = gvm_host_value_str (allowed_hosts->hosts[i]);
if (name)
g_hash_table_insert (name_allow_table, name, hosts);
}
}
/* Check for authorized hosts in hash table and create a list of removed
* hosts. */
for (i = 0; i < hosts->count; i++)
{
gchar *name;
name = gvm_host_value_str (hosts->hosts[i]);
if (name)
{
if (denied_hosts != NULL
&& g_hash_table_lookup (name_deny_table, name))
{
gvm_host_free (hosts->hosts[i]);
hosts->hosts[i] = NULL;
excluded++;
removed = g_slist_prepend (removed, name);
continue;
}
else if (allowed_hosts != NULL
&& !g_hash_table_lookup (name_allow_table, name))
{
gvm_host_free (hosts->hosts[i]);
hosts->hosts[i] = NULL;
excluded++;
removed = g_slist_prepend (removed, name);
continue;
}
g_free (name);
}
}
/* Cleanup. */
if (excluded)
gvm_hosts_fill_gaps (hosts);
hosts->count -= excluded;
hosts->removed += excluded;
hosts->current = 0;
if (name_allow_table != NULL)
g_hash_table_destroy (name_allow_table);
if (name_deny_table != NULL)
g_hash_table_destroy (name_deny_table);
if (allowed_hosts != NULL)
gvm_hosts_free (allowed_hosts);
if (denied_hosts != NULL)
gvm_hosts_free (denied_hosts);
return removed;
}
int
gvm_hosts_exclude (gvm_hosts_t *hosts, const char *excluded_str)
{
return gvm_hosts_exclude_with_max (hosts, excluded_str, 0);
}
gvm_host_t *
gvm_host_from_str (const gchar *host_str)
{
int host_type;
if (host_str == NULL)
return NULL;
/* IPv4, hostname, IPv6 */
/* -1 if error. */
host_type = gvm_get_host_type (host_str);
switch (host_type)
{
case HOST_TYPE_NAME:
case HOST_TYPE_IPV4:
case HOST_TYPE_IPV6:
{
/* New host. */
gvm_host_t *host = gvm_host_new ();
host->type = host_type;
if (host_type == HOST_TYPE_NAME)
host->name = g_ascii_strdown (host_str, -1);
else if (host_type == HOST_TYPE_IPV4)
{
if (inet_pton (AF_INET, host_str, &host->addr) != 1)
break;
}
else if (host_type == HOST_TYPE_IPV6)
{
if (inet_pton (AF_INET6, host_str, &host->addr6) != 1)
break;
}
return host;
}
case -1:
default:
return NULL;
}
return NULL;
}
char *
gvm_host_reverse_lookup (gvm_host_t *host)
{
int retry = 10;
gchar hostname[NI_MAXHOST];
void *addr;
size_t addrlen;
struct sockaddr_in sa;
struct sockaddr_in6 sa6;
if (!host)
return NULL;
if (host->type == HOST_TYPE_IPV4)
{
addr = &sa;
addrlen = sizeof (sa);
memset (addr, '\0', addrlen);
sa.sin_addr = host->addr;
sa.sin_family = AF_INET;
}
else if (host->type == HOST_TYPE_IPV6)
{
addr = &sa6;
addrlen = sizeof (sa6);
memset (&sa6, '\0', addrlen);
memcpy (&sa6.sin6_addr, &host->addr6, 16);
sa6.sin6_family = AF_INET6;
}
else
return NULL;
while (retry--)
{
int ret = getnameinfo (addr, addrlen, hostname, sizeof (hostname), NULL,
0, NI_NAMEREQD);
if (!ret)
return g_ascii_strdown (hostname, -1);
if (ret != EAI_AGAIN)
break;
usleep (10000); // 10ms
}
return NULL;
}
static int
host_name_verify (gvm_host_t *host, const char *value)
{
GSList *list, *tmp;
char *host_str;
int ret = -1;
assert (host);
assert (value);
host_str = gvm_host_value_str (host);
list = tmp = gvm_resolve_list (value);
while (tmp)
{
char buffer[INET6_ADDRSTRLEN];
addr6_to_str (tmp->data, buffer);
if (!strcasecmp (host_str, buffer))
{
ret = 0;
break;
}
tmp = tmp->next;
}
g_free (host_str);
g_slist_free_full (list, g_free);
return ret;
}
void
gvm_host_add_reverse_lookup (gvm_host_t *host)
{
GSList *vhosts;
gvm_vhost_t *vhost;
char *value;
if (!host || host->type == HOST_TYPE_NAME)
return;
value = gvm_host_reverse_lookup (host);
if (!value)
return;
if (host_name_verify (host, value))
{
g_free (value);
return;
}
/* Don't add vhost, if already in the list. */
vhosts = host->vhosts;
while (vhosts)
{
if (!strcasecmp (((gvm_vhost_t *) vhosts->data)->value, value))
{
g_free (value);
return;
}
vhosts = vhosts->next;
}
vhost = gvm_vhost_new (value, g_strdup ("Reverse-DNS"));
host->vhosts = g_slist_prepend (host->vhosts, vhost);
}
gvm_hosts_t *
gvm_hosts_reverse_lookup_only_excluded (gvm_hosts_t *hosts)
{
size_t i, count = 0;
gvm_hosts_t *excluded = gvm_hosts_new ("");
if (hosts == NULL)
return NULL;
for (i = 0; i < hosts->count; i++)
{
gchar *name = gvm_host_reverse_lookup (hosts->hosts[i]);
if (name == NULL)
{
gvm_hosts_add (excluded, gvm_duplicate_host (hosts->hosts[i]));
gvm_host_free (hosts->hosts[i]);
hosts->hosts[i] = NULL;
count++;
}
else
g_free (name);
}
if (count)
gvm_hosts_fill_gaps (hosts);
hosts->count -= count;
hosts->removed += count;
hosts->current = 0;
return excluded;
}
int
gvm_hosts_reverse_lookup_only (gvm_hosts_t *hosts)
{
gvm_hosts_t *excluded;
int count = 0;
if (hosts == NULL)
return -1;
excluded = gvm_hosts_reverse_lookup_only_excluded (hosts);
count = excluded->count;
gvm_hosts_free (excluded);
return count;
}
gvm_hosts_t *
gvm_hosts_reverse_lookup_unify_excluded (gvm_hosts_t *hosts)
{
size_t i, count = 0;
GHashTable *name_table;
gvm_hosts_t *excluded = NULL;
if (hosts == NULL)
return NULL;
excluded = gvm_hosts_new ("");
name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < hosts->count; i++)
{
gchar *name;
name = gvm_host_reverse_lookup (hosts->hosts[i]);
if (name)
{
if (g_hash_table_lookup (name_table, name))
{
gvm_hosts_add (excluded, gvm_duplicate_host (hosts->hosts[i]));
gvm_host_free (hosts->hosts[i]);
hosts->hosts[i] = NULL;
count++;
g_free (name);
}
else
{
/* Insert in the hash table. Value not important. */
g_hash_table_insert (name_table, name, hosts);
}
}
}
if (count)
gvm_hosts_fill_gaps (hosts);
g_hash_table_destroy (name_table);
hosts->removed += count;
hosts->count -= count;
hosts->current = 0;
return excluded;
}
int
gvm_hosts_reverse_lookup_unify (gvm_hosts_t *hosts)
{
gvm_hosts_t *excluded = NULL;
int count = 0;
if (hosts == NULL)
return -1;
excluded = gvm_hosts_reverse_lookup_unify_excluded (hosts);
count = excluded->count;
gvm_hosts_free (excluded);
return count;
}
unsigned int
gvm_hosts_count (const gvm_hosts_t *hosts)
{
return hosts ? hosts->count : 0;
}
unsigned int
gvm_hosts_removed (const gvm_hosts_t *hosts)
{
return hosts ? hosts->removed : 0;
}
unsigned int
gvm_hosts_duplicated (const gvm_hosts_t *hosts)
{
return hosts ? hosts->duplicated : 0;
}
gvm_host_t *
gvm_host_find_in_hosts (const gvm_host_t *host, const struct in6_addr *addr,
const gvm_hosts_t *hosts)
{
char *host_str;
size_t i;
if (host == NULL || hosts == NULL)
return NULL;
host_str = gvm_host_value_str (host);
for (i = 0; i < hosts->count; i++)
{
gvm_host_t *current_host = hosts->hosts[i];
char *tmp = gvm_host_value_str (current_host);
if (strcasecmp (host_str, tmp) == 0)
{
g_free (host_str);
g_free (tmp);
return current_host;
}
g_free (tmp);
/* Hostnames in hosts list shouldn't be resolved. */
if (addr && gvm_host_type (current_host) != HOST_TYPE_NAME)
{
struct in6_addr tmpaddr;
gvm_host_get_addr6 (current_host, &tmpaddr);
if (memcmp (addr->s6_addr, &tmpaddr.s6_addr, 16) == 0)
{
g_free (host_str);
return current_host;
}
}
}
g_free (host_str);
return NULL;
}
gvm_host_t *
gvm_duplicate_host (gvm_host_t *host)
{
gvm_host_t *ret = NULL;
if (host == NULL)
return NULL;
ret = gvm_host_new ();
ret->type = host->type;
switch (host->type)
{
case HOST_TYPE_NAME:
ret->name = g_strdup (host->name);
break;
case HOST_TYPE_IPV4:
ret->addr.s_addr = host->addr.s_addr;
break;
case HOST_TYPE_IPV6:
ret->addr6.__in6_u = host->addr6.__in6_u;
break;
default:
g_free (ret);
return NULL;
}
ret->vhosts = g_slist_copy_deep (host->vhosts, gvm_duplicate_vhost, NULL);
return ret;
}
int
gvm_host_in_hosts (const gvm_host_t *host, const struct in6_addr *addr,
const gvm_hosts_t *hosts)
{
if (gvm_host_find_in_hosts (host, addr, hosts))
return 1;
return 0;
}
enum host_type
gvm_host_type (const gvm_host_t *host)
{
assert (host);
return host->type;
}
gchar *
gvm_host_type_str (const gvm_host_t *host)
{
if (host == NULL)
return NULL;
return host_type_str[host->type];
}
gchar *
gvm_host_value_str (const gvm_host_t *host)
{
if (host == NULL)
return NULL;
switch (host->type)
{
case HOST_TYPE_NAME:
return g_strdup (host->name);
break;
case HOST_TYPE_IPV4:
case HOST_TYPE_IPV6:
/* Handle both cases using inet_ntop(). */
{
int family, size;
gchar *str;
const void *srcaddr;
if (host->type == HOST_TYPE_IPV4)
{
family = AF_INET;
size = INET_ADDRSTRLEN;
srcaddr = &host->addr;
}
else
{
family = AF_INET6;
size = INET6_ADDRSTRLEN;
srcaddr = &host->addr6;
}
str = g_malloc0 (size);
if (inet_ntop (family, srcaddr, str, size) == NULL)
{
perror ("inet_ntop");
g_free (str);
return NULL;
}
return str;
}
default:
return g_strdup ("Erroneous host type: Should be Hostname/IPv4/IPv6.");
}
}
int
gvm_host_resolve (const gvm_host_t *host, void *dst, int family)
{
if (host == NULL || dst == NULL || host->type != HOST_TYPE_NAME)
return -1;
return gvm_resolve (host->name, dst, family);
}
int
gvm_host_get_addr6 (const gvm_host_t *host, struct in6_addr *ip6)
{
if (host == NULL || ip6 == NULL)
return -1;
switch (gvm_host_type (host))
{
case HOST_TYPE_IPV6:
memcpy (ip6, &host->addr6, sizeof (struct in6_addr));
return 0;
case HOST_TYPE_IPV4:
ipv4_as_ipv6 (&host->addr, ip6);
return 0;
case HOST_TYPE_NAME:
{
struct in_addr ip4;
/* Fail if IPv4 and IPv6 both don't resolve. */
if (gvm_host_resolve (host, &ip4, AF_INET) == 0)
ipv4_as_ipv6 (&ip4, ip6);
else if (gvm_host_resolve (host, ip6, AF_INET6) == -1)
return -1;
return 0;
}
default:
return -1;
}
}
gvm_hosts_add
void gvm_hosts_add(gvm_hosts_t *hosts, gvm_host_t *host)
Inserts a host object at the end of a hosts collection.
Definition hosts.c:966
gvm_host_in_hosts
int gvm_host_in_hosts(const gvm_host_t *host, const struct in6_addr *addr, const gvm_hosts_t *hosts)
Returns whether a host has an equal host in a hosts collection. eg. 192.168.10.1 has an equal in list...
Definition hosts.c:2242
is_long_range_network
static int is_long_range_network(const char *str)
Checks if a buffer points to a valid long range-expressed network. "192.168.12.1-192....
Definition hosts.c:229
gvm_hosts_reverse_lookup_unify_excluded
gvm_hosts_t * gvm_hosts_reverse_lookup_unify_excluded(gvm_hosts_t *hosts)
Removes hosts duplicates that reverse-lookup to the same value. Not to be used while iterating over t...
Definition hosts.c:2029
cidr_get_ip
static int cidr_get_ip(const char *str, struct in_addr *addr)
Gets the IPv4 value from a CIDR-expressed block. eg. For "192.168.1.10/24" it is "192....
Definition hosts.c:158
gvm_hosts_reverse_lookup_only
int gvm_hosts_reverse_lookup_only(gvm_hosts_t *hosts)
Removes hosts that don't reverse-lookup from the hosts collection. Not to be used while iterating ove...
Definition hosts.c:2004
gvm_host_value_str
gchar * gvm_host_value_str(const gvm_host_t *host)
Gets a host's value in printable format.
Definition hosts.c:2290
short_range_network_ips
static int short_range_network_ips(const char *str, struct in_addr *first, struct in_addr *last)
Gets the first and last IPv4 addresses from a short range-expressed network. "192....
Definition hosts.c:352
gvm_host_resolve
int gvm_host_resolve(const gvm_host_t *host, void *dst, int family)
Resolves a host object's name to an IPv4 or IPv6 address. Host object should be of type HOST_TYPE_NAM...
Definition hosts.c:2347
gvm_hosts_reverse_lookup_only_excluded
gvm_hosts_t * gvm_hosts_reverse_lookup_only_excluded(gvm_hosts_t *hosts)
Removes hosts that don't reverse-lookup from the hosts collection. Not to be used while iterating ove...
Definition hosts.c:1963
host_type_str
gchar * host_type_str[HOST_TYPE_MAX]
Definition hosts.c:40
is_long_range6_network
static int is_long_range6_network(const char *str)
Checks if a buffer points to a valid long IPv6 range-expressed network. "::fee5-::1:530" is valid.
Definition hosts.c:645
long_range_network_ips
static int long_range_network_ips(const char *str, struct in_addr *first, struct in_addr *last)
Gets the first and last IPv4 addresses from a long range-expressed network. eg. "192....
Definition hosts.c:264
gvm_host_reverse_lookup
char * gvm_host_reverse_lookup(gvm_host_t *host)
Checks for a host object reverse dns lookup existence.
Definition hosts.c:1836
is_cidr_block
static int is_cidr_block(const char *str)
Checks if a buffer points to an IPv4 CIDR-expressed block. "192.168.12.3/24" is valid,...
Definition hosts.c:91
gvm_duplicate_host
gvm_host_t * gvm_duplicate_host(gvm_host_t *host)
Creates a deep copy of a host. gvm_host_free has to be called on it.
Definition hosts.c:2199
is_short_range_network
static int is_short_range_network(const char *str)
Checks if a buffer points to a valid short range-expressed network. "192.168.11.1-50" is valid,...
Definition hosts.c:304
gvm_vhost_new
gvm_vhost_t * gvm_vhost_new(char *value, char *source)
Creates a new gvm_vhost_t object.
Definition hosts.c:875
gvm_hosts_new
gvm_hosts_t * gvm_hosts_new(const gchar *hosts_str)
Creates a new gvm_hosts_t structure and the associated hosts objects from the provided hosts_str.
Definition hosts.c:1301
gvm_hosts_next
gvm_host_t * gvm_hosts_next(gvm_hosts_t *hosts)
Gets the next gvm_host_t from a gvm_hosts_t structure. The state of iteration is kept internally with...
Definition hosts.c:1315
gvm_hosts_allowed_only
GSList * gvm_hosts_allowed_only(gvm_hosts_t *hosts, const char *deny_hosts_str, const char *allow_hosts_str)
Returns a list of hosts after a host authorization check.
Definition hosts.c:1658
gvm_host_free
void gvm_host_free(gpointer host)
Frees the memory occupied by an gvm_host_t object.
Definition hosts.c:945
gvm_hosts_removed
unsigned int gvm_hosts_removed(const gvm_hosts_t *hosts)
Gets the count of single values in hosts string that were removed (duplicates / excluded....
Definition hosts.c:2120
gvm_host_type_str
gchar * gvm_host_type_str(const gvm_host_t *host)
Gets a host's type in printable format.
Definition hosts.c:2274
gvm_host_add_reverse_lookup
void gvm_host_add_reverse_lookup(gvm_host_t *host)
Add a host's reverse-lookup name to the vhosts list.
Definition hosts.c:1921
gvm_hosts_new_with_max
gvm_hosts_t * gvm_hosts_new_with_max(const gchar *hosts_str, unsigned int max_hosts)
Creates a new gvm_hosts_t structure and the associated hosts objects from the provided hosts_str.
Definition hosts.c:1104
gvm_cidr6_block_ips
int gvm_cidr6_block_ips(const char *str, struct in6_addr *first, struct in6_addr *last)
Gets the first and last usable IPv4 addresses from a CIDR-expressed block. eg. "192....
Definition hosts.c:572
is_hostname
static int is_hostname(const char *str)
Checks if a buffer points to a valid hostname.
Definition hosts.c:396
gvm_host_new
static gvm_host_t * gvm_host_new()
Creates a new gvm_host_t object.
Definition hosts.c:930
gvm_hosts_reverse
void gvm_hosts_reverse(gvm_hosts_t *hosts)
Reverses the order of the hosts objects in the collection. Not to be used while iterating over the si...
Definition hosts.c:1431
gvm_hosts_shuffle
void gvm_hosts_shuffle(gvm_hosts_t *hosts)
Randomizes the order of the hosts objects in the collection. Not to be used while iterating over the ...
Definition hosts.c:1399
gvm_hosts_duplicated
unsigned int gvm_hosts_duplicated(const gvm_hosts_t *hosts)
Gets the count of single values in hosts string that were duplicated and therefore removed from the l...
Definition hosts.c:2134
is_short_range6_network
static int is_short_range6_network(const char *str)
Checks if a buffer points to a valid short IPv6 range-expressed network. "::200:ff:1-fee5" is valid.
Definition hosts.c:720
gvm_host_from_str
gvm_host_t * gvm_host_from_str(const gchar *host_str)
Creates a new gvm_host_t from a host string.
Definition hosts.c:1787
gvm_hosts_deduplicate
static void gvm_hosts_deduplicate(gvm_hosts_t *hosts)
Removes duplicate hosts values from an gvm_hosts_t structure. Also resets the iterator current positi...
Definition hosts.c:1044
gvm_cidr6_get_block
int gvm_cidr6_get_block(const char *str, unsigned int *block)
Gets the network block value from a CIDR-expressed block string. For "192.168.1.1/24" it is 24.
Definition hosts.c:516
short_range6_network_ips
static int short_range6_network_ips(const char *str, struct in6_addr *first, struct in6_addr *last)
Gets the first and last IPv6 addresses from a short range-expressed network. eg. "\::ffee:1:1001-1005...
Definition hosts.c:768
gvm_cidr6_get_ip
int gvm_cidr6_get_ip(const char *str, struct in6_addr *addr6)
Gets the IPv4 value from a CIDR-expressed block. eg. For "192.168.1.10/24" it is "192....
Definition hosts.c:537
is_ipv6_address
static int is_ipv6_address(const char *str)
Checks if a buffer points to a valid IPv6 address. "0:0:0:0:0:0:0:1", "::1" and "::FFFF:192....
Definition hosts.c:75
gvm_hosts_init
static gvm_hosts_t * gvm_hosts_init(const char *hosts_str)
Creates a hosts collection from a hosts string.
Definition hosts.c:988
long_range6_network_ips
static int long_range6_network_ips(const char *str, struct in6_addr *first, struct in6_addr *last)
Gets the first and last IPv6 addresses from a long range-expressed network. eg. "::1:200:7-::1:205:50...
Definition hosts.c:680
gvm_host_get_addr6
int gvm_host_get_addr6(const gvm_host_t *host, struct in6_addr *ip6)
Gives a host object's value as an IPv6 address. If the host type is hostname, it resolves the IPv4 ad...
Definition hosts.c:2368
is_ipv4_address
static int is_ipv4_address(const char *str)
Checks if a buffer points to a valid IPv4 address. "192.168.11.1" is valid, "192.168....
Definition hosts.c:59
gvm_hosts_move_current_host_to_end
void gvm_hosts_move_current_host_to_end(gvm_hosts_t *hosts)
Move the current gvm_host_t from a gvm_hosts_t structure to the end of the hosts list.
Definition hosts.c:1333
gvm_vhosts_exclude
int gvm_vhosts_exclude(gvm_host_t *host, const char *excluded_str)
Exclude a list of vhosts from a host's vhosts list.
Definition hosts.c:1525
gvm_hosts_exclude_with_max
int gvm_hosts_exclude_with_max(gvm_hosts_t *hosts, const char *excluded_str, unsigned int max_hosts)
Excludes a set of hosts provided as a string from a hosts collection. Not to be used while iterating ...
Definition hosts.c:1580
gvm_hosts_resolve
GSList * gvm_hosts_resolve(gvm_hosts_t *hosts)
Resolves host objects of type name in a hosts collection, replacing hostnames with IPv4 values....
Definition hosts.c:1457
gvm_host_type
enum host_type gvm_host_type(const gvm_host_t *host)
Gets a host object's type.
Definition hosts.c:2259
gvm_duplicate_vhost
gpointer gvm_duplicate_vhost(gconstpointer vhost, gpointer data)
Creates a deep copy of a gvm_vhost_t object.
Definition hosts.c:910
gvm_hosts_fill_gaps
static void gvm_hosts_fill_gaps(gvm_hosts_t *hosts)
Fill the gaps in the array of a hosts collection, which are caused by the removal of host entries.
Definition hosts.c:1006
host_name_verify
static int host_name_verify(gvm_host_t *host, const char *value)
Verifies that hostname value resolves to a host's IP.
Definition hosts.c:1889
gvm_host_find_in_hosts
gvm_host_t * gvm_host_find_in_hosts(const gvm_host_t *host, const struct in6_addr *addr, const gvm_hosts_t *hosts)
Find the gvm_host_t from a gvm_hosts_t structure.
Definition hosts.c:2150
gvm_get_host_type
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition hosts.c:814
cidr_get_block
static int cidr_get_block(const char *str, unsigned int *block)
Gets the network block value from a CIDR-expressed block string. For "192.168.1.1/24" it is 24.
Definition hosts.c:137
gvm_hosts_count
unsigned int gvm_hosts_count(const gvm_hosts_t *hosts)
Gets the count of single hosts objects in a hosts collection.
Definition hosts.c:2106
cidr_block_ips
static int cidr_block_ips(const char *str, struct in_addr *first, struct in_addr *last)
Gets the first and last usable IPv4 addresses from a CIDR-expressed block. eg. "192....
Definition hosts.c:198
gvm_vhost_free
static void gvm_vhost_free(gpointer vhost)
Frees the memory occupied by an gvm_vhost_t object.
Definition hosts.c:892
gvm_hosts_free
void gvm_hosts_free(gvm_hosts_t *hosts)
Frees memory occupied by an gvm_hosts_t structure.
Definition hosts.c:1376
gvm_hosts_exclude
int gvm_hosts_exclude(gvm_hosts_t *hosts, const char *excluded_str)
Excludes a set of hosts provided as a string from a hosts collection. Not to be used while iterating ...
Definition hosts.c:1771
gvm_is_cidr6_block
int gvm_is_cidr6_block(const char *str)
Checks if a buffer points to an IPv6 CIDR-expressed block. "2620:0:2d0:200::7/120" is valid,...
Definition hosts.c:470
gvm_hosts_reverse_lookup_unify
int gvm_hosts_reverse_lookup_unify(gvm_hosts_t *hosts)
Removes hosts duplicates that reverse-lookup to the same value. Not to be used while iterating over t...
Definition hosts.c:2085
hosts.h
Protos and data structures for Hosts collections and single hosts objects.
host_type
host_type
Definition hosts.h:34
HOST_TYPE_RANGE_SHORT
@ HOST_TYPE_RANGE_SHORT
Definition hosts.h:38
HOST_TYPE_RANGE6_SHORT
@ HOST_TYPE_RANGE6_SHORT
Definition hosts.h:43
HOST_TYPE_RANGE_LONG
@ HOST_TYPE_RANGE_LONG
Definition hosts.h:39
HOST_TYPE_RANGE6_LONG
@ HOST_TYPE_RANGE6_LONG
Definition hosts.h:42
HOST_TYPE_NAME
@ HOST_TYPE_NAME
Definition hosts.h:35
HOST_TYPE_IPV6
@ HOST_TYPE_IPV6
Definition hosts.h:40
HOST_TYPE_CIDR6_BLOCK
@ HOST_TYPE_CIDR6_BLOCK
Definition hosts.h:41
HOST_TYPE_MAX
@ HOST_TYPE_MAX
Definition hosts.h:44
HOST_TYPE_IPV4
@ HOST_TYPE_IPV4
Definition hosts.h:36
HOST_TYPE_CIDR_BLOCK
@ HOST_TYPE_CIDR_BLOCK
Definition hosts.h:37
gvm_host_t
struct gvm_host gvm_host_t
Definition hosts.h:48
gvm_vhost_t
struct gvm_vhost gvm_vhost_t
Definition hosts.h:49
gvm_hosts_t
struct gvm_hosts gvm_hosts_t
Definition hosts.h:50
addr6_to_str
void addr6_to_str(const struct in6_addr *addr6, char *str)
Stringifies an IP address.
Definition networking.c:261
ipv4_as_ipv6
void ipv4_as_ipv6(const struct in_addr *ip4, struct in6_addr *ip6)
Maps an IPv4 address as an IPv6 address. eg. 192.168.10.20 would map to ::ffff:192....
Definition networking.c:243
gvm_resolve
int gvm_resolve(const char *name, void *dst, int family)
Resolves a hostname to an IPv4 or IPv6 address.
Definition networking.c:389
gvm_resolve_list
GSList * gvm_resolve_list(const char *name)
Returns a list of addresses that a hostname resolves to.
Definition networking.c:339
networking.h
GVM Networking related API.
gvm_host::addr6
struct in6_addr addr6
Definition hosts.h:66
gvm_host::name
gchar * name
Definition hosts.h:64
gvm_host::vhosts
GSList * vhosts
Definition hosts.h:69
gvm_host::addr
struct in_addr addr
Definition hosts.h:65
gvm_host::type
enum host_type type
Definition hosts.h:68
gvm_hosts::max_size
size_t max_size
Definition hosts.h:91
gvm_hosts::removed
size_t removed
Definition hosts.h:94
gvm_hosts::orig_str
gchar * orig_str
Definition hosts.h:89
gvm_hosts::duplicated
size_t duplicated
Definition hosts.h:95
gvm_hosts::current
size_t current
Definition hosts.h:92
gvm_hosts::count
size_t count
Definition hosts.h:93
gvm_hosts::hosts
gvm_host_t ** hosts
Definition hosts.h:90
gvm_vhost::value
char * value
Definition hosts.h:77
gvm_vhost::source
char * source
Definition hosts.h:78