Greenbone Vulnerability Management Libraries 22.18.1
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 return 0;
437 }
438 }
439
440 /* Check each part. */
441
442 point = split;
443 while (*point)
444 if (g_regex_match_simple ("^(?!-)[a-z0-9_-]{1,63}(?<!-)$", *point,
445 G_REGEX_CASELESS, 0)
446 == 0)
447 {
448 g_strfreev (split);
449 return 0;
450 }
451 else
452 point++;
453
454 g_strfreev (split);
455 return 1;
456}
457
466static int
467is_cidr6_block (const char *str)
468{
469 long block;
470 char *addr6_str, *block_str, *p;
471
472 addr6_str = g_strdup (str);
473 block_str = strchr (addr6_str, '/');
474 if (block_str == NULL)
475 {
476 g_free (addr6_str);
477 return 0;
478 }
479
480 /* Separate the address from the block value. */
481 *block_str = '\0';
482 block_str++;
483
484 if (!is_ipv6_address (addr6_str) || !isdigit (*block_str))
485 {
486 g_free (addr6_str);
487 return 0;
488 }
489
490 p = NULL;
491 block = strtol (block_str, &p, 10);
492
493 if (*p || block <= 0 || block > 128)
494 {
495 g_free (addr6_str);
496 return 0;
497 }
498
499 g_free (addr6_str);
500 return 1;
501}
502
512static int
513cidr6_get_block (const char *str, unsigned int *block)
514{
515 if (str == NULL || block == NULL)
516 return -1;
517
518 if (sscanf (str, "%*[0-9a-fA-F.:]/%3u", block) != 1)
519 return -1;
520
521 return 0;
522}
523
533static int
534cidr6_get_ip (const char *str, struct in6_addr *addr6)
535{
536 gchar *addr6_str, *tmp;
537
538 if (str == NULL || addr6 == NULL)
539 return -1;
540
541 addr6_str = g_strdup (str);
542 tmp = strchr (addr6_str, '/');
543 if (tmp == NULL)
544 {
545 g_free (addr6_str);
546 return -1;
547 }
548 *tmp = '\0';
549
550 if (inet_pton (AF_INET6, addr6_str, addr6) != 1)
551 return -1;
552
553 g_free (addr6_str);
554 return 0;
555}
556
568static int
569cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last)
570{
571 unsigned int block;
572 int i, j;
573
574 if (str == NULL || first == NULL || last == NULL)
575 return -1;
576
577 /* Get IP and block values. */
578 if (cidr6_get_block (str, &block) == -1)
579 return -1;
580 if (cidr6_get_ip (str, first) == -1)
581 return -1;
582 memcpy (&last->s6_addr, &first->s6_addr, 16);
583
584 /* /128 => Specified address is the first and last one. */
585 if (block == 128)
586 return 0;
587
588 /* First IP: And with mask and increment to skip network address. */
589 j = 15;
590 for (i = (128 - block) / 8; i > 0; i--)
591 {
592 first->s6_addr[j] = 0;
593 j--;
594 }
595 first->s6_addr[j] &= 0xff ^ ((1 << ((128 - block) % 8)) - 1);
596
597 /* Last IP: Broadcast address - 1. */
598 j = 15;
599 for (i = (128 - block) / 8; i > 0; i--)
600 {
601 last->s6_addr[j] = 0xff;
602 j--;
603 }
604 last->s6_addr[j] |= (1 << ((128 - block) % 8)) - 1;
605
606 /* /127 => Only two addresses. Don't skip network / broadcast addresses.*/
607 if (block == 127)
608 return 0;
609
610 /* Increment first IP. */
611 for (i = 15; i >= 0; --i)
612 if (first->s6_addr[i] < 255)
613 {
614 first->s6_addr[i]++;
615 break;
616 }
617 else
618 first->s6_addr[i] = 0;
619 /* Decrement last IP. */
620 for (i = 15; i >= 0; --i)
621 if (last->s6_addr[i] > 0)
622 {
623 last->s6_addr[i]--;
624 break;
625 }
626 else
627 last->s6_addr[i] = 0xff;
628
629 return 0;
630}
631
640static int
641is_long_range6_network (const char *str)
642{
643 char *first_str, *second_str;
644 int ret;
645
646 first_str = g_strdup (str);
647 second_str = strchr (first_str, '-');
648 if (second_str == NULL)
649 {
650 g_free (first_str);
651 return 0;
652 }
653
654 /* Separate the addresses. */
655 *second_str = '\0';
656 second_str++;
657
658 ret = is_ipv6_address (first_str) && is_ipv6_address (second_str);
659 g_free (first_str);
660
661 return ret;
662}
663
675static int
676long_range6_network_ips (const char *str, struct in6_addr *first,
677 struct in6_addr *last)
678{
679 char *first_str, *last_str;
680
681 if (str == NULL || first == NULL || last == NULL)
682 return -1;
683
684 first_str = g_strdup (str);
685 last_str = strchr (first_str, '-');
686 if (last_str == NULL)
687 {
688 g_free (first_str);
689 return -1;
690 }
691
692 /* Separate the two IPs. */
693 *last_str = '\0';
694 last_str++;
695
696 if (inet_pton (AF_INET6, first_str, first) != 1
697 || inet_pton (AF_INET6, last_str, last) != 1)
698 {
699 g_free (first_str);
700 return -1;
701 }
702
703 g_free (first_str);
704 return 0;
705}
706
715static int
716is_short_range6_network (const char *str)
717{
718 char *ip_str, *end_str, *p;
719
720 ip_str = g_strdup (str);
721 end_str = strchr (ip_str, '-');
722 if (end_str == NULL)
723 {
724 g_free (ip_str);
725 return 0;
726 }
727
728 /* Separate the addresses. */
729 *end_str = '\0';
730 end_str++;
731
732 if (!is_ipv6_address (ip_str) || *end_str == '\0')
733 {
734 g_free (ip_str);
735 return 0;
736 }
737
738 p = end_str;
739 /* Check that the 2nd part is at most 4 hexadecimal characters. */
740 while (isxdigit (*p) && p++)
741 ;
742 if (*p || p - end_str > 4)
743 {
744 g_free (ip_str);
745 return 0;
746 }
747
748 g_free (ip_str);
749 return 1;
750}
751
763static int
764short_range6_network_ips (const char *str, struct in6_addr *first,
765 struct in6_addr *last)
766{
767 char *first_str, *last_str;
768 long int end;
769
770 if (str == NULL || first == NULL || last == NULL)
771 return -1;
772
773 first_str = g_strdup (str);
774 last_str = strchr (first_str, '-');
775 if (last_str == NULL)
776 {
777 g_free (first_str);
778 return -1;
779 }
780
781 /* Separate the first IP. */
782 *last_str = '\0';
783 last_str++;
784
785 if (inet_pton (AF_INET6, first_str, first) != 1)
786 {
787 g_free (first_str);
788 return -1;
789 }
790
791 /* Calculate the last IP. */
792 memcpy (last, first, sizeof (*last));
793 end = strtol (last_str, NULL, 16);
794 memcpy (&last->s6_addr[15], &end, 1);
795 memcpy (&last->s6_addr[14], ((char *) &end) + 1, 1);
796
797 g_free (first_str);
798 return 0;
799}
800
809int
810gvm_get_host_type (const gchar *str_stripped)
811{
812 /*
813 * We have a single element with no leading or trailing
814 * white spaces. This element could represent different host
815 * definitions: single IPs, host names, CIDR-expressed blocks,
816 * range-expressed networks, IPv6 addresses.
817 */
818
819 /* Null or empty string. */
820 if (str_stripped == NULL || *str_stripped == '\0')
821 return -1;
822
823 /* Check for regular single IPv4 address. */
824 if (is_ipv4_address (str_stripped))
825 return HOST_TYPE_IPV4;
826
827 /* Check for regular single IPv6 address. */
828 if (is_ipv6_address (str_stripped))
829 return HOST_TYPE_IPV6;
830
831 /* Check for regular IPv4 CIDR-expressed block like "192.168.12.0/24" */
832 if (is_cidr_block (str_stripped))
834
835 /* Check for short range-expressed networks "192.168.12.5-40" */
836 if (is_short_range_network (str_stripped))
838
839 /* Check for long range-expressed networks "192.168.1.0-192.168.3.44" */
840 if (is_long_range_network (str_stripped))
842
843 /* Check for regular IPv6 CIDR-expressed block like "2620:0:2d0:200::7/120" */
844 if (is_cidr6_block (str_stripped))
846
847 /* Check for short range-expressed networks "::1-ef12" */
848 if (is_short_range6_network (str_stripped))
850
851 /* Check for long IPv6 range-expressed networks like "::1:20:7-::1:25:3" */
852 if (is_long_range6_network (str_stripped))
854
855 /* Check for hostname. */
856 if (is_hostname (str_stripped))
857 return HOST_TYPE_NAME;
858
859 return -1;
860}
861
871gvm_vhost_new (char *value, char *source)
872{
873 gvm_vhost_t *vhost;
874
875 vhost = g_malloc0 (sizeof (gvm_vhost_t));
876 vhost->value = value;
877 vhost->source = source;
878
879 return vhost;
880}
881
887static void
888gvm_vhost_free (gpointer vhost)
889{
890 if (vhost)
891 {
892 g_free (((gvm_vhost_t *) vhost)->value);
893 g_free (((gvm_vhost_t *) vhost)->source);
894 }
895 g_free (vhost);
896}
897
905gpointer
906gvm_duplicate_vhost (gconstpointer vhost, gpointer data)
907{
908 (void) (data);
909 gvm_vhost_t *ret = NULL;
910
911 if (!vhost)
912 return NULL;
913
914 ret = gvm_vhost_new (g_strdup (((gvm_vhost_t *) vhost)->value),
915 g_strdup (((gvm_vhost_t *) vhost)->source));
916
917 return ret;
918}
919
925static gvm_host_t *
927{
928 gvm_host_t *host;
929
930 host = g_malloc0 (sizeof (gvm_host_t));
931
932 return host;
933}
934
940void
941gvm_host_free (gpointer host)
942{
943 gvm_host_t *h = host;
944 if (h == NULL)
945 return;
946
947 /* If host of type hostname, free the name buffer, first. */
948 if (h->type == HOST_TYPE_NAME)
949 g_free (h->name);
950
951 g_slist_free_full (h->vhosts, gvm_vhost_free);
952 g_free (h);
953}
954
961void
963{
964 if (hosts->count == hosts->max_size)
965 {
966 hosts->max_size *= 4;
967 hosts->hosts =
968 g_realloc_n (hosts->hosts, hosts->max_size, sizeof (*hosts->hosts));
969 memset (hosts->hosts + hosts->count, '\0',
970 (hosts->max_size - hosts->count) * sizeof (gvm_host_t *));
971 }
972 hosts->hosts[hosts->count] = host;
973 hosts->count++;
974}
975
983static gvm_hosts_t *
984gvm_hosts_init (const char *hosts_str)
985{
986 gvm_hosts_t *hosts;
987
988 hosts = g_malloc0 (sizeof (gvm_hosts_t));
989 hosts->max_size = 1024;
990 hosts->hosts = g_malloc0_n (hosts->max_size, sizeof (gvm_host_t *));
991 hosts->orig_str = g_strdup (hosts_str);
992 return hosts;
993}
994
1001static void
1003{
1004 size_t i;
1005 if (!hosts)
1006 return;
1007
1008 for (i = 0; i < hosts->max_size; i++)
1009 {
1010 if (!hosts->hosts[i])
1011 {
1012 size_t j;
1013
1014 /* Fill the gap with the closest host entry, in order to keep the
1015 * sequential ordering. */
1016 for (j = i + 1; j < hosts->max_size; j++)
1017 {
1018 if (hosts->hosts[j])
1019 {
1020 hosts->hosts[i] = hosts->hosts[j];
1021 hosts->hosts[j] = NULL;
1022 break;
1023 }
1024 }
1025 /* No more entries left, ie. the empty space between count and
1026 * max_size. */
1027 if (!hosts->hosts[i])
1028 return;
1029 }
1030 }
1031}
1032
1039static void
1041{
1045 GHashTable *name_table;
1046 size_t i, duplicates = 0;
1047
1048 if (hosts == NULL)
1049 return;
1050 name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1051
1052 for (i = 0; i < hosts->count; i++)
1053 {
1054 gchar *name;
1055
1056 name = gvm_host_value_str (hosts->hosts[i]);
1057 if (name)
1058 {
1059 gvm_host_t *host, *removed = hosts->hosts[i];
1060
1061 host = g_hash_table_lookup (name_table, name);
1062 if (host)
1063 {
1064 /* Remove duplicate host. Add its vhosts to the original host. */
1065 host->vhosts = g_slist_concat (host->vhosts, removed->vhosts);
1066 removed->vhosts = NULL;
1067 gvm_host_free (removed);
1068 hosts->hosts[i] = NULL;
1069 duplicates++;
1070 g_free (name);
1071 }
1072 else
1073 g_hash_table_insert (name_table, name, hosts->hosts[i]);
1074 }
1075 }
1076
1077 if (duplicates)
1078 gvm_hosts_fill_gaps (hosts);
1079 g_hash_table_destroy (name_table);
1080 hosts->count -= duplicates;
1081 hosts->duplicated += duplicates;
1082 hosts->current = 0;
1083#ifdef __GLIBC__
1084 malloc_trim (0);
1085#endif
1086}
1087
1100gvm_hosts_new_with_max (const gchar *hosts_str, unsigned int max_hosts)
1101{
1102 gvm_hosts_t *hosts;
1103 gchar **host_element, **split;
1104 gchar *str;
1105
1106 if (hosts_str == NULL)
1107 return NULL;
1108
1109 /* Normalize separator: Transform newlines into commas. */
1110 hosts = gvm_hosts_init (hosts_str);
1111 str = hosts->orig_str;
1112 while (*str)
1113 {
1114 if (*str == '\n')
1115 *str = ',';
1116 str++;
1117 }
1118
1119 /* Split comma-separated list into single host-specifications */
1120 split = g_strsplit (hosts->orig_str, ",", 0);
1121
1122 /* first element of the split list */
1123 host_element = split;
1124 while (*host_element)
1125 {
1126 int host_type;
1127 gchar *stripped = g_strstrip (*host_element);
1128
1129 if (stripped == NULL || *stripped == '\0')
1130 {
1131 host_element++;
1132 continue;
1133 }
1134
1135 /* IPv4, hostname, IPv6, collection (short/long range, cidr block) etc,. ?
1136 */
1137 /* -1 if error. */
1138 host_type = gvm_get_host_type (stripped);
1139
1140 switch (host_type)
1141 {
1142 case HOST_TYPE_NAME:
1143 case HOST_TYPE_IPV4:
1144 case HOST_TYPE_IPV6:
1145 {
1146 /* New host. */
1147 gvm_host_t *host = gvm_host_new ();
1148 host->type = host_type;
1150 host->name = g_ascii_strdown (stripped, -1);
1151 else if (host_type == HOST_TYPE_IPV4)
1152 {
1153 if (inet_pton (AF_INET, stripped, &host->addr) != 1)
1154 break;
1155 }
1156 else if (host_type == HOST_TYPE_IPV6)
1157 {
1158 if (inet_pton (AF_INET6, stripped, &host->addr6) != 1)
1159 break;
1160 }
1161 gvm_hosts_add (hosts, host);
1162 break;
1163 }
1167 {
1168 struct in_addr first, last;
1169 uint32_t current;
1170 int (*ips_func) (const char *, struct in_addr *, struct in_addr *);
1171
1173 ips_func = cidr_block_ips;
1174 else if (host_type == HOST_TYPE_RANGE_SHORT)
1175 ips_func = short_range_network_ips;
1176 else
1177 ips_func = long_range_network_ips;
1178
1179 if (ips_func (stripped, &first, &last) == -1)
1180 break;
1181
1182 /* Make sure that first actually comes before last */
1183 if (ntohl (first.s_addr) > ntohl (last.s_addr))
1184 break;
1185
1186 /* Add addresses from first to last as single hosts. */
1187 current = first.s_addr;
1188 while (ntohl (current) <= ntohl (last.s_addr))
1189 {
1190 gvm_host_t *host;
1191 if (max_hosts > 0 && hosts->count > max_hosts)
1192 {
1193 g_strfreev (split);
1194 gvm_hosts_free (hosts);
1195 return NULL;
1196 }
1197 host = gvm_host_new ();
1198 host->type = HOST_TYPE_IPV4;
1199 host->addr.s_addr = current;
1200 gvm_hosts_add (hosts, host);
1201 /* Next IP address. */
1202 current = htonl (ntohl (current) + 1);
1203 }
1204 break;
1205 }
1209 {
1210 struct in6_addr first, last;
1211 unsigned char current[16];
1212 int (*ips_func) (const char *, struct in6_addr *,
1213 struct in6_addr *);
1214
1216 ips_func = cidr6_block_ips;
1218 ips_func = short_range6_network_ips;
1219 else
1220 ips_func = long_range6_network_ips;
1221
1222 if (ips_func (stripped, &first, &last) == -1)
1223 break;
1224
1225 /* Make sure the first comes before the last. */
1226 if (memcmp (&first.s6_addr, &last.s6_addr, 16) > 0)
1227 break;
1228
1229 /* Add addresses from first to last as single hosts. */
1230 memcpy (current, &first.s6_addr, 16);
1231 while (memcmp (current, &last.s6_addr, 16) <= 0)
1232 {
1233 int i;
1234 gvm_host_t *host;
1235
1236 if (max_hosts > 0 && hosts->count > max_hosts)
1237 {
1238 g_strfreev (split);
1239 gvm_hosts_free (hosts);
1240 return NULL;
1241 }
1242 host = gvm_host_new ();
1243 host->type = HOST_TYPE_IPV6;
1244 memcpy (host->addr6.s6_addr, current, 16);
1245 gvm_hosts_add (hosts, host);
1246 /* Next IPv6 address. */
1247 for (i = 15; i >= 0; --i)
1248 if (current[i] < 255)
1249 {
1250 current[i]++;
1251 break;
1252 }
1253 else
1254 current[i] = 0;
1255 }
1256 break;
1257 }
1258 case -1:
1259 default:
1260 /* Invalid host string. */
1261 g_strfreev (split);
1262 gvm_hosts_free (hosts);
1263 return NULL;
1264 }
1265 host_element++; /* move on to next element of split list */
1266 if (max_hosts > 0 && hosts->count > max_hosts)
1267 {
1268 g_strfreev (split);
1269 gvm_hosts_free (hosts);
1270 return NULL;
1271 }
1272 }
1273
1274 /* No need to check for duplicates when a hosts string contains a
1275 * single (IP/Hostname/Range/Subnetwork) entry. */
1276 if (g_strv_length (split) > 1)
1277 gvm_hosts_deduplicate (hosts);
1278
1279 g_strfreev (split);
1280#ifdef __GLIBC__
1281 malloc_trim (0);
1282#endif
1283 return hosts;
1284}
1285
1297gvm_hosts_new (const gchar *hosts_str)
1298{
1299 return gvm_hosts_new_with_max (hosts_str, 0);
1300}
1301
1310gvm_host_t *
1312{
1313 if (!hosts || hosts->current == hosts->count)
1314 return NULL;
1315
1316 return hosts->hosts[hosts->current++];
1317}
1318
1328void
1330{
1331 void *host_tmp;
1332 size_t i;
1333
1334 if (!hosts)
1335 return;
1336
1337 if (hosts->current == hosts->count)
1338 {
1339 hosts->current -= 1;
1340 return;
1341 }
1342
1343 hosts->current -= 1;
1344 host_tmp = hosts->hosts[hosts->current];
1345
1346 for (i = hosts->current; i < hosts->count; i++)
1347 hosts->hosts[i - 1] = hosts->hosts[i];
1348
1349 hosts->hosts[hosts->count - 1] = host_tmp;
1350}
1351
1358void
1360{
1361 size_t i;
1362
1363 if (hosts == NULL)
1364 return;
1365
1366 if (hosts->orig_str)
1367 g_free (hosts->orig_str);
1368 for (i = 0; i < hosts->count; i++)
1369 gvm_host_free (hosts->hosts[i]);
1370 g_free (hosts->hosts);
1371 g_free (hosts);
1372 hosts = NULL;
1373}
1374
1382void
1384{
1385 size_t i = 0;
1386 GRand *rand;
1387
1388 if (hosts == NULL)
1389 return;
1390
1391 /* Shuffle the array. */
1392 rand = g_rand_new ();
1393 for (i = 0; i < hosts->count; i++)
1394 {
1395 void *tmp;
1396 int j = g_rand_int_range (rand, 0, hosts->count);
1397
1398 tmp = hosts->hosts[i];
1399 hosts->hosts[i] = hosts->hosts[j];
1400 hosts->hosts[j] = tmp;
1401 }
1402
1403 hosts->current = 0;
1404 g_rand_free (rand);
1405}
1406
1414void
1416{
1417 size_t i, j;
1418 if (hosts == NULL)
1419 return;
1420
1421 for (i = 0, j = hosts->count - 1; i < j; i++, j--)
1422 {
1423 gvm_host_t *tmp = hosts->hosts[i];
1424 hosts->hosts[i] = hosts->hosts[j];
1425 hosts->hosts[j] = tmp;
1426 }
1427 hosts->current = 0;
1428}
1429
1440GSList *
1442{
1443 size_t i, new_entries = 0, resolved = 0;
1444 GSList *unresolved = NULL;
1445
1446 for (i = 0; i < hosts->count; i++)
1447 {
1448 GSList *list, *tmp;
1449 gvm_host_t *host = hosts->hosts[i];
1450
1451 if (host->type != HOST_TYPE_NAME)
1452 continue;
1453
1454 list = tmp = gvm_resolve_list (host->name);
1455 while (tmp)
1456 {
1457 /* Create a new host for each IP address. */
1458 gvm_host_t *new;
1459 struct in6_addr *ip6 = tmp->data;
1460 gvm_vhost_t *vhost;
1461
1462 new = gvm_host_new ();
1463 if (ip6->s6_addr32[0] != 0 || ip6->s6_addr32[1] != 0
1464 || ip6->s6_addr32[2] != htonl (0xffff))
1465 {
1466 new->type = HOST_TYPE_IPV6;
1467 memcpy (&new->addr6, ip6, sizeof (new->addr6));
1468 }
1469 else
1470 {
1471 new->type = HOST_TYPE_IPV4;
1472 memcpy (&new->addr6, &ip6->s6_addr32[3], sizeof (new->addr));
1473 }
1474 vhost =
1475 gvm_vhost_new (g_strdup (host->name), g_strdup ("Forward-DNS"));
1476 new->vhosts = g_slist_prepend (new->vhosts, vhost);
1477 gvm_hosts_add (hosts, new);
1478 tmp = tmp->next;
1479 new_entries = 1;
1480 }
1481 /* Remove hostname from list, as it was either replaced by IPs, or
1482 * is unresolvable. */
1483 hosts->hosts[i] = NULL;
1484 resolved++;
1485 if (!list)
1486 unresolved = g_slist_prepend (unresolved, g_strdup (host->name));
1487 gvm_host_free (host);
1488 g_slist_free_full (list, g_free);
1489 }
1490 if (resolved)
1491 gvm_hosts_fill_gaps (hosts);
1492 hosts->count -= resolved;
1493 hosts->removed += resolved;
1494 if (new_entries)
1495 gvm_hosts_deduplicate (hosts);
1496 hosts->current = 0;
1497 return unresolved;
1498}
1499
1508int
1509gvm_vhosts_exclude (gvm_host_t *host, const char *excluded_str)
1510{
1511 GSList *vhost;
1512 char **excluded;
1513 int ret = 0;
1514
1515 if (!host || !excluded_str)
1516 return ret;
1517
1518 vhost = host->vhosts;
1519 excluded = g_strsplit (excluded_str, ",", 0);
1520 if (!excluded || !*excluded)
1521 {
1522 g_strfreev (excluded);
1523 return ret;
1524 }
1525 while (vhost)
1526 {
1527 char **tmp = excluded;
1528 char *value = ((gvm_vhost_t *) vhost->data)->value;
1529
1530 while (*tmp)
1531 {
1532 if (!strcasecmp (value, g_strstrip (*tmp)))
1533 {
1534 gvm_vhost_free (vhost->data);
1535 host->vhosts = vhost = g_slist_delete_link (host->vhosts, vhost);
1536 ret++;
1537 break;
1538 }
1539 tmp++;
1540 if (!*tmp)
1541 {
1542 vhost = vhost->next;
1543 break;
1544 }
1545 }
1546 }
1547 g_strfreev (excluded);
1548
1549 return ret;
1550}
1551
1563int
1564gvm_hosts_exclude_with_max (gvm_hosts_t *hosts, const char *excluded_str,
1565 unsigned int max_hosts)
1566{
1570 gvm_hosts_t *excluded_hosts;
1571 GHashTable *name_table;
1572 size_t excluded = 0, i;
1573
1574 if (hosts == NULL || excluded_str == NULL)
1575 return -1;
1576
1577 excluded_hosts = gvm_hosts_new_with_max (excluded_str, max_hosts);
1578 if (excluded_hosts == NULL)
1579 return -1;
1580
1581 if (gvm_hosts_count (excluded_hosts) == 0)
1582 {
1583 gvm_hosts_free (excluded_hosts);
1584 return 0;
1585 }
1586
1587 /* Hash host values from excluded hosts list. */
1588 name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1589 for (i = 0; i < excluded_hosts->count; i++)
1590 {
1591 gchar *name;
1592
1593 name = gvm_host_value_str (excluded_hosts->hosts[i]);
1594 if (name)
1595 g_hash_table_insert (name_table, name, hosts);
1596 }
1597
1598 /* Check for hosts values in hash table. */
1599 for (i = 0; i < hosts->count; i++)
1600 {
1601 gchar *name;
1602
1603 name = gvm_host_value_str (hosts->hosts[i]);
1604 if (name)
1605 {
1606 if (g_hash_table_lookup (name_table, name))
1607 {
1608 gvm_host_free (hosts->hosts[i]);
1609 hosts->hosts[i] = NULL;
1610 excluded++;
1611 g_free (name);
1612 continue;
1613 }
1614 g_free (name);
1615 }
1616 }
1617
1618 /* Cleanup. */
1619 if (excluded)
1620 gvm_hosts_fill_gaps (hosts);
1621 hosts->count -= excluded;
1622 hosts->removed += excluded;
1623 hosts->current = 0;
1624 g_hash_table_destroy (name_table);
1625 gvm_hosts_free (excluded_hosts);
1626 return excluded;
1627}
1628
1641GSList *
1642gvm_hosts_allowed_only (gvm_hosts_t *hosts, const char *deny_hosts_str,
1643 const char *allow_hosts_str)
1644{
1648 gvm_hosts_t *allowed_hosts, *denied_hosts;
1649 GHashTable *name_allow_table = NULL, *name_deny_table = NULL;
1650 GSList *removed = NULL;
1651 size_t excluded = 0, i;
1652
1653 if (hosts == NULL || (deny_hosts_str == NULL && allow_hosts_str == NULL))
1654 return NULL;
1655
1656 // Prepare list of denied and allowed hosts
1657 denied_hosts = gvm_hosts_new_with_max (deny_hosts_str, 0);
1658 allowed_hosts = gvm_hosts_new_with_max (allow_hosts_str, 0);
1659 if (denied_hosts == NULL && allowed_hosts == NULL)
1660 return NULL;
1661
1662 if (gvm_hosts_count (denied_hosts) == 0)
1663 gvm_hosts_free (denied_hosts);
1664 else
1665 {
1666 /* Hash host values from denied hosts list. */
1667 name_deny_table =
1668 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1669 for (i = 0; i < denied_hosts->count; i++)
1670 {
1671 gchar *name;
1672
1673 name = gvm_host_value_str (denied_hosts->hosts[i]);
1674 if (name)
1675 g_hash_table_insert (name_deny_table, name, hosts);
1676 }
1677 }
1678 if (gvm_hosts_count (allowed_hosts) == 0)
1679 gvm_hosts_free (allowed_hosts);
1680 else
1681 {
1682 /* Hash host values from allowed hosts list. */
1683 name_allow_table =
1684 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1685 for (i = 0; i < allowed_hosts->count; i++)
1686 {
1687 gchar *name;
1688
1689 name = gvm_host_value_str (allowed_hosts->hosts[i]);
1690 if (name)
1691 g_hash_table_insert (name_allow_table, name, hosts);
1692 }
1693 }
1694
1695 /* Check for authorized hosts in hash table and create a list of removed
1696 * hosts. */
1697 for (i = 0; i < hosts->count; i++)
1698 {
1699 gchar *name;
1700
1701 name = gvm_host_value_str (hosts->hosts[i]);
1702 if (name)
1703 {
1704 if (denied_hosts != NULL
1705 && g_hash_table_lookup (name_deny_table, name))
1706 {
1707 gvm_host_free (hosts->hosts[i]);
1708 hosts->hosts[i] = NULL;
1709 excluded++;
1710 removed = g_slist_prepend (removed, name);
1711 continue;
1712 }
1713 else if (allowed_hosts != NULL
1714 && !g_hash_table_lookup (name_allow_table, name))
1715 {
1716 gvm_host_free (hosts->hosts[i]);
1717 hosts->hosts[i] = NULL;
1718 excluded++;
1719 removed = g_slist_prepend (removed, name);
1720 continue;
1721 }
1722 g_free (name);
1723 }
1724 }
1725
1726 /* Cleanup. */
1727 if (excluded)
1728 gvm_hosts_fill_gaps (hosts);
1729
1730 hosts->count -= excluded;
1731 hosts->removed += excluded;
1732 hosts->current = 0;
1733 if (name_allow_table != NULL)
1734 g_hash_table_destroy (name_allow_table);
1735 if (name_deny_table != NULL)
1736 g_hash_table_destroy (name_deny_table);
1737 if (allowed_hosts != NULL)
1738 gvm_hosts_free (allowed_hosts);
1739 if (denied_hosts != NULL)
1740 gvm_hosts_free (denied_hosts);
1741 return removed;
1742}
1743
1754int
1755gvm_hosts_exclude (gvm_hosts_t *hosts, const char *excluded_str)
1756{
1757 return gvm_hosts_exclude_with_max (hosts, excluded_str, 0);
1758}
1759
1770gvm_host_t *
1771gvm_host_from_str (const gchar *host_str)
1772{
1773 int host_type;
1774
1775 if (host_str == NULL)
1776 return NULL;
1777
1778 /* IPv4, hostname, IPv6 */
1779 /* -1 if error. */
1780 host_type = gvm_get_host_type (host_str);
1781
1782 switch (host_type)
1783 {
1784 case HOST_TYPE_NAME:
1785 case HOST_TYPE_IPV4:
1786 case HOST_TYPE_IPV6:
1787 {
1788 /* New host. */
1789 gvm_host_t *host = gvm_host_new ();
1790 host->type = host_type;
1792 host->name = g_ascii_strdown (host_str, -1);
1793 else if (host_type == HOST_TYPE_IPV4)
1794 {
1795 if (inet_pton (AF_INET, host_str, &host->addr) != 1)
1796 break;
1797 }
1798 else if (host_type == HOST_TYPE_IPV6)
1799 {
1800 if (inet_pton (AF_INET6, host_str, &host->addr6) != 1)
1801 break;
1802 }
1803 return host;
1804 }
1805 case -1:
1806 default:
1807 return NULL;
1808 }
1809 return NULL;
1810}
1811
1819char *
1821{
1822 int retry = 10;
1823 gchar hostname[NI_MAXHOST];
1824 void *addr;
1825 size_t addrlen;
1826 struct sockaddr_in sa;
1827 struct sockaddr_in6 sa6;
1828
1829 if (!host)
1830 return NULL;
1831
1832 if (host->type == HOST_TYPE_IPV4)
1833 {
1834 addr = &sa;
1835 addrlen = sizeof (sa);
1836 memset (addr, '\0', addrlen);
1837 sa.sin_addr = host->addr;
1838 sa.sin_family = AF_INET;
1839 }
1840 else if (host->type == HOST_TYPE_IPV6)
1841 {
1842 addr = &sa6;
1843 addrlen = sizeof (sa6);
1844 memset (&sa6, '\0', addrlen);
1845 memcpy (&sa6.sin6_addr, &host->addr6, 16);
1846 sa6.sin6_family = AF_INET6;
1847 }
1848 else
1849 return NULL;
1850
1851 while (retry--)
1852 {
1853 int ret = getnameinfo (addr, addrlen, hostname, sizeof (hostname), NULL,
1854 0, NI_NAMEREQD);
1855 if (!ret)
1856 return g_ascii_strdown (hostname, -1);
1857 if (ret != EAI_AGAIN)
1858 break;
1859 usleep (10000); // 10ms
1860 }
1861 return NULL;
1862}
1863
1872static int
1873host_name_verify (gvm_host_t *host, const char *value)
1874{
1875 GSList *list, *tmp;
1876 char *host_str;
1877 int ret = -1;
1878
1879 assert (host);
1880 assert (value);
1881 host_str = gvm_host_value_str (host);
1882 list = tmp = gvm_resolve_list (value);
1883 while (tmp)
1884 {
1885 char buffer[INET6_ADDRSTRLEN];
1886 addr6_to_str (tmp->data, buffer);
1887 if (!strcasecmp (host_str, buffer))
1888 {
1889 ret = 0;
1890 break;
1891 }
1892 tmp = tmp->next;
1893 }
1894 g_free (host_str);
1895 g_slist_free_full (list, g_free);
1896 return ret;
1897}
1898
1904void
1906{
1907 GSList *vhosts;
1908 gvm_vhost_t *vhost;
1909 char *value;
1910
1911 if (!host || host->type == HOST_TYPE_NAME)
1912 return;
1913
1914 value = gvm_host_reverse_lookup (host);
1915 if (!value)
1916 return;
1917 if (host_name_verify (host, value))
1918 {
1919 g_free (value);
1920 return;
1921 }
1922 /* Don't add vhost, if already in the list. */
1923 vhosts = host->vhosts;
1924 while (vhosts)
1925 {
1926 if (!strcasecmp (((gvm_vhost_t *) vhosts->data)->value, value))
1927 {
1928 g_free (value);
1929 return;
1930 }
1931 vhosts = vhosts->next;
1932 }
1933 vhost = gvm_vhost_new (value, g_strdup ("Reverse-DNS"));
1934 host->vhosts = g_slist_prepend (host->vhosts, vhost);
1935}
1936
1948{
1949 size_t i, count = 0;
1950 gvm_hosts_t *excluded = gvm_hosts_new ("");
1951
1952 if (hosts == NULL)
1953 return NULL;
1954
1955 for (i = 0; i < hosts->count; i++)
1956 {
1957 gchar *name = gvm_host_reverse_lookup (hosts->hosts[i]);
1958
1959 if (name == NULL)
1960 {
1961 gvm_hosts_add (excluded, gvm_duplicate_host (hosts->hosts[i]));
1962 gvm_host_free (hosts->hosts[i]);
1963 hosts->hosts[i] = NULL;
1964 count++;
1965 }
1966 else
1967 g_free (name);
1968 }
1969
1970 if (count)
1971 gvm_hosts_fill_gaps (hosts);
1972 hosts->count -= count;
1973 hosts->removed += count;
1974 hosts->current = 0;
1975 return excluded;
1976}
1977
1987int
1989{
1990 gvm_hosts_t *excluded;
1991 int count = 0;
1992
1993 if (hosts == NULL)
1994 return -1;
1995
1996 excluded = gvm_hosts_reverse_lookup_only_excluded (hosts);
1997 count = excluded->count;
1998 gvm_hosts_free (excluded);
1999
2000 return count;
2001}
2002
2014{
2018 size_t i, count = 0;
2019 GHashTable *name_table;
2020 gvm_hosts_t *excluded = NULL;
2021
2022 if (hosts == NULL)
2023 return NULL;
2024
2025 excluded = gvm_hosts_new ("");
2026 name_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
2027 for (i = 0; i < hosts->count; i++)
2028 {
2029 gchar *name;
2030
2031 name = gvm_host_reverse_lookup (hosts->hosts[i]);
2032 if (name)
2033 {
2034 if (g_hash_table_lookup (name_table, name))
2035 {
2036 gvm_hosts_add (excluded, gvm_duplicate_host (hosts->hosts[i]));
2037 gvm_host_free (hosts->hosts[i]);
2038 hosts->hosts[i] = NULL;
2039 count++;
2040 g_free (name);
2041 }
2042 else
2043 {
2044 /* Insert in the hash table. Value not important. */
2045 g_hash_table_insert (name_table, name, hosts);
2046 }
2047 }
2048 }
2049
2050 if (count)
2051 gvm_hosts_fill_gaps (hosts);
2052 g_hash_table_destroy (name_table);
2053 hosts->removed += count;
2054 hosts->count -= count;
2055 hosts->current = 0;
2056 return excluded;
2057}
2058
2068int
2070{
2071 gvm_hosts_t *excluded = NULL;
2072 int count = 0;
2073 if (hosts == NULL)
2074 return -1;
2075
2076 excluded = gvm_hosts_reverse_lookup_unify_excluded (hosts);
2077 count = excluded->count;
2078 gvm_hosts_free (excluded);
2079
2080 return count;
2081}
2082
2089unsigned int
2091{
2092 return hosts ? hosts->count : 0;
2093}
2094
2103unsigned int
2105{
2106 return hosts ? hosts->removed : 0;
2107}
2108
2117unsigned int
2119{
2120 return hosts ? hosts->duplicated : 0;
2121}
2122
2133gvm_host_t *
2134gvm_host_find_in_hosts (const gvm_host_t *host, const struct in6_addr *addr,
2135 const gvm_hosts_t *hosts)
2136{
2137 char *host_str;
2138 size_t i;
2139
2140 if (host == NULL || hosts == NULL)
2141 return NULL;
2142
2143 host_str = gvm_host_value_str (host);
2144
2145 for (i = 0; i < hosts->count; i++)
2146 {
2147 gvm_host_t *current_host = hosts->hosts[i];
2148 char *tmp = gvm_host_value_str (current_host);
2149
2150 if (strcasecmp (host_str, tmp) == 0)
2151 {
2152 g_free (host_str);
2153 g_free (tmp);
2154 return current_host;
2155 }
2156 g_free (tmp);
2157
2158 /* Hostnames in hosts list shouldn't be resolved. */
2159 if (addr && gvm_host_type (current_host) != HOST_TYPE_NAME)
2160 {
2161 struct in6_addr tmpaddr;
2162 gvm_host_get_addr6 (current_host, &tmpaddr);
2163
2164 if (memcmp (addr->s6_addr, &tmpaddr.s6_addr, 16) == 0)
2165 {
2166 g_free (host_str);
2167 return current_host;
2168 }
2169 }
2170 }
2171
2172 g_free (host_str);
2173 return NULL;
2174}
2175
2182gvm_host_t *
2184{
2185 gvm_host_t *ret = NULL;
2186
2187 if (host == NULL)
2188 return NULL;
2189
2190 ret = gvm_host_new ();
2191
2192 ret->type = host->type;
2193 switch (host->type)
2194 {
2195 case HOST_TYPE_NAME:
2196 ret->name = g_strdup (host->name);
2197 break;
2198 case HOST_TYPE_IPV4:
2199 ret->addr = host->addr;
2200 break;
2201 case HOST_TYPE_IPV6:
2202 ret->addr6 = host->addr6;
2203 break;
2204 default:
2205 g_free (ret);
2206 return NULL;
2207 }
2208 ret->vhosts = g_slist_copy_deep (host->vhosts, gvm_duplicate_vhost, NULL);
2209
2210 return ret;
2211}
2212
2225int
2226gvm_host_in_hosts (const gvm_host_t *host, const struct in6_addr *addr,
2227 const gvm_hosts_t *hosts)
2228{
2229 if (gvm_host_find_in_hosts (host, addr, hosts))
2230 return 1;
2231
2232 return 0;
2233}
2234
2242enum host_type
2244{
2245 assert (host);
2246 return host->type;
2247}
2248
2257gchar *
2259{
2260 if (host == NULL)
2261 return NULL;
2262
2263 return host_type_str[host->type];
2264}
2265
2273gchar *
2275{
2276 if (host == NULL)
2277 return NULL;
2278
2279 switch (host->type)
2280 {
2281 case HOST_TYPE_NAME:
2282 return g_strdup (host->name);
2283 break;
2284 case HOST_TYPE_IPV4:
2285 case HOST_TYPE_IPV6:
2286 /* Handle both cases using inet_ntop(). */
2287 {
2288 int family, size;
2289 gchar *str;
2290 const void *srcaddr;
2291
2292 if (host->type == HOST_TYPE_IPV4)
2293 {
2294 family = AF_INET;
2295 size = INET_ADDRSTRLEN;
2296 srcaddr = &host->addr;
2297 }
2298 else
2299 {
2300 family = AF_INET6;
2301 size = INET6_ADDRSTRLEN;
2302 srcaddr = &host->addr6;
2303 }
2304
2305 str = g_malloc0 (size);
2306 if (inet_ntop (family, srcaddr, str, size) == NULL)
2307 {
2308 perror ("inet_ntop");
2309 g_free (str);
2310 return NULL;
2311 }
2312 return str;
2313 }
2314 default:
2315 return g_strdup ("Erroneous host type: Should be Hostname/IPv4/IPv6.");
2316 }
2317}
2318
2330int
2331gvm_host_resolve (const gvm_host_t *host, void *dst, int family)
2332{
2333 if (host == NULL || dst == NULL || host->type != HOST_TYPE_NAME)
2334 return -1;
2335
2336 return gvm_resolve (host->name, dst, family);
2337}
2338
2351int
2352gvm_host_get_addr6 (const gvm_host_t *host, struct in6_addr *ip6)
2353{
2354 if (host == NULL || ip6 == NULL)
2355 return -1;
2356
2357 switch (gvm_host_type (host))
2358 {
2359 case HOST_TYPE_IPV6:
2360 memcpy (ip6, &host->addr6, sizeof (struct in6_addr));
2361 return 0;
2362
2363 case HOST_TYPE_IPV4:
2364 ipv4_as_ipv6 (&host->addr, ip6);
2365 return 0;
2366
2367 case HOST_TYPE_NAME:
2368 {
2369 struct in_addr ip4;
2370
2371 /* Fail if IPv4 and IPv6 both don't resolve. */
2372 if (gvm_host_resolve (host, &ip4, AF_INET) == 0)
2373 ipv4_as_ipv6 (&ip4, ip6);
2374 else if (gvm_host_resolve (host, ip6, AF_INET6) == -1)
2375 return -1;
2376 return 0;
2377 }
2378
2379 default:
2380 return -1;
2381 }
2382}
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:962
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:2226
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:2013
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:1988
gchar * gvm_host_value_str(const gvm_host_t *host)
Gets a host's value in printable format.
Definition hosts.c:2274
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:2331
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:1947
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:641
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:1820
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
static int 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:513
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:2183
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:871
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:1297
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:1311
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:1642
void gvm_host_free(gpointer host)
Frees the memory occupied by an gvm_host_t object.
Definition hosts.c:941
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:2104
gchar * gvm_host_type_str(const gvm_host_t *host)
Gets a host's type in printable format.
Definition hosts.c:2258
void gvm_host_add_reverse_lookup(gvm_host_t *host)
Add a host's reverse-lookup name to the vhosts list.
Definition hosts.c:1905
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:1100
static int is_hostname(const char *str)
Checks if a buffer points to a valid hostname.
Definition hosts.c:396
static int 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:467
static gvm_host_t * gvm_host_new()
Creates a new gvm_host_t object.
Definition hosts.c:926
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:1415
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:1383
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:2118
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:716
gvm_host_t * gvm_host_from_str(const gchar *host_str)
Creates a new gvm_host_t from a host string.
Definition hosts.c:1771
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:1040
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:764
static int 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:569
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:984
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:676
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:2352
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:1329
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:1509
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:1564
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:1441
enum host_type gvm_host_type(const gvm_host_t *host)
Gets a host object's type.
Definition hosts.c:2243
gpointer gvm_duplicate_vhost(gconstpointer vhost, gpointer data)
Creates a deep copy of a gvm_vhost_t object.
Definition hosts.c:906
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:1002
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:1873
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:2134
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition hosts.c:810
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:2090
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:888
void gvm_hosts_free(gvm_hosts_t *hosts)
Frees memory occupied by an gvm_hosts_t structure.
Definition hosts.c:1359
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:1755
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:2069
static int 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:534
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