Greenbone Vulnerability Management Libraries 23.9.3
hosts.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013-2023 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
15
16#include "hosts.h"
17
18#include "networking.h" /* for ipv4_as_ipv6, addr6_as_str, gvm_resolve */
19
20#include <arpa/inet.h> /* for inet_pton, inet_ntop */
21#include <assert.h> /* for assert */
22#include <ctype.h> /* for isdigit */
23#include <malloc.h>
24#include <netdb.h> /* for getnameinfo, NI_NAMEREQD */
25#include <stdint.h> /* for uint8_t, uint32_t */
26#include <stdio.h> /* for sscanf, perror */
27#include <stdlib.h> /* for strtol, atoi */
28#include <string.h> /* for strchr, memcpy, memcmp, bzero, strcasecmp */
29#include <sys/socket.h> /* for AF_INET, AF_INET6, sockaddr */
30#include <unistd.h> /* for usleep() */
31
32#undef G_LOG_DOMAIN
36#define G_LOG_DOMAIN "libgvm base"
37
38/* Static variables */
39
41 [HOST_TYPE_NAME] = "Hostname",
42 [HOST_TYPE_IPV4] = "IPv4",
43 [HOST_TYPE_IPV6] = "IPv6",
44 [HOST_TYPE_CIDR_BLOCK] = "IPv4 CIDR block",
45 [HOST_TYPE_RANGE_SHORT] = "IPv4 short range",
46 [HOST_TYPE_RANGE_LONG] = "IPv4 long range"};
47
48/* Function definitions */
49
58static int
59is_ipv4_address (const char *str)
60{
61 struct sockaddr_in sa;
62
63 return inet_pton (AF_INET, str, &(sa.sin_addr)) == 1;
64}
65
74static int
75is_ipv6_address (const char *str)
76{
77 struct sockaddr_in6 sa6;
78
79 return inet_pton (AF_INET6, str, &(sa6.sin6_addr)) == 1;
80}
81
90static int
91is_cidr_block (const char *str)
92{
93 long block;
94 char *addr_str, *block_str, *p;
95
96 addr_str = g_strdup (str);
97 block_str = strchr (addr_str, '/');
98 if (block_str == NULL)
99 {
100 g_free (addr_str);
101 return 0;
102 }
103
104 /* Separate the address from the block value. */
105 *block_str = '\0';
106 block_str++;
107
108 if (!is_ipv4_address (addr_str) || !isdigit (*block_str))
109 {
110 g_free (addr_str);
111 return 0;
112 }
113
114 p = NULL;
115 block = strtol (block_str, &p, 10);
116
117 if (*p || block <= 0 || block > 30)
118 {
119 g_free (addr_str);
120 return 0;
121 }
122
123 g_free (addr_str);
124 return 1;
125}
126
136static int
137cidr_get_block (const char *str, unsigned int *block)
138{
139 if (str == NULL || block == NULL)
140 return -1;
141
142 if (sscanf (str, "%*[0-9.]/%2u", block) != 1)
143 return -1;
144
145 return 0;
146}
147
157static int
158cidr_get_ip (const char *str, struct in_addr *addr)
159{
160 gchar *addr_str, *tmp;
161
162 if (str == NULL || addr == NULL)
163 return -1;
164
165 addr_str = g_strdup (str);
166 tmp = strchr (addr_str, '/');
167 if (tmp == NULL)
168 {
169 g_free (addr_str);
170 return -1;
171 }
172 *tmp = '\0';
173
174 if (inet_pton (AF_INET, addr_str, addr) != 1)
175 return -1;
176
177 g_free (addr_str);
178 return 0;
179}
180
197static int
198cidr_block_ips (const char *str, struct in_addr *first, struct in_addr *last)
199{
200 unsigned int block;
201
202 if (str == NULL || first == NULL || last == NULL)
203 return -1;
204
205 /* Get IP and block values. */
206 if (cidr_get_block (str, &block) == -1)
207 return -1;
208 if (cidr_get_ip (str, first) == -1)
209 return -1;
210
211 /* First IP: And with mask and increment. */
212 first->s_addr &= htonl (0xffffffff ^ ((1 << (32 - block)) - 1));
213 first->s_addr = htonl (ntohl (first->s_addr) + 1);
214
215 /* Last IP: First IP + Number of usable hosts - 1. */
216 last->s_addr = htonl (ntohl (first->s_addr) + (1 << (32 - block)) - 3);
217 return 0;
218}
219
228static int
229is_long_range_network (const char *str)
230{
231 char *first_str, *second_str;
232 int ret;
233
234 first_str = g_strdup (str);
235 second_str = strchr (first_str, '-');
236 if (second_str == NULL)
237 {
238 g_free (first_str);
239 return 0;
240 }
241
242 /* Separate the addresses. */
243 *second_str = '\0';
244 second_str++;
245
246 ret = is_ipv4_address (first_str) && is_ipv4_address (second_str);
247 g_free (first_str);
248
249 return ret;
250}
251
263static int
264long_range_network_ips (const char *str, struct in_addr *first,
265 struct in_addr *last)
266{
267 char *first_str, *last_str;
268
269 if (str == NULL || first == NULL || last == NULL)
270 return -1;
271
272 first_str = g_strdup (str);
273 last_str = strchr (first_str, '-');
274 if (last_str == NULL)
275 {
276 g_free (first_str);
277 return -1;
278 }
279
280 /* Separate the two IPs. */
281 *last_str = '\0';
282 last_str++;
283
284 if (inet_pton (AF_INET, first_str, first) != 1
285 || inet_pton (AF_INET, last_str, last) != 1)
286 {
287 g_free (first_str);
288 return -1;
289 }
290
291 g_free (first_str);
292 return 0;
293}
294
303static int
304is_short_range_network (const char *str)
305{
306 long end;
307 char *ip_str, *end_str, *p;
308
309 ip_str = g_strdup (str);
310 end_str = strchr (ip_str, '-');
311 if (end_str == NULL)
312 {
313 g_free (ip_str);
314 return 0;
315 }
316
317 /* Separate the addresses. */
318 *end_str = '\0';
319 end_str++;
320
321 if (!is_ipv4_address (ip_str) || !isdigit (*end_str))
322 {
323 g_free (ip_str);
324 return 0;
325 }
326
327 p = NULL;
328 end = strtol (end_str, &p, 10);
329
330 if (*p || end < 0 || end > 255)
331 {
332 g_free (ip_str);
333 return 0;
334 }
335
336 g_free (ip_str);
337 return 1;
338}
339
351static int
352short_range_network_ips (const char *str, struct in_addr *first,
353 struct in_addr *last)
354{
355 char *first_str, *last_str;
356 int end;
357
358 if (str == NULL || first == NULL || last == NULL)
359 return -1;
360
361 first_str = g_strdup (str);
362 last_str = strchr (first_str, '-');
363 if (last_str == NULL)
364 {
365 g_free (first_str);
366 return -1;
367 }
368
369 /* Separate the two IPs. */
370 *last_str = '\0';
371 last_str++;
372 end = atoi (last_str);
373
374 /* Get the first IP */
375 if (inet_pton (AF_INET, first_str, first) != 1)
376 {
377 g_free (first_str);
378 return -1;
379 }
380
381 /* Get the last IP */
382 last->s_addr = htonl ((ntohl (first->s_addr) & 0xffffff00) + end);
383
384 g_free (first_str);
385 return 0;
386}
387
395static int
396is_hostname (const char *str)
397{
398 gchar *copy, **point, **split;
399
400 /* From
401 * https://stackoverflow.com/questions/2532053/validate-a-hostname-string. */
402
403 /* Remove one dot from the end. */
404
405 copy = g_strdup (str);
406 if (copy[strlen (copy) - 1] == '.')
407 copy[strlen (copy) - 1] = '\0';
408
409 /* Check length. */
410
411 if (strlen (copy) == 0 || strlen (copy) > 253)
412 {
413 g_free (copy);
414 return 0;
415 }
416
417 /* Split on dots. */
418
419 point = split = g_strsplit (copy, ".", 0);
420 g_free (copy);
421
422 /* Last part (TLD) may not be an integer. */
423
424 if (*point)
425 {
426 gchar *last;
427
428 while (*(point + 1))
429 point++;
430 last = *point;
431 if (strlen (last))
432 {
433 while (*last && isdigit (*last))
434 last++;
435 if (*last == '\0')
436 {
437 g_strfreev (split);
438 return 0;
439 }
440 }
441 }
442
443 /* Check each part. */
444
445 point = split;
446 while (*point)
447 if (g_regex_match_simple ("^(?!-)[a-z0-9_-]{1,63}(?<!-)$", *point,
448 G_REGEX_CASELESS, 0)
449 == 0)
450 {
451 g_strfreev (split);
452 return 0;
453 }
454 else
455 point++;
456
457 g_strfreev (split);
458 return 1;
459}
460
469int
470gvm_is_cidr6_block (const char *str)
471{
472 long block;
473 char *addr6_str, *block_str, *p;
474
475 addr6_str = g_strdup (str);
476 block_str = strchr (addr6_str, '/');
477 if (block_str == NULL)
478 {
479 g_free (addr6_str);
480 return 0;
481 }
482
483 /* Separate the address from the block value. */
484 *block_str = '\0';
485 block_str++;
486
487 if (!is_ipv6_address (addr6_str) || !isdigit (*block_str))
488 {
489 g_free (addr6_str);
490 return 0;
491 }
492
493 p = NULL;
494 block = strtol (block_str, &p, 10);
495
496 if (*p || block <= 0 || block > 128)
497 {
498 g_free (addr6_str);
499 return 0;
500 }
501
502 g_free (addr6_str);
503 return 1;
504}
505
515int
516gvm_cidr6_get_block (const char *str, unsigned int *block)
517{
518 if (str == NULL || block == NULL)
519 return -1;
520
521 if (sscanf (str, "%*[0-9a-fA-F.:]/%3u", block) != 1)
522 return -1;
523
524 return 0;
525}
526
536int
537gvm_cidr6_get_ip (const char *str, struct in6_addr *addr6)
538{
539 gchar *addr6_str, *tmp;
540
541 if (str == NULL || addr6 == NULL)
542 return -1;
543
544 addr6_str = g_strdup (str);
545 tmp = strchr (addr6_str, '/');
546 if (tmp == NULL)
547 {
548 g_free (addr6_str);
549 return -1;
550 }
551 *tmp = '\0';
552
553 if (inet_pton (AF_INET6, addr6_str, addr6) != 1)
554 return -1;
555
556 g_free (addr6_str);
557 return 0;
558}
559
571int
572gvm_cidr6_block_ips (const char *str, struct in6_addr *first,
573 struct in6_addr *last)
574{
575 unsigned int block;
576 int i, j;
577
578 if (str == NULL || first == NULL || last == NULL)
579 return -1;
580
581 /* Get IP and block values. */
582 if (gvm_cidr6_get_block (str, &block) == -1)
583 return -1;
584 if (gvm_cidr6_get_ip (str, first) == -1)
585 return -1;
586 memcpy (&last->s6_addr, &first->s6_addr, 16);
587
588 /* /128 => Specified address is the first and last one. */
589 if (block == 128)
590 return 0;
591
592 /* First IP: And with mask and increment to skip network address. */
593 j = 15;
594 for (i = (128 - block) / 8; i > 0; i--)
595 {
596 first->s6_addr[j] = 0;
597 j--;
598 }
599 first->s6_addr[j] &= 0xff ^ ((1 << ((128 - block) % 8)) - 1);
600
601 /* Last IP: Broadcast address - 1. */
602 j = 15;
603 for (i = (128 - block) / 8; i > 0; i--)
604 {
605 last->s6_addr[j] = 0xff;
606 j--;
607 }
608 last->s6_addr[j] |= (1 << ((128 - block) % 8)) - 1;
609
610 /* /127 => Only two addresses. Don't skip network / broadcast addresses.*/
611 if (block == 127)
612 return 0;
613
614 /* Increment first IP. */
615 for (i = 15; i >= 0; --i)
616 if (first->s6_addr[i] < 255)
617 {
618 first->s6_addr[i]++;
619 break;
620 }
621 else
622 first->s6_addr[i] = 0;
623 /* Decrement last IP. */
624 for (i = 15; i >= 0; --i)
625 if (last->s6_addr[i] > 0)
626 {
627 last->s6_addr[i]--;
628 break;
629 }
630 else
631 last->s6_addr[i] = 0xff;
632
633 return 0;
634}
635
644static int
645is_long_range6_network (const char *str)
646{
647 char *first_str, *second_str;
648 int ret;
649
650 first_str = g_strdup (str);
651 second_str = strchr (first_str, '-');
652 if (second_str == NULL)
653 {
654 g_free (first_str);
655 return 0;
656 }
657
658 /* Separate the addresses. */
659 *second_str = '\0';
660 second_str++;
661
662 ret = is_ipv6_address (first_str) && is_ipv6_address (second_str);
663 g_free (first_str);
664
665 return ret;
666}
667
679static int
680long_range6_network_ips (const char *str, struct in6_addr *first,
681 struct in6_addr *last)
682{
683 char *first_str, *last_str;
684
685 if (str == NULL || first == NULL || last == NULL)
686 return -1;
687
688 first_str = g_strdup (str);
689 last_str = strchr (first_str, '-');
690 if (last_str == NULL)
691 {
692 g_free (first_str);
693 return -1;
694 }
695
696 /* Separate the two IPs. */
697 *last_str = '\0';
698 last_str++;
699
700 if (inet_pton (AF_INET6, first_str, first) != 1
701 || inet_pton (AF_INET6, last_str, last) != 1)
702 {
703 g_free (first_str);
704 return -1;
705 }
706
707 g_free (first_str);
708 return 0;
709}
710
719static int
720is_short_range6_network (const char *str)
721{
722 char *ip_str, *end_str, *p;
723
724 ip_str = g_strdup (str);
725 end_str = strchr (ip_str, '-');
726 if (end_str == NULL)
727 {
728 g_free (ip_str);
729 return 0;
730 }
731
732 /* Separate the addresses. */
733 *end_str = '\0';
734 end_str++;
735
736 if (!is_ipv6_address (ip_str) || *end_str == '\0')
737 {
738 g_free (ip_str);
739 return 0;
740 }
741
742 p = end_str;
743 /* Check that the 2nd part is at most 4 hexadecimal characters. */
744 while (isxdigit (*p) && p++)
745 ;
746 if (*p || p - end_str > 4)
747 {
748 g_free (ip_str);
749 return 0;
750 }
751
752 g_free (ip_str);
753 return 1;
754}
755
767static int
768short_range6_network_ips (const char *str, struct in6_addr *first,
769 struct in6_addr *last)
770{
771 char *first_str, *last_str;
772 long int end;
773
774 if (str == NULL || first == NULL || last == NULL)
775 return -1;
776
777 first_str = g_strdup (str);
778 last_str = strchr (first_str, '-');
779 if (last_str == NULL)
780 {
781 g_free (first_str);
782 return -1;
783 }
784
785 /* Separate the first IP. */
786 *last_str = '\0';
787 last_str++;
788
789 if (inet_pton (AF_INET6, first_str, first) != 1)
790 {
791 g_free (first_str);
792 return -1;
793 }
794
795 /* Calculate the last IP. */
796 memcpy (last, first, sizeof (*last));
797 end = strtol (last_str, NULL, 16);
798 memcpy (&last->s6_addr[15], &end, 1);
799 memcpy (&last->s6_addr[14], ((char *) &end) + 1, 1);
800
801 g_free (first_str);
802 return 0;
803}
804
813int
814gvm_get_host_type (const gchar *str_stripped)
815{
816 /*
817 * We have a single element with no leading or trailing
818 * white spaces. This element could represent different host
819 * definitions: single IPs, host names, CIDR-expressed blocks,
820 * range-expressed networks, IPv6 addresses.
821 */
822
823 /* Null or empty string. */
824 if (str_stripped == NULL || *str_stripped == '\0')
825 return -1;
826
827 /* Check for regular single IPv4 address. */
828 if (is_ipv4_address (str_stripped))
829 return HOST_TYPE_IPV4;
830
831 /* Check for regular single IPv6 address. */
832 if (is_ipv6_address (str_stripped))
833 return HOST_TYPE_IPV6;
834
835 /* Check for regular IPv4 CIDR-expressed block like "192.168.12.0/24" */
836 if (is_cidr_block (str_stripped))
838
839 /* Check for short range-expressed networks "192.168.12.5-40" */
840 if (is_short_range_network (str_stripped))
842
843 /* Check for long range-expressed networks "192.168.1.0-192.168.3.44" */
844 if (is_long_range_network (str_stripped))
846
847 /* Check for regular IPv6 CIDR-expressed block like "2620:0:2d0:200::7/120" */
848 if (gvm_is_cidr6_block (str_stripped))
850
851 /* Check for short range-expressed networks "::1-ef12" */
852 if (is_short_range6_network (str_stripped))
854
855 /* Check for long IPv6 range-expressed networks like "::1:20:7-::1:25:3" */
856 if (is_long_range6_network (str_stripped))
858
859 /* Check for hostname. */
860 if (is_hostname (str_stripped))
861 return HOST_TYPE_NAME;
862
863 return -1;
864}
865
875gvm_vhost_new (char *value, char *source)
876{
877 gvm_vhost_t *vhost;
878
879 vhost = g_malloc0 (sizeof (gvm_vhost_t));
880 vhost->value = value;
881 vhost->source = source;
882
883 return vhost;
884}
885
891static void
892gvm_vhost_free (gpointer vhost)
893{
894 if (vhost)
895 {
896 g_free (((gvm_vhost_t *) vhost)->value);
897 g_free (((gvm_vhost_t *) vhost)->source);
898 }
899 g_free (vhost);
900}
901
909gpointer
910gvm_duplicate_vhost (gconstpointer vhost, gpointer data)
911{
912 (void) (data);
913 gvm_vhost_t *ret = NULL;
914
915 if (!vhost)
916 return NULL;
917
918 ret = gvm_vhost_new (g_strdup (((gvm_vhost_t *) vhost)->value),
919 g_strdup (((gvm_vhost_t *) vhost)->source));
920
921 return ret;
922}
923
929static gvm_host_t *
931{
932 gvm_host_t *host;
933
934 host = g_malloc0 (sizeof (gvm_host_t));
935
936 return host;
937}
938
944void
945gvm_host_free (gpointer host)
946{
947 gvm_host_t *h = host;
948 if (h == NULL)
949 return;
950
951 /* If host of type hostname, free the name buffer, first. */
952 if (h->type == HOST_TYPE_NAME)
953 g_free (h->name);
954
955 g_slist_free_full (h->vhosts, gvm_vhost_free);
956 g_free (h);
957}
958
965void
967{
968 if (hosts->count == hosts->max_size)
969 {
970 hosts->max_size *= 4;
971 hosts->hosts =
972 g_realloc_n (hosts->hosts, hosts->max_size, sizeof (*hosts->hosts));
973 memset (hosts->hosts + hosts->count, '\0',
974 (hosts->max_size - hosts->count) * sizeof (gvm_host_t *));
975 }
976 hosts->hosts[hosts->count] = host;
977 hosts->count++;
978}
979
987static gvm_hosts_t *
988gvm_hosts_init (const char *hosts_str)
989{
990 gvm_hosts_t *hosts;
991
992 hosts = g_malloc0 (sizeof (gvm_hosts_t));
993 hosts->max_size = 1024;
994 hosts->hosts = g_malloc0_n (hosts->max_size, sizeof (gvm_host_t *));
995 hosts->orig_str = g_strdup (hosts_str);
996 return hosts;
997}
998
1005static void
1007{
1008 size_t i;
1009 if (!hosts)
1010 return;
1011
1012 for (i = 0; i < hosts->max_size; i++)
1013 {
1014 if (!hosts->hosts[i])
1015 {
1016 size_t j;
1017
1018 /* Fill the gap with the closest host entry, in order to keep the
1019 * sequential ordering. */
1020 for (j = i + 1; j < hosts->max_size; j++)
1021 {
1022 if (hosts->hosts[j])
1023 {
1024 hosts->hosts[i] = hosts->hosts[j];
1025 hosts->hosts[j] = NULL;
1026 break;
1027 }
1028 }
1029 /* No more entries left, ie. the empty space between count and
1030 * max_size. */
1031 if (!hosts->hosts[i])
1032 return;
1033 }
1034 }
1035}
1036
1043static void
1045{
1049 GHashTable *name_table;
1050 size_t i, duplicates = 0;
1051
1052 if (hosts == NULL)
1053 return;
1054 name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1055
1056 for (i = 0; i < hosts->count; i++)
1057 {
1058 gchar *name;
1059
1060 name = gvm_host_value_str (hosts->hosts[i]);
1061 if (name)
1062 {
1063 gvm_host_t *host, *removed = hosts->hosts[i];
1064
1065 host = g_hash_table_lookup (name_table, name);
1066 if (host)
1067 {
1068 /* Remove duplicate host. Add its vhosts to the original host. */
1069 host->vhosts = g_slist_concat (host->vhosts, removed->vhosts);
1070 removed->vhosts = NULL;
1071 gvm_host_free (removed);
1072 hosts->hosts[i] = NULL;
1073 duplicates++;
1074 g_free (name);
1075 }
1076 else
1077 g_hash_table_insert (name_table, name, hosts->hosts[i]);
1078 }
1079 }
1080
1081 if (duplicates)
1082 gvm_hosts_fill_gaps (hosts);
1083 g_hash_table_destroy (name_table);
1084 hosts->count -= duplicates;
1085 hosts->duplicated += duplicates;
1086 hosts->current = 0;
1087#ifdef __GLIBC__
1088 malloc_trim (0);
1089#endif
1090}
1091
1104gvm_hosts_new_with_max (const gchar *hosts_str, unsigned int max_hosts)
1105{
1106 gvm_hosts_t *hosts;
1107 gchar **host_element, **split;
1108 gchar *str;
1109
1110 if (hosts_str == NULL)
1111 return NULL;
1112
1113 /* Normalize separator: Transform newlines into commas. */
1114 hosts = gvm_hosts_init (hosts_str);
1115 str = hosts->orig_str;
1116 while (*str)
1117 {
1118 if (*str == '\n')
1119 *str = ',';
1120 str++;
1121 }
1122
1123 /* Split comma-separated list into single host-specifications */
1124 split = g_strsplit (hosts->orig_str, ",", 0);
1125
1126 /* first element of the split list */
1127 host_element = split;
1128 while (*host_element)
1129 {
1130 int host_type;
1131 gchar *stripped = g_strstrip (*host_element);
1132
1133 if (stripped == NULL || *stripped == '\0')
1134 {
1135 host_element++;
1136 continue;
1137 }
1138
1139 /* IPv4, hostname, IPv6, collection (short/long range, cidr block) etc,. ?
1140 */
1141 /* -1 if error. */
1142 host_type = gvm_get_host_type (stripped);
1143
1144 switch (host_type)
1145 {
1146 case HOST_TYPE_NAME:
1147 case HOST_TYPE_IPV4:
1148 case HOST_TYPE_IPV6:
1149 {
1150 /* New host. */
1151 gvm_host_t *host = gvm_host_new ();
1152 host->type = host_type;
1154 host->name = g_ascii_strdown (stripped, -1);
1155 else if (host_type == HOST_TYPE_IPV4)
1156 {
1157 if (inet_pton (AF_INET, stripped, &host->addr) != 1)
1158 break;
1159 }
1160 else if (host_type == HOST_TYPE_IPV6)
1161 {
1162 if (inet_pton (AF_INET6, stripped, &host->addr6) != 1)
1163 break;
1164 }
1165 gvm_hosts_add (hosts, host);
1166 break;
1167 }
1171 {
1172 struct in_addr first, last;
1173 uint32_t current;
1174 int (*ips_func) (const char *, struct in_addr *, struct in_addr *);
1175
1177 ips_func = cidr_block_ips;
1178 else if (host_type == HOST_TYPE_RANGE_SHORT)
1179 ips_func = short_range_network_ips;
1180 else
1181 ips_func = long_range_network_ips;
1182
1183 if (ips_func (stripped, &first, &last) == -1)
1184 break;
1185
1186 /* Make sure that first actually comes before last */
1187 if (ntohl (first.s_addr) > ntohl (last.s_addr))
1188 break;
1189
1190 /* Add addresses from first to last as single hosts. */
1191 current = first.s_addr;
1192 while (1)
1193 {
1194 gvm_host_t *host;
1195 if (max_hosts > 0 && hosts->count > max_hosts)
1196 {
1197 g_strfreev (split);
1198 gvm_hosts_free (hosts);
1199 return NULL;
1200 }
1201 host = gvm_host_new ();
1202 host->type = HOST_TYPE_IPV4;
1203 host->addr.s_addr = current;
1204 gvm_hosts_add (hosts, host);
1205 /* Exit loop if range end has been reached.
1206 * Check is done before increment to avoid possible overflow.
1207 */
1208 if (ntohl (current) >= ntohl (last.s_addr))
1209 break;
1210 /* Next IP address. */
1211 current = htonl (ntohl (current) + 1);
1212 }
1213 break;
1214 }
1218 {
1219 struct in6_addr first, last;
1220 unsigned char current[16];
1221 int (*ips_func) (const char *, struct in6_addr *,
1222 struct in6_addr *);
1223
1225 ips_func = gvm_cidr6_block_ips;
1227 ips_func = short_range6_network_ips;
1228 else
1229 ips_func = long_range6_network_ips;
1230
1231 if (ips_func (stripped, &first, &last) == -1)
1232 break;
1233
1234 /* Make sure the first comes before the last. */
1235 if (memcmp (&first.s6_addr, &last.s6_addr, 16) > 0)
1236 break;
1237
1238 /* Add addresses from first to last as single hosts. */
1239 memcpy (current, &first.s6_addr, 16);
1240 while (1)
1241 {
1242 int i;
1243 gvm_host_t *host;
1244
1245 if (max_hosts > 0 && hosts->count > max_hosts)
1246 {
1247 g_strfreev (split);
1248 gvm_hosts_free (hosts);
1249 return NULL;
1250 }
1251 host = gvm_host_new ();
1252 host->type = HOST_TYPE_IPV6;
1253 memcpy (host->addr6.s6_addr, current, 16);
1254 gvm_hosts_add (hosts, host);
1255
1256 /* Exit loop if range end has been reached.
1257 * Check is done before increment to avoid possible overflow.
1258 */
1259 if (memcmp (current, &last.s6_addr, 16) >= 0)
1260 break;
1261
1262 /* Next IPv6 address. */
1263 for (i = 15; i >= 0; --i)
1264 if (current[i] < 255)
1265 {
1266 current[i]++;
1267 break;
1268 }
1269 else
1270 current[i] = 0;
1271 }
1272 break;
1273 }
1274 case -1:
1275 default:
1276 /* Invalid host string. */
1277 g_strfreev (split);
1278 gvm_hosts_free (hosts);
1279 return NULL;
1280 }
1281 host_element++; /* move on to next element of split list */
1282 if (max_hosts > 0 && hosts->count > max_hosts)
1283 {
1284 g_strfreev (split);
1285 gvm_hosts_free (hosts);
1286 return NULL;
1287 }
1288 }
1289
1290 /* No need to check for duplicates when a hosts string contains a
1291 * single (IP/Hostname/Range/Subnetwork) entry. */
1292 if (g_strv_length (split) > 1)
1293 gvm_hosts_deduplicate (hosts);
1294
1295 g_strfreev (split);
1296#ifdef __GLIBC__
1297 malloc_trim (0);
1298#endif
1299 return hosts;
1300}
1301
1313gvm_hosts_new (const gchar *hosts_str)
1314{
1315 return gvm_hosts_new_with_max (hosts_str, 0);
1316}
1317
1326gvm_host_t *
1328{
1329 if (!hosts || hosts->current == hosts->count)
1330 return NULL;
1331
1332 return hosts->hosts[hosts->current++];
1333}
1334
1344void
1346{
1347 void *host_tmp;
1348 size_t i;
1349
1350 if (!hosts)
1351 return;
1352
1353 // Keep in mind that gvm_hosts_next will return the current host and then
1354 // increment hosts->current.
1355
1356 if (hosts->current == hosts->count)
1357 {
1358 // We're on the last host, just make the previous host current.
1359 // TODO what happens when current is 0?
1360 hosts->current -= 1;
1361 return;
1362 }
1363
1364 // Make the previous host current. This makes sure that gvm_hosts_next will
1365 // return the host that has replaced the current host.
1366 // TODO what happens when current is 0?
1367 hosts->current -= 1;
1368 // Get the host to be moved.
1369 host_tmp = hosts->hosts[hosts->current];
1370
1371 // Shift all the others down. Start from current + 1 because we're assigning
1372 // into the previous slot (i - 1). It's safe to do this because we already
1373 // checked if current == count above.
1374 for (i = hosts->current + 1; i < hosts->count; i++)
1375 hosts->hosts[i - 1] = hosts->hosts[i];
1376
1377 // Put the moved host on the end.
1378 hosts->hosts[hosts->count - 1] = host_tmp;
1379}
1380
1387void
1389{
1390 size_t i;
1391
1392 if (hosts == NULL)
1393 return;
1394
1395 g_free (hosts->orig_str);
1396 for (i = 0; i < hosts->count; i++)
1397 gvm_host_free (hosts->hosts[i]);
1398 g_free (hosts->hosts);
1399 g_free (hosts);
1400 hosts = NULL;
1401}
1402
1410void
1412{
1413 size_t i = 0;
1414 GRand *rand;
1415
1416 if (hosts == NULL)
1417 return;
1418
1419 /* Shuffle the array. */
1420 rand = g_rand_new ();
1421 for (i = 0; i < hosts->count; i++)
1422 {
1423 void *tmp;
1424 int j = g_rand_int_range (rand, 0, hosts->count);
1425
1426 tmp = hosts->hosts[i];
1427 hosts->hosts[i] = hosts->hosts[j];
1428 hosts->hosts[j] = tmp;
1429 }
1430
1431 hosts->current = 0;
1432 g_rand_free (rand);
1433}
1434
1442void
1444{
1445 size_t i, j;
1446 if (hosts == NULL || hosts->count < 2)
1447 return;
1448
1449 for (i = 0, j = hosts->count - 1; i < j; i++, j--)
1450 {
1451 gvm_host_t *tmp = hosts->hosts[i];
1452 hosts->hosts[i] = hosts->hosts[j];
1453 hosts->hosts[j] = tmp;
1454 }
1455 hosts->current = 0;
1456}
1457
1468GSList *
1470{
1471 size_t i, new_entries = 0, resolved = 0;
1472 GSList *unresolved = NULL;
1473
1474 for (i = 0; i < hosts->count; i++)
1475 {
1476 GSList *list, *tmp;
1477 gvm_host_t *host = hosts->hosts[i];
1478
1479 if (host->type != HOST_TYPE_NAME)
1480 continue;
1481
1482 list = tmp = gvm_resolve_list (host->name);
1483 while (tmp)
1484 {
1485 /* Create a new host for each IP address. */
1486 gvm_host_t *new;
1487 struct in6_addr *ip6 = tmp->data;
1488 gvm_vhost_t *vhost;
1489
1490 new = gvm_host_new ();
1491 if (ip6->s6_addr32[0] != 0 || ip6->s6_addr32[1] != 0
1492 || ip6->s6_addr32[2] != htonl (0xffff))
1493 {
1494 new->type = HOST_TYPE_IPV6;
1495 memcpy (&new->addr6, ip6, sizeof (new->addr6));
1496 }
1497 else
1498 {
1499 new->type = HOST_TYPE_IPV4;
1500 memcpy (&new->addr6, &ip6->s6_addr32[3], sizeof (new->addr));
1501 }
1502 vhost =
1503 gvm_vhost_new (g_strdup (host->name), g_strdup ("Forward-DNS"));
1504 new->vhosts = g_slist_prepend (new->vhosts, vhost);
1505 gvm_hosts_add (hosts, new);
1506 tmp = tmp->next;
1507 new_entries = 1;
1508 }
1509 /* Remove hostname from list, as it was either replaced by IPs, or
1510 * is unresolvable. */
1511 hosts->hosts[i] = NULL;
1512 resolved++;
1513 if (!list)
1514 unresolved = g_slist_prepend (unresolved, g_strdup (host->name));
1515 gvm_host_free (host);
1516 g_slist_free_full (list, g_free);
1517 }
1518 if (resolved)
1519 gvm_hosts_fill_gaps (hosts);
1520 hosts->count -= resolved;
1521 hosts->removed += resolved;
1522 if (new_entries)
1523 gvm_hosts_deduplicate (hosts);
1524 hosts->current = 0;
1525 return unresolved;
1526}
1527
1536int
1537gvm_vhosts_exclude (gvm_host_t *host, const char *excluded_str)
1538{
1539 GSList *vhost;
1540 char **excluded;
1541 int ret = 0;
1542
1543 if (!host || !excluded_str)
1544 return ret;
1545
1546 vhost = host->vhosts;
1547 excluded = g_strsplit (excluded_str, ",", 0);
1548 if (!excluded || !*excluded)
1549 {
1550 g_strfreev (excluded);
1551 return ret;
1552 }
1553 while (vhost)
1554 {
1555 char **tmp = excluded;
1556 char *value = ((gvm_vhost_t *) vhost->data)->value;
1557
1558 while (*tmp)
1559 {
1560 if (!strcasecmp (value, g_strstrip (*tmp)))
1561 {
1562 gvm_vhost_free (vhost->data);
1563 host->vhosts = vhost = g_slist_delete_link (host->vhosts, vhost);
1564 ret++;
1565 break;
1566 }
1567 tmp++;
1568 if (!*tmp)
1569 {
1570 vhost = vhost->next;
1571 break;
1572 }
1573 }
1574 }
1575 g_strfreev (excluded);
1576
1577 return ret;
1578}
1579
1591int
1592gvm_hosts_exclude_with_max (gvm_hosts_t *hosts, const char *excluded_str,
1593 unsigned int max_hosts)
1594{
1598 gvm_hosts_t *excluded_hosts;
1599 GHashTable *name_table;
1600 size_t excluded = 0, i;
1601
1602 if (hosts == NULL || excluded_str == NULL)
1603 return -1;
1604
1605 excluded_hosts = gvm_hosts_new_with_max (excluded_str, max_hosts);
1606 if (excluded_hosts == NULL)
1607 return -1;
1608
1609 if (gvm_hosts_count (excluded_hosts) == 0)
1610 {
1611 gvm_hosts_free (excluded_hosts);
1612 return 0;
1613 }
1614
1615 /* Hash host values from excluded hosts list. */
1616 name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1617 for (i = 0; i < excluded_hosts->count; i++)
1618 {
1619 gchar *name;
1620
1621 name = gvm_host_value_str (excluded_hosts->hosts[i]);
1622 if (name)
1623 g_hash_table_insert (name_table, name, hosts);
1624 }
1625
1626 /* Check for hosts values in hash table. */
1627 for (i = 0; i < hosts->count; i++)
1628 {
1629 gchar *name;
1630
1631 name = gvm_host_value_str (hosts->hosts[i]);
1632 if (name)
1633 {
1634 if (g_hash_table_lookup (name_table, name))
1635 {
1636 gvm_host_free (hosts->hosts[i]);
1637 hosts->hosts[i] = NULL;
1638 excluded++;
1639 g_free (name);
1640 continue;
1641 }
1642 g_free (name);
1643 }
1644 }
1645
1646 /* Cleanup. */
1647 if (excluded)
1648 gvm_hosts_fill_gaps (hosts);
1649 hosts->count -= excluded;
1650 hosts->removed += excluded;
1651 hosts->current = 0;
1652 g_hash_table_destroy (name_table);
1653 gvm_hosts_free (excluded_hosts);
1654 return excluded;
1655}
1656
1669GSList *
1670gvm_hosts_allowed_only (gvm_hosts_t *hosts, const char *deny_hosts_str,
1671 const char *allow_hosts_str)
1672{
1676 gvm_hosts_t *allowed_hosts, *denied_hosts;
1677 GHashTable *name_allow_table = NULL, *name_deny_table = NULL;
1678 GSList *removed = NULL;
1679 size_t excluded = 0, i;
1680
1681 if (hosts == NULL || (deny_hosts_str == NULL && allow_hosts_str == NULL))
1682 return NULL;
1683
1684 // Prepare list of denied and allowed hosts
1685 denied_hosts = gvm_hosts_new_with_max (deny_hosts_str, 0);
1686 allowed_hosts = gvm_hosts_new_with_max (allow_hosts_str, 0);
1687 if (denied_hosts == NULL && allowed_hosts == NULL)
1688 return NULL;
1689
1690 if (gvm_hosts_count (denied_hosts) == 0)
1691 gvm_hosts_free (denied_hosts);
1692 else
1693 {
1694 /* Hash host values from denied hosts list. */
1695 name_deny_table =
1696 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1697 for (i = 0; i < denied_hosts->count; i++)
1698 {
1699 gchar *name;
1700
1701 name = gvm_host_value_str (denied_hosts->hosts[i]);
1702 if (name)
1703 g_hash_table_insert (name_deny_table, name, hosts);
1704 }
1705 }
1706 if (gvm_hosts_count (allowed_hosts) == 0)
1707 gvm_hosts_free (allowed_hosts);
1708 else
1709 {
1710 /* Hash host values from allowed hosts list. */
1711 name_allow_table =
1712 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1713 for (i = 0; i < allowed_hosts->count; i++)
1714 {
1715 gchar *name;
1716
1717 name = gvm_host_value_str (allowed_hosts->hosts[i]);
1718 if (name)
1719 g_hash_table_insert (name_allow_table, name, hosts);
1720 }
1721 }
1722
1723 /* Check for authorized hosts in hash table and create a list of removed
1724 * hosts. */
1725 for (i = 0; i < hosts->count; i++)
1726 {
1727 gchar *name;
1728
1729 name = gvm_host_value_str (hosts->hosts[i]);
1730 if (name)
1731 {
1732 if (denied_hosts != NULL
1733 && g_hash_table_lookup (name_deny_table, name))
1734 {
1735 gvm_host_free (hosts->hosts[i]);
1736 hosts->hosts[i] = NULL;
1737 excluded++;
1738 removed = g_slist_prepend (removed, name);
1739 continue;
1740 }
1741 else if (allowed_hosts != NULL
1742 && !g_hash_table_lookup (name_allow_table, name))
1743 {
1744 gvm_host_free (hosts->hosts[i]);
1745 hosts->hosts[i] = NULL;
1746 excluded++;
1747 removed = g_slist_prepend (removed, name);
1748 continue;
1749 }
1750 g_free (name);
1751 }
1752 }
1753
1754 /* Cleanup. */
1755 if (excluded)
1756 gvm_hosts_fill_gaps (hosts);
1757
1758 hosts->count -= excluded;
1759 hosts->removed += excluded;
1760 hosts->current = 0;
1761 if (name_allow_table != NULL)
1762 g_hash_table_destroy (name_allow_table);
1763 if (name_deny_table != NULL)
1764 g_hash_table_destroy (name_deny_table);
1765 if (allowed_hosts != NULL)
1766 gvm_hosts_free (allowed_hosts);
1767 if (denied_hosts != NULL)
1768 gvm_hosts_free (denied_hosts);
1769 return removed;
1770}
1771
1782int
1783gvm_hosts_exclude (gvm_hosts_t *hosts, const char *excluded_str)
1784{
1785 return gvm_hosts_exclude_with_max (hosts, excluded_str, 0);
1786}
1787
1798gvm_host_t *
1799gvm_host_from_str (const gchar *host_str)
1800{
1801 int host_type;
1802
1803 if (host_str == NULL)
1804 return NULL;
1805
1806 /* IPv4, hostname, IPv6 */
1807 /* -1 if error. */
1808 host_type = gvm_get_host_type (host_str);
1809
1810 switch (host_type)
1811 {
1812 case HOST_TYPE_NAME:
1813 case HOST_TYPE_IPV4:
1814 case HOST_TYPE_IPV6:
1815 {
1816 /* New host. */
1817 gvm_host_t *host = gvm_host_new ();
1818 host->type = host_type;
1820 host->name = g_ascii_strdown (host_str, -1);
1821 else if (host_type == HOST_TYPE_IPV4)
1822 {
1823 if (inet_pton (AF_INET, host_str, &host->addr) != 1)
1824 break;
1825 }
1826 else if (host_type == HOST_TYPE_IPV6)
1827 {
1828 if (inet_pton (AF_INET6, host_str, &host->addr6) != 1)
1829 break;
1830 }
1831 return host;
1832 }
1833 case -1:
1834 default:
1835 return NULL;
1836 }
1837 return NULL;
1838}
1839
1847char *
1849{
1850 int retry = 10;
1851 gchar hostname[NI_MAXHOST];
1852 void *addr;
1853 size_t addrlen;
1854 struct sockaddr_in sa;
1855 struct sockaddr_in6 sa6;
1856
1857 if (!host)
1858 return NULL;
1859
1860 if (host->type == HOST_TYPE_IPV4)
1861 {
1862 addr = &sa;
1863 addrlen = sizeof (sa);
1864 memset (addr, '\0', addrlen);
1865 sa.sin_addr = host->addr;
1866 sa.sin_family = AF_INET;
1867 }
1868 else if (host->type == HOST_TYPE_IPV6)
1869 {
1870 addr = &sa6;
1871 addrlen = sizeof (sa6);
1872 memset (&sa6, '\0', addrlen);
1873 memcpy (&sa6.sin6_addr, &host->addr6, 16);
1874 sa6.sin6_family = AF_INET6;
1875 }
1876 else
1877 return NULL;
1878
1879 while (retry--)
1880 {
1881 int ret = getnameinfo (addr, addrlen, hostname, sizeof (hostname), NULL,
1882 0, NI_NAMEREQD);
1883 if (!ret)
1884 return g_ascii_strdown (hostname, -1);
1885 if (ret != EAI_AGAIN)
1886 break;
1887 usleep (10000); // 10ms
1888 }
1889 return NULL;
1890}
1891
1900static int
1901host_name_verify (gvm_host_t *host, const char *value)
1902{
1903 GSList *list, *tmp;
1904 char *host_str;
1905 int ret = -1;
1906
1907 assert (host);
1908 assert (value);
1909 host_str = gvm_host_value_str (host);
1910 list = tmp = gvm_resolve_list (value);
1911 while (tmp)
1912 {
1913 char buffer[INET6_ADDRSTRLEN];
1914 addr6_to_str (tmp->data, buffer);
1915 if (!strcasecmp (host_str, buffer))
1916 {
1917 ret = 0;
1918 break;
1919 }
1920 tmp = tmp->next;
1921 }
1922 g_free (host_str);
1923 g_slist_free_full (list, g_free);
1924 return ret;
1925}
1926
1932void
1934{
1935 GSList *vhosts;
1936 gvm_vhost_t *vhost;
1937 char *value;
1938
1939 if (!host || host->type == HOST_TYPE_NAME)
1940 return;
1941
1942 value = gvm_host_reverse_lookup (host);
1943 if (!value)
1944 return;
1945 if (host_name_verify (host, value))
1946 {
1947 g_free (value);
1948 return;
1949 }
1950 /* Don't add vhost, if already in the list. */
1951 vhosts = host->vhosts;
1952 while (vhosts)
1953 {
1954 if (!strcasecmp (((gvm_vhost_t *) vhosts->data)->value, value))
1955 {
1956 g_free (value);
1957 return;
1958 }
1959 vhosts = vhosts->next;
1960 }
1961 vhost = gvm_vhost_new (value, g_strdup ("Reverse-DNS"));
1962 host->vhosts = g_slist_prepend (host->vhosts, vhost);
1963}
1964
1976{
1977 size_t i, count = 0;
1978 gvm_hosts_t *excluded = gvm_hosts_new ("");
1979
1980 if (hosts == NULL)
1981 return NULL;
1982
1983 for (i = 0; i < hosts->count; i++)
1984 {
1985 gchar *name = gvm_host_reverse_lookup (hosts->hosts[i]);
1986
1987 if (name == NULL)
1988 {
1989 gvm_hosts_add (excluded, gvm_duplicate_host (hosts->hosts[i]));
1990 gvm_host_free (hosts->hosts[i]);
1991 hosts->hosts[i] = NULL;
1992 count++;
1993 }
1994 else
1995 g_free (name);
1996 }
1997
1998 if (count)
1999 gvm_hosts_fill_gaps (hosts);
2000 hosts->count -= count;
2001 hosts->removed += count;
2002 hosts->current = 0;
2003 return excluded;
2004}
2005
2015int
2017{
2018 gvm_hosts_t *excluded;
2019 int count = 0;
2020
2021 if (hosts == NULL)
2022 return -1;
2023
2024 excluded = gvm_hosts_reverse_lookup_only_excluded (hosts);
2025 count = excluded->count;
2026 gvm_hosts_free (excluded);
2027
2028 return count;
2029}
2030
2042{
2046 size_t i, count = 0;
2047 GHashTable *name_table;
2048 gvm_hosts_t *excluded = NULL;
2049
2050 if (hosts == NULL)
2051 return NULL;
2052
2053 excluded = gvm_hosts_new ("");
2054 name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
2055 for (i = 0; i < hosts->count; i++)
2056 {
2057 gchar *name;
2058
2059 name = gvm_host_reverse_lookup (hosts->hosts[i]);
2060 if (name)
2061 {
2062 if (g_hash_table_lookup (name_table, name))
2063 {
2064 gvm_hosts_add (excluded, gvm_duplicate_host (hosts->hosts[i]));
2065 gvm_host_free (hosts->hosts[i]);
2066 hosts->hosts[i] = NULL;
2067 count++;
2068 g_free (name);
2069 }
2070 else
2071 {
2072 /* Insert in the hash table. Value not important. */
2073 g_hash_table_insert (name_table, name, hosts);
2074 }
2075 }
2076 }
2077
2078 if (count)
2079 gvm_hosts_fill_gaps (hosts);
2080 g_hash_table_destroy (name_table);
2081 hosts->removed += count;
2082 hosts->count -= count;
2083 hosts->current = 0;
2084 return excluded;
2085}
2086
2096int
2098{
2099 gvm_hosts_t *excluded = NULL;
2100 int count = 0;
2101 if (hosts == NULL)
2102 return -1;
2103
2104 excluded = gvm_hosts_reverse_lookup_unify_excluded (hosts);
2105 count = excluded->count;
2106 gvm_hosts_free (excluded);
2107
2108 return count;
2109}
2110
2117unsigned int
2119{
2120 return hosts ? hosts->count : 0;
2121}
2122
2131unsigned int
2133{
2134 return hosts ? hosts->removed : 0;
2135}
2136
2145unsigned int
2147{
2148 return hosts ? hosts->duplicated : 0;
2149}
2150
2161gvm_host_t *
2162gvm_host_find_in_hosts (const gvm_host_t *host, const struct in6_addr *addr,
2163 const gvm_hosts_t *hosts)
2164{
2165 char *host_str;
2166 size_t i;
2167
2168 if (host == NULL || hosts == NULL)
2169 return NULL;
2170
2171 host_str = gvm_host_value_str (host);
2172
2173 for (i = 0; i < hosts->count; i++)
2174 {
2175 gvm_host_t *current_host = hosts->hosts[i];
2176 char *tmp = gvm_host_value_str (current_host);
2177
2178 if (strcasecmp (host_str, tmp) == 0)
2179 {
2180 g_free (host_str);
2181 g_free (tmp);
2182 return current_host;
2183 }
2184 g_free (tmp);
2185
2186 /* Hostnames in hosts list shouldn't be resolved. */
2187 if (addr && gvm_host_type (current_host) != HOST_TYPE_NAME)
2188 {
2189 struct in6_addr tmpaddr;
2190 gvm_host_get_addr6 (current_host, &tmpaddr);
2191
2192 if (memcmp (addr->s6_addr, &tmpaddr.s6_addr, 16) == 0)
2193 {
2194 g_free (host_str);
2195 return current_host;
2196 }
2197 }
2198 }
2199
2200 g_free (host_str);
2201 return NULL;
2202}
2203
2210gvm_host_t *
2212{
2213 gvm_host_t *ret = NULL;
2214
2215 if (host == NULL)
2216 return NULL;
2217
2218 ret = gvm_host_new ();
2219
2220 ret->type = host->type;
2221 switch (host->type)
2222 {
2223 case HOST_TYPE_NAME:
2224 ret->name = g_strdup (host->name);
2225 break;
2226 case HOST_TYPE_IPV4:
2227 ret->addr = host->addr;
2228 break;
2229 case HOST_TYPE_IPV6:
2230 ret->addr6 = host->addr6;
2231 break;
2232 default:
2233 g_free (ret);
2234 return NULL;
2235 }
2236 ret->vhosts = g_slist_copy_deep (host->vhosts, gvm_duplicate_vhost, NULL);
2237
2238 return ret;
2239}
2240
2253int
2254gvm_host_in_hosts (const gvm_host_t *host, const struct in6_addr *addr,
2255 const gvm_hosts_t *hosts)
2256{
2257 if (gvm_host_find_in_hosts (host, addr, hosts))
2258 return 1;
2259
2260 return 0;
2261}
2262
2270enum host_type
2272{
2273 assert (host);
2274 return host->type;
2275}
2276
2285gchar *
2287{
2288 if (host == NULL)
2289 return NULL;
2290
2291 return host_type_str[host->type];
2292}
2293
2301gchar *
2303{
2304 if (host == NULL)
2305 return NULL;
2306
2307 switch (host->type)
2308 {
2309 case HOST_TYPE_NAME:
2310 return g_strdup (host->name);
2311 break;
2312 case HOST_TYPE_IPV4:
2313 case HOST_TYPE_IPV6:
2314 /* Handle both cases using inet_ntop(). */
2315 {
2316 int family, size;
2317 gchar *str;
2318 const void *srcaddr;
2319
2320 if (host->type == HOST_TYPE_IPV4)
2321 {
2322 family = AF_INET;
2323 size = INET_ADDRSTRLEN;
2324 srcaddr = &host->addr;
2325 }
2326 else
2327 {
2328 family = AF_INET6;
2329 size = INET6_ADDRSTRLEN;
2330 srcaddr = &host->addr6;
2331 }
2332
2333 str = g_malloc0 (size);
2334 if (inet_ntop (family, srcaddr, str, size) == NULL)
2335 {
2336 perror ("inet_ntop");
2337 g_free (str);
2338 return NULL;
2339 }
2340 return str;
2341 }
2342 default:
2343 return g_strdup ("Erroneous host type: Should be Hostname/IPv4/IPv6.");
2344 }
2345}
2346
2358int
2359gvm_host_resolve (const gvm_host_t *host, void *dst, int family)
2360{
2361 if (host == NULL || dst == NULL || host->type != HOST_TYPE_NAME)
2362 return -1;
2363
2364 return gvm_resolve (host->name, dst, family);
2365}
2366
2379int
2380gvm_host_get_addr6 (const gvm_host_t *host, struct in6_addr *ip6)
2381{
2382 if (host == NULL || ip6 == NULL)
2383 return -1;
2384
2385 switch (gvm_host_type (host))
2386 {
2387 case HOST_TYPE_IPV6:
2388 memcpy (ip6, &host->addr6, sizeof (struct in6_addr));
2389 return 0;
2390
2391 case HOST_TYPE_IPV4:
2392 ipv4_as_ipv6 (&host->addr, ip6);
2393 return 0;
2394
2395 case HOST_TYPE_NAME:
2396 {
2397 struct in_addr ip4;
2398
2399 /* Fail if IPv4 and IPv6 both don't resolve. */
2400 if (gvm_host_resolve (host, &ip4, AF_INET) == 0)
2401 ipv4_as_ipv6 (&ip4, ip6);
2402 else if (gvm_host_resolve (host, ip6, AF_INET6) == -1)
2403 return -1;
2404 return 0;
2405 }
2406
2407 default:
2408 return -1;
2409 }
2410}
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
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:2254
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_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:2041
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
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:2016
gchar * gvm_host_value_str(const gvm_host_t *host)
Gets a host's value in printable format.
Definition hosts.c:2302
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
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:2359
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:1975
gchar * host_type_str[HOST_TYPE_MAX]
Definition hosts.c:40
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
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
char * gvm_host_reverse_lookup(gvm_host_t *host)
Checks for a host object reverse dns lookup existence.
Definition hosts.c:1848
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_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:2211
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_t * gvm_vhost_new(char *value, char *source)
Creates a new gvm_vhost_t object.
Definition hosts.c:875
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:1313
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:1327
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:1670
void gvm_host_free(gpointer host)
Frees the memory occupied by an gvm_host_t object.
Definition hosts.c:945
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:2132
gchar * gvm_host_type_str(const gvm_host_t *host)
Gets a host's type in printable format.
Definition hosts.c:2286
void gvm_host_add_reverse_lookup(gvm_host_t *host)
Add a host's reverse-lookup name to the vhosts list.
Definition hosts.c:1933
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
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
static int is_hostname(const char *str)
Checks if a buffer points to a valid hostname.
Definition hosts.c:396
static gvm_host_t * gvm_host_new()
Creates a new gvm_host_t object.
Definition hosts.c:930
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:1443
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:1411
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:2146
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_t * gvm_host_from_str(const gchar *host_str)
Creates a new gvm_host_t from a host string.
Definition hosts.c:1799
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
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
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
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
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
static gvm_hosts_t * gvm_hosts_init(const char *hosts_str)
Creates a hosts collection from a hosts string.
Definition hosts.c:988
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
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:2380
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
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:1345
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:1537
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:1592
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:1469
enum host_type gvm_host_type(const gvm_host_t *host)
Gets a host object's type.
Definition hosts.c:2271
gpointer gvm_duplicate_vhost(gconstpointer vhost, gpointer data)
Creates a deep copy of a gvm_vhost_t object.
Definition hosts.c:910
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
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:1901
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:2162
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition hosts.c:814
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
unsigned int gvm_hosts_count(const gvm_hosts_t *hosts)
Gets the count of single hosts objects in a hosts collection.
Definition hosts.c:2118
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
static void gvm_vhost_free(gpointer vhost)
Frees the memory occupied by an gvm_vhost_t object.
Definition hosts.c:892
void gvm_hosts_free(gvm_hosts_t *hosts)
Frees memory occupied by an gvm_hosts_t structure.
Definition hosts.c:1388
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:1783
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
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:2097
Protos and data structures for Hosts collections and single hosts objects.
host_type
Definition hosts.h:34
@ HOST_TYPE_RANGE_SHORT
Definition hosts.h:38
@ HOST_TYPE_RANGE6_SHORT
Definition hosts.h:43
@ HOST_TYPE_RANGE_LONG
Definition hosts.h:39
@ HOST_TYPE_RANGE6_LONG
Definition hosts.h:42
@ HOST_TYPE_NAME
Definition hosts.h:35
@ HOST_TYPE_IPV6
Definition hosts.h:40
@ HOST_TYPE_CIDR6_BLOCK
Definition hosts.h:41
@ HOST_TYPE_MAX
Definition hosts.h:44
@ HOST_TYPE_IPV4
Definition hosts.h:36
@ HOST_TYPE_CIDR_BLOCK
Definition hosts.h:37
struct gvm_host gvm_host_t
Definition hosts.h:48
struct gvm_vhost gvm_vhost_t
Definition hosts.h:49
struct gvm_hosts gvm_hosts_t
Definition hosts.h:50
void addr6_to_str(const struct in6_addr *addr6, char *str)
Stringifies an IP address.
Definition networking.c:261
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
int gvm_resolve(const char *name, void *dst, int family)
Resolves a hostname to an IPv4 or IPv6 address.
Definition networking.c:389
GSList * gvm_resolve_list(const char *name)
Returns a list of addresses that a hostname resolves to.
Definition networking.c:339
GVM Networking related API.
struct in6_addr addr6
Definition hosts.h:66
gchar * name
Definition hosts.h:64
GSList * vhosts
Definition hosts.h:69
struct in_addr addr
Definition hosts.h:65
enum host_type type
Definition hosts.h:68
size_t max_size
Definition hosts.h:91
size_t removed
Definition hosts.h:94
gchar * orig_str
Definition hosts.h:89
size_t duplicated
Definition hosts.h:95
size_t current
Definition hosts.h:92
size_t count
Definition hosts.h:93
gvm_host_t ** hosts
Definition hosts.h:90
char * value
Definition hosts.h:77
char * source
Definition hosts.h:78