From 18573b23aa84a04d973d454ac81960e374de0bb3 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Thu, 5 Mar 2026 10:51:01 -0300 Subject: [PATCH 01/11] Add: ipv6 network host discovery --- base/hosts.c | 26 +++++++ base/hosts.h | 13 ++++ boreas/alivedetection.c | 1 + boreas/alivedetection.h | 10 ++- boreas/boreas_error.c | 3 + boreas/boreas_error.h | 1 + boreas/cli.c | 159 ++++++++++++++++++++++++++++++++-------- boreas/cli.h | 3 + boreas/ping.c | 121 ++++++++++++++++++++++++++++++ boreas/ping.h | 2 + boreas/util.c | 13 +++- 11 files changed, 321 insertions(+), 31 deletions(-) diff --git a/base/hosts.c b/base/hosts.c index 4d40167bf..c3069d35f 100644 --- a/base/hosts.c +++ b/base/hosts.c @@ -503,6 +503,13 @@ is_cidr6_block (const char *str) return 1; } +int +gvm_is_cidr6_block (const char *str) +{ + return is_cidr6_block (str); +} + + /** * @brief Gets the network block value from a CIDR-expressed block string. * For "192.168.1.1/24" it is 24. @@ -524,6 +531,12 @@ cidr6_get_block (const char *str, unsigned int *block) return 0; } +int +gvm_cidr6_get_block (const char *str, unsigned int *block) +{ + return cidr6_get_block (str, block); +} + /** * @brief Gets the IPv4 value from a CIDR-expressed block. * eg. For "192.168.1.10/24" it is "192.168.1.10". @@ -557,6 +570,12 @@ cidr6_get_ip (const char *str, struct in6_addr *addr6) return 0; } +int +gvm_cidr6_get_ip (const char *str, struct in6_addr *addr6) +{ + return cidr6_get_ip (str, addr6); +} + /** * @brief Gets the first and last usable IPv4 addresses from a CIDR-expressed * block. eg. "192.168.1.0/24 would give 192.168.1.1 as first and 192.168.1.254 @@ -632,6 +651,13 @@ cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) return 0; } +int +gvm_cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) +{ + return cidr6_block_ips (const char *str, struct in6_addr *first, + struct in6_addr *last); +} + /** * @brief Checks if a buffer points to a valid long IPv6 range-expressed * network. "::fee5-::1:530" is valid. diff --git a/base/hosts.h b/base/hosts.h index 1c34e6bd4..a0604336e 100644 --- a/base/hosts.h +++ b/base/hosts.h @@ -208,4 +208,17 @@ gvm_vhost_new (char *, char *); int gvm_get_host_type (const gchar *); +int +gvm_is_cidr6_block (const char *); + +int +gvm_cidr6_get_block (const char *, unsigned int *); + +int +gvm_cidr6_get_ip (const char *, struct in6_addr *); + +int +gvm_cidr6_block_ips (const char *str, struct in6_addr *first, + struct in6_addr *last); + #endif /* not _GVM_BASE_HOSTS_H */ diff --git a/boreas/alivedetection.c b/boreas/alivedetection.c index 5cd25a69f..73cd988ae 100644 --- a/boreas/alivedetection.c +++ b/boreas/alivedetection.c @@ -462,6 +462,7 @@ alive_detection_free (void *error) * gvm_host_t are freed by caller of start_alive_detection()! */ g_hash_table_destroy (scanner.hosts_data->targethosts); g_free (scanner.hosts_data); + g_free (scanner.ipv6_net); /* Set error. */ *(boreas_error_t *) error = error_out; diff --git a/boreas/alivedetection.h b/boreas/alivedetection.h index 1441ec316..a8e654ee0 100644 --- a/boreas/alivedetection.h +++ b/boreas/alivedetection.h @@ -36,6 +36,7 @@ start_alive_detection (void *); typedef struct hosts_data hosts_data_t; typedef struct scan_restrictions scan_restrictions_t; +typedef struct ipv6_net_data ipv6_net_data_t; /** * @brief The scanner struct holds data which is used frequently by the alive @@ -62,6 +63,7 @@ struct scanner /* pcap handle */ pcap_t *pcap_handle; hosts_data_t *hosts_data; + ipv6_net_data_t *ipv6_net; scan_restrictions_t *scan_restrictions; /* 0 do not print in stdout, 1 print in stdout used for cmd line cli. */ int print_results; @@ -69,6 +71,11 @@ struct scanner typedef struct scanner scanner_t; +struct ipv6_net_data +{ + char *net; +} + /** * @brief The hosts_data struct holds the alive hosts and target hosts in * separate hashtables. @@ -108,7 +115,8 @@ typedef enum ALIVE_TEST_ICMP = 2, ALIVE_TEST_ARP = 4, ALIVE_TEST_CONSIDER_ALIVE = 8, - ALIVE_TEST_TCP_SYN_SERVICE = 16 + ALIVE_TEST_TCP_SYN_SERVICE = 16, + ALIVE_TEST_IPV6_HOST_DISCOVERY = 32 } alive_test_t; /** diff --git a/boreas/boreas_error.c b/boreas/boreas_error.c index 83b55772d..0fc1c6eb1 100644 --- a/boreas/boreas_error.c +++ b/boreas/boreas_error.c @@ -45,6 +45,9 @@ str_boreas_error (boreas_error_t boreas_error) msg = "Boreas was not able to determine a source address for the given " "destination."; break; + case BOREAS_INVALID_IPV6_NETWORK: + msg = "Invalid IPv6 Network. Not possible to run an Host Discovery"; + break; case NO_ERROR: msg = "No error was encountered by Boreas"; break; diff --git a/boreas/boreas_error.h b/boreas/boreas_error.h index ffbcd5386..1fd416095 100644 --- a/boreas/boreas_error.h +++ b/boreas/boreas_error.h @@ -16,6 +16,7 @@ typedef enum BOREAS_NO_VALID_ALIVE_TEST_SPECIFIED, BOREAS_CLEANUP_ERROR, BOREAS_NO_SRC_ADDR_FOUND, + BOREAS_INVALID_IPV6_NETWORK, NO_ERROR = 0, } boreas_error_t; diff --git a/boreas/cli.c b/boreas/cli.c index 5f746c959..b2c38c493 100644 --- a/boreas/cli.c +++ b/boreas/cli.c @@ -8,6 +8,7 @@ #include "../base/networking.h" #include "../base/prefs.h" #include "alivedetection.h" +#include "boreas_error.h" #include "boreas_io.h" #include "ping.h" #include "sniffer.h" @@ -15,7 +16,9 @@ #include #include +#include #include +#include #undef G_LOG_DOMAIN /** @@ -71,6 +74,38 @@ init_cli (scanner_t *scanner, gvm_hosts_t *hosts, alive_test_t alive_test, return error; } +static boreas_error_t +init_cli_for_host_discovery (scanner_t *scanner, const char *net, + alive_test_t alive_test, + const int print_results) +{ + int error; + + /* No kb used for cli mode.*/ + scanner->main_kb = NULL; + scanner->print_results = print_results; + + scanner->ipv6_net = g_malloc0 (sizeof (ipv6_net_data_t)); + scanner->ipv6_net->net = net; + + /* hosts_data */ + scanner->hosts_data = g_malloc0 (sizeof (hosts_data_t)); + scanner->hosts_data->alivehosts = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + scanner->hosts_data->targethosts = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + /* Sockets. */ + error = set_all_needed_sockets (scanner, alive_test); + if (error != 0) + return error; + + /* No scan restrictions. */ + init_scan_restrictions (scanner, 0); + + return error; +} + static boreas_error_t free_cli (scanner_t *scanner, alive_test_t alive_test) { @@ -108,39 +143,48 @@ run_cli_scan (scanner_t *scanner, alive_test_t alive_test) if (error) return error; - if (alive_test & (ALIVE_TEST_ICMP)) - { - g_hash_table_foreach (scanner->hosts_data->targethosts, send_icmp, - scanner); - wait_until_so_sndbuf_empty (scanner->icmpv4soc, 10); - wait_until_so_sndbuf_empty (scanner->icmpv6soc, 10); - usleep (500000); - } - if (alive_test & (ALIVE_TEST_TCP_SYN_SERVICE)) + if (alive_test & (ALIVE_TEST_IPV6_HOST_DISCOVERY)) { - scanner->tcp_flag = 0x02; /* SYN */ - g_hash_table_foreach (scanner->hosts_data->targethosts, send_tcp, - scanner); - wait_until_so_sndbuf_empty (scanner->tcpv4soc, 10); - wait_until_so_sndbuf_empty (scanner->tcpv6soc, 10); + send_icmp_v6_multicast (&scanner, net); + wait_until_so_sndbuf_empty ((&scanner)->icmpv6soc, 10); usleep (500000); } - if (alive_test & (ALIVE_TEST_TCP_ACK_SERVICE)) + else { - scanner->tcp_flag = 0x10; /* ACK */ - g_hash_table_foreach (scanner->hosts_data->targethosts, send_tcp, - scanner); - wait_until_so_sndbuf_empty (scanner->tcpv4soc, 10); - wait_until_so_sndbuf_empty (scanner->tcpv6soc, 10); - usleep (500000); - } - if (alive_test & (ALIVE_TEST_ARP)) - { - g_hash_table_foreach (scanner->hosts_data->targethosts, send_arp, - scanner); - wait_until_so_sndbuf_empty (scanner->arpv4soc, 10); - wait_until_so_sndbuf_empty (scanner->arpv6soc, 10); - usleep (500000); + if (alive_test & (ALIVE_TEST_ICMP)) + { + g_hash_table_foreach (scanner->hosts_data->targethosts, send_icmp, + scanner); + wait_until_so_sndbuf_empty (scanner->icmpv4soc, 10); + wait_until_so_sndbuf_empty (scanner->icmpv6soc, 10); + usleep (500000); + } + if (alive_test & (ALIVE_TEST_TCP_SYN_SERVICE)) + { + scanner->tcp_flag = 0x02; /* SYN */ + g_hash_table_foreach (scanner->hosts_data->targethosts, send_tcp, + scanner); + wait_until_so_sndbuf_empty (scanner->tcpv4soc, 10); + wait_until_so_sndbuf_empty (scanner->tcpv6soc, 10); + usleep (500000); + } + if (alive_test & (ALIVE_TEST_TCP_ACK_SERVICE)) + { + scanner->tcp_flag = 0x10; /* ACK */ + g_hash_table_foreach (scanner->hosts_data->targethosts, send_tcp, + scanner); + wait_until_so_sndbuf_empty (scanner->tcpv4soc, 10); + wait_until_so_sndbuf_empty (scanner->tcpv6soc, 10); + usleep (500000); + } + if (alive_test & (ALIVE_TEST_ARP)) + { + g_hash_table_foreach (scanner->hosts_data->targethosts, send_arp, + scanner); + wait_until_so_sndbuf_empty (scanner->arpv4soc, 10); + wait_until_so_sndbuf_empty (scanner->arpv6soc, 10); + usleep (500000); + } } if (wait_timeout > 0 && wait_timeout <= 20) @@ -203,6 +247,63 @@ run_cli_extended (gvm_hosts_t *hosts, alive_test_t alive_test, return NO_ERROR; } + +/** + * @brief + * + * @param[in] net IPv6 network + * + * @return NO_ERROR (0) on success, boreas_error_t on error. + */ +boreas_error_t +run_cli_for_ipv6_network (const char *net) +{ + unsigned int block; + struct in6_addr target; + scanner_t scanner = {0}; + boreas_error_t init_err; + boreas_error_t run_err; + boreas_error_t free_err; + int print_results = 1; + + if (net == NULL || gvm_get_host_type(net) != HOST_TYPE_CIDR6_BLOCK) + return BOREAS_INVALID_IPV6_NETWORK; + + if (gvm_cidr6_get_block (net, &block) < 0 || + gvm_cidr6_get_ip (net, &target) < 0) + return BOREAS_INVALID_IPV6_NETWORK; + + init_err = + init_cli_for_host_discovery (&scanner, net, ALIVE_TEST_IPV6_HOST_DISCOVERY, + print_results); + if (init_err) + { + printf ("Error initializing scanner.\n"); + return init_err; + } + + send_icmp_v6_multicast (&scanner, net); + wait_until_so_sndbuf_empty ((&scanner)->icmpv6soc, 10); + + run_err = run_cli_scan (&scanner, ALIVE_TEST_IPV6_HOST_DISCOVERY); + if (run_err) + { + printf ("Error while running the scan.\n"); + return run_err; + } + + free_err = free_cli (&scanner, ALIVE_TEST_IPV6_HOST_DISCOVERY); + if (free_err) + { + printf ("Error freeing scan data.\n"); + return free_err; + } + + return NO_ERROR; + + return 0; +} + /** * @brief Scan all specified hosts in ip_str list. * diff --git a/boreas/cli.h b/boreas/cli.h index a129c8ba1..6ec3bc184 100644 --- a/boreas/cli.h +++ b/boreas/cli.h @@ -17,6 +17,9 @@ boreas_error_t run_cli (gvm_hosts_t *, alive_test_t, const gchar *); boreas_error_t +run_cli_for_ipv6_network (const char *); + + boreas_error_t is_host_alive (const char *, int *); #endif /* not _GVM_BOREAS_CLI_H */ diff --git a/boreas/ping.c b/boreas/ping.c index eb69b9fe3..a0dbc48d4 100644 --- a/boreas/ping.c +++ b/boreas/ping.c @@ -6,6 +6,7 @@ #include "ping.h" #include "../base/prefs.h" /* for prefs_get() */ +#include "../base/networking.h" #include "arp.h" #include "util.h" @@ -32,6 +33,18 @@ */ #define G_LOG_DOMAIN "libgvm boreas" +struct v6pseudo_icmp_hdr +{ + struct in6_addr s6addr; + struct in6_addr d6addr; + u_short length; + u_char zero1; + u_char zero2; + u_char zero3; + u_char protocol; + struct icmp6_hdr icmpheader; +}; + struct v6pseudohdr { struct in6_addr s6addr; @@ -293,6 +306,114 @@ send_icmp (gpointer key, gpointer value, gpointer scanner_p) } } +/** + * @brief Send icmp ping to multicast address. + * + * @param soc Socket to use for sending. + * @param dst Destination network address to explore + */ +void +send_icmp_v6_multicast (gpointer scanner_p, const char *net) +{ + boreas_error_t error; + struct sockaddr_in6 soca, socs; + struct in6_addr src; + scanner_t *scanner = scanner_p; + /* Throttling related variables */ + static int so_sndbuf = -1; // socket send buffer + static int init = -1; + int *udpv6soc = &(scanner->udpv6soc); + int soc; + struct in6_addr first; + struct in6_addr last; + + u_char packet[sizeof (struct ip6_hdr) + sizeof (struct icmp6_hdr)]; + struct ip6_hdr *ip = (struct ip6_hdr *) packet; + struct icmp6_hdr *icmp = + (struct icmp6_hdr *) (packet + sizeof (struct ip6_hdr)); + + /* Get source address for TCP header. */ + gvm_cidr6_block_ips(net, &first, &last); + error = get_source_addr_v6 (udpv6soc, &first, &src); + if (error) + { + char destination_str[INET_ADDRSTRLEN]; + inet_ntop (AF_INET6, (const void *) &first, destination_str, + INET_ADDRSTRLEN); + g_debug ("%s: Destination: %s. %s", __func__, destination_str, + str_boreas_error (error)); + return; + } + + memset (packet, 0, sizeof (packet)); + /* IPv6 */ + ip->ip6_flow = htonl ((6 << 28) | (0 << 20) | 0); + ip->ip6_plen = htons (8); // ICMP6_HDRLEN + ip->ip6_nxt= IPPROTO_ICMPV6; + ip->ip6_hops = 255; // max value + inet_pton (AF_INET6, "FF02::1", &ip->ip6_dst); + ip->ip6_src = src; + + /* ICMP */ + icmp->icmp6_type = ICMP6_ECHO_REQUEST; + icmp->icmp6_code = 0; + icmp->icmp6_id = get_echo_id (); + icmp->icmp6_seq = 0x0100; + + /* CKsum */ + { + struct v6pseudo_icmp_hdr pseudoheader; + + memset (&pseudoheader, 0, sizeof (packet)); + memcpy (&pseudoheader.s6addr, &ip->ip6_src, sizeof (struct in6_addr)); + memcpy (&pseudoheader.d6addr, &ip->ip6_dst, sizeof (struct in6_addr)); + + pseudoheader.protocol = IPPROTO_ICMPV6; + pseudoheader.length = htons(8); + memcpy ((char *) &pseudoheader.icmpheader, (char *) icmp, + sizeof (struct icmp6_hdr)); + icmp->icmp6_cksum = + in_cksum((unsigned short *) &pseudoheader, sizeof(packet)); + } + + int opt_on = 1; + soc = socket (AF_INET6, SOCK_RAW, IPPROTO_RAW); + setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on, + sizeof (opt_on)); + + /* Get size of empty SO_SNDBUF */ + if (init == -1) + { + if (get_so_sndbuf (soc, &so_sndbuf) == 0) + init = 1; + } + + /* Throttle speed if needed */ + throttle (soc, so_sndbuf); + + // Enable multicast + setsockopt (soc, SOL_SOCKET, SO_BROADCAST, &opt_on, sizeof (opt_on)); + + // source + memset (&socs, 0, sizeof (socs)); + socs.sin6_family = AF_INET6; + socs.sin6_addr = ip->ip6_src; + // destination socket + memset (&soca, 0, sizeof (soca)); + soca.sin6_family = AF_INET6; + soca.sin6_addr = ip->ip6_dst; + // to set the source address + bind(soc, (struct sockaddr *) &socs, sizeof(socs)); + + /* ICMP6_HDRLEN(8) IP6_HDRLEN(40) */ + if (sendto (soc, (const void *) ip, 40 + 8, 0, + (struct sockaddr *) &soca, sizeof (struct sockaddr_in6)) + < 0) + { + g_debug ("%s: sendto(): %s", __func__, strerror (errno)); + } +} + /** * @brief Send tcp ping. * diff --git a/boreas/ping.h b/boreas/ping.h index be3a66f09..44dc1b852 100644 --- a/boreas/ping.h +++ b/boreas/ping.h @@ -14,4 +14,6 @@ void send_tcp (gpointer, gpointer, gpointer); void send_arp (gpointer, gpointer, gpointer); +void send_icmp_v6_multicast (gpointer, const char *); + #endif /* not _GVM_BOREAS_PING_H */ diff --git a/boreas/util.c b/boreas/util.c index 504d3195f..dc5025fa6 100644 --- a/boreas/util.c +++ b/boreas/util.c @@ -157,7 +157,7 @@ get_source_addr_v6 (int *udpv6soc, struct in6_addr *dst, struct in6_addr *src) sock_len = sizeof (storage); if (connect (*udpv6soc, (const struct sockaddr *) &storage, sock_len) < 0) { - g_warning ("%s: connect() on udpv6soc failed: %s %d", __func__, + g_warning("%s: connect() on udpv6soc failed: %s %d", __func__, strerror (errno), errno); /* State of the socket is unspecified. Close the socket and create a new * one. */ @@ -583,6 +583,17 @@ set_all_needed_sockets (scanner_t *scanner, alive_test_t alive_test) return error; } + if ((alive_test & 32)) + { + // Set UDP socket for getting the src address + error = set_socket (UDPV6, &(scanner->udpv6soc)); + if (error != 0) + return error; + error = set_socket (ICMPV6, &(scanner->icmpv6soc)); + if (error != 0) + return error; + } + return error; } From ac4b0ba340729af05305de806106489742120b37 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Thu, 5 Mar 2026 16:50:29 -0300 Subject: [PATCH 02/11] capture icmpv6 reply while performing host discovery --- base/hosts.c | 3 +- boreas/alivedetection.c | 3 +- boreas/alivedetection.h | 4 ++- boreas/cli.c | 35 +++++++++++++-------- boreas/ping.c | 43 +++----------------------- boreas/ping.h | 2 +- boreas/sniffer.c | 24 +++++++++++++-- boreas/util.c | 68 ++++++++++++++++++++++++++++++++++------- boreas/util.h | 6 ++++ 9 files changed, 119 insertions(+), 69 deletions(-) diff --git a/base/hosts.c b/base/hosts.c index c3069d35f..02a507a60 100644 --- a/base/hosts.c +++ b/base/hosts.c @@ -654,8 +654,7 @@ cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) int gvm_cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) { - return cidr6_block_ips (const char *str, struct in6_addr *first, - struct in6_addr *last); + return cidr6_block_ips (str, first, last); } /** diff --git a/boreas/alivedetection.c b/boreas/alivedetection.c index 73cd988ae..395d7142b 100644 --- a/boreas/alivedetection.c +++ b/boreas/alivedetection.c @@ -462,8 +462,9 @@ alive_detection_free (void *error) * gvm_host_t are freed by caller of start_alive_detection()! */ g_hash_table_destroy (scanner.hosts_data->targethosts); g_free (scanner.hosts_data); + g_free (scanner.ipv6_net->net); g_free (scanner.ipv6_net); - + /* Set error. */ *(boreas_error_t *) error = error_out; } diff --git a/boreas/alivedetection.h b/boreas/alivedetection.h index a8e654ee0..9cb603ecb 100644 --- a/boreas/alivedetection.h +++ b/boreas/alivedetection.h @@ -67,6 +67,7 @@ struct scanner scan_restrictions_t *scan_restrictions; /* 0 do not print in stdout, 1 print in stdout used for cmd line cli. */ int print_results; + int host_discovery; }; typedef struct scanner scanner_t; @@ -74,7 +75,8 @@ typedef struct scanner scanner_t; struct ipv6_net_data { char *net; -} + struct in6_addr src; +}; /** * @brief The hosts_data struct holds the alive hosts and target hosts in diff --git a/boreas/cli.c b/boreas/cli.c index b2c38c493..27b1eceb5 100644 --- a/boreas/cli.c +++ b/boreas/cli.c @@ -41,6 +41,7 @@ init_cli (scanner_t *scanner, gvm_hosts_t *hosts, alive_test_t alive_test, /* No kb used for cli mode.*/ scanner->main_kb = NULL; scanner->print_results = print_results; + scanner->host_discovery = 0; /* hosts_data */ scanner->hosts_data = g_malloc0 (sizeof (hosts_data_t)); @@ -76,7 +77,6 @@ init_cli (scanner_t *scanner, gvm_hosts_t *hosts, alive_test_t alive_test, static boreas_error_t init_cli_for_host_discovery (scanner_t *scanner, const char *net, - alive_test_t alive_test, const int print_results) { int error; @@ -84,10 +84,8 @@ init_cli_for_host_discovery (scanner_t *scanner, const char *net, /* No kb used for cli mode.*/ scanner->main_kb = NULL; scanner->print_results = print_results; + scanner->host_discovery = 1; - scanner->ipv6_net = g_malloc0 (sizeof (ipv6_net_data_t)); - scanner->ipv6_net->net = net; - /* hosts_data */ scanner->hosts_data = g_malloc0 (sizeof (hosts_data_t)); scanner->hosts_data->alivehosts = @@ -95,10 +93,21 @@ init_cli_for_host_discovery (scanner_t *scanner, const char *net, scanner->hosts_data->targethosts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - /* Sockets. */ - error = set_all_needed_sockets (scanner, alive_test); + // Create socket for getting the src address + error = set_udp6_socket (scanner); if (error != 0) - return error; + { + printf ("%s: %s", __func__, str_boreas_error (error)); + return error; + } + + error = init_ipv6_net_data(scanner, net); + if (error != 0) + { + printf ("%s:Not possible to initialize data: %s", + __func__, str_boreas_error (error)); + return error; + } /* No scan restrictions. */ init_scan_restrictions (scanner, 0); @@ -136,7 +145,9 @@ run_cli_scan (scanner_t *scanner, alive_test_t alive_test) gettimeofday (&start_time, NULL); number_of_targets = g_hash_table_size (scanner->hosts_data->targethosts); - if (scanner->print_results == 1) + if (scanner->print_results == 1 && scanner->host_discovery) + printf ("Host discovery started for network %s.\n", scanner->ipv6_net->net); + else printf ("Alive scan started: Target has %d hosts.\n", number_of_targets); error = start_sniffer_thread (scanner, &sniffer_thread_id); @@ -145,8 +156,8 @@ run_cli_scan (scanner_t *scanner, alive_test_t alive_test) if (alive_test & (ALIVE_TEST_IPV6_HOST_DISCOVERY)) { - send_icmp_v6_multicast (&scanner, net); - wait_until_so_sndbuf_empty ((&scanner)->icmpv6soc, 10); + send_icmp_v6_multicast (scanner); + wait_until_so_sndbuf_empty (scanner->icmpv6soc, 10); usleep (500000); } else @@ -274,7 +285,7 @@ run_cli_for_ipv6_network (const char *net) return BOREAS_INVALID_IPV6_NETWORK; init_err = - init_cli_for_host_discovery (&scanner, net, ALIVE_TEST_IPV6_HOST_DISCOVERY, + init_cli_for_host_discovery (&scanner, net, print_results); if (init_err) { @@ -282,7 +293,7 @@ run_cli_for_ipv6_network (const char *net) return init_err; } - send_icmp_v6_multicast (&scanner, net); + send_icmp_v6_multicast (&scanner); wait_until_so_sndbuf_empty ((&scanner)->icmpv6soc, 10); run_err = run_cli_scan (&scanner, ALIVE_TEST_IPV6_HOST_DISCOVERY); diff --git a/boreas/ping.c b/boreas/ping.c index a0dbc48d4..04ce40b86 100644 --- a/boreas/ping.c +++ b/boreas/ping.c @@ -313,46 +313,27 @@ send_icmp (gpointer key, gpointer value, gpointer scanner_p) * @param dst Destination network address to explore */ void -send_icmp_v6_multicast (gpointer scanner_p, const char *net) +send_icmp_v6_multicast (gpointer scanner_p) { - boreas_error_t error; - struct sockaddr_in6 soca, socs; - struct in6_addr src; + struct sockaddr_in6 soca; scanner_t *scanner = scanner_p; /* Throttling related variables */ static int so_sndbuf = -1; // socket send buffer static int init = -1; - int *udpv6soc = &(scanner->udpv6soc); - int soc; - struct in6_addr first; - struct in6_addr last; - u_char packet[sizeof (struct ip6_hdr) + sizeof (struct icmp6_hdr)]; struct ip6_hdr *ip = (struct ip6_hdr *) packet; + int soc = scanner->icmpv6soc; struct icmp6_hdr *icmp = (struct icmp6_hdr *) (packet + sizeof (struct ip6_hdr)); - /* Get source address for TCP header. */ - gvm_cidr6_block_ips(net, &first, &last); - error = get_source_addr_v6 (udpv6soc, &first, &src); - if (error) - { - char destination_str[INET_ADDRSTRLEN]; - inet_ntop (AF_INET6, (const void *) &first, destination_str, - INET_ADDRSTRLEN); - g_debug ("%s: Destination: %s. %s", __func__, destination_str, - str_boreas_error (error)); - return; - } - memset (packet, 0, sizeof (packet)); /* IPv6 */ ip->ip6_flow = htonl ((6 << 28) | (0 << 20) | 0); ip->ip6_plen = htons (8); // ICMP6_HDRLEN ip->ip6_nxt= IPPROTO_ICMPV6; ip->ip6_hops = 255; // max value + ip->ip6_src = scanner->ipv6_net->src; inet_pton (AF_INET6, "FF02::1", &ip->ip6_dst); - ip->ip6_src = src; /* ICMP */ icmp->icmp6_type = ICMP6_ECHO_REQUEST; @@ -376,12 +357,7 @@ send_icmp_v6_multicast (gpointer scanner_p, const char *net) in_cksum((unsigned short *) &pseudoheader, sizeof(packet)); } - int opt_on = 1; - soc = socket (AF_INET6, SOCK_RAW, IPPROTO_RAW); - setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on, - sizeof (opt_on)); - - /* Get size of empty SO_SNDBUF */ + /* Get size of empty SO_SNDBUF */ if (init == -1) { if (get_so_sndbuf (soc, &so_sndbuf) == 0) @@ -391,19 +367,10 @@ send_icmp_v6_multicast (gpointer scanner_p, const char *net) /* Throttle speed if needed */ throttle (soc, so_sndbuf); - // Enable multicast - setsockopt (soc, SOL_SOCKET, SO_BROADCAST, &opt_on, sizeof (opt_on)); - - // source - memset (&socs, 0, sizeof (socs)); - socs.sin6_family = AF_INET6; - socs.sin6_addr = ip->ip6_src; // destination socket memset (&soca, 0, sizeof (soca)); soca.sin6_family = AF_INET6; soca.sin6_addr = ip->ip6_dst; - // to set the source address - bind(soc, (struct sockaddr *) &socs, sizeof(socs)); /* ICMP6_HDRLEN(8) IP6_HDRLEN(40) */ if (sendto (soc, (const void *) ip, 40 + 8, 0, diff --git a/boreas/ping.h b/boreas/ping.h index 44dc1b852..1ce1e850f 100644 --- a/boreas/ping.h +++ b/boreas/ping.h @@ -14,6 +14,6 @@ void send_tcp (gpointer, gpointer, gpointer); void send_arp (gpointer, gpointer, gpointer); -void send_icmp_v6_multicast (gpointer, const char *); +void send_icmp_v6_multicast (gpointer); #endif /* not _GVM_BOREAS_PING_H */ diff --git a/boreas/sniffer.c b/boreas/sniffer.c index 1f274f9dc..6fddeded0 100644 --- a/boreas/sniffer.c +++ b/boreas/sniffer.c @@ -5,6 +5,7 @@ #include "sniffer.h" +#include "../base/networking.h" /* for range_t */ #include "alivedetection.h" #include "boreas_io.h" @@ -13,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -170,11 +172,16 @@ got_packet (u_char *user_data, g_debug ("%s: Failed to transform IP into string representation: %s", __func__, strerror (errno)); } + + /* Only put unique hosts on queue and in hash table. Use short circuit * evaluation to not add hosts to the hash table which are not in our * target list.*/ - if ((g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE) - && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str)))) + if (((scanner->host_discovery == 0) + && (g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE) + && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str)))) + || + (scanner->host_discovery && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))))) { /* handle max_scan_hosts related restrictions. */ handle_scan_restrictions (scanner, addr_str); @@ -283,7 +290,18 @@ start_sniffer_thread (scanner_t *scanner, pthread_t *sniffer_thread_id) { int err; - scanner->pcap_handle = open_live (NULL, FILTER_STR); + if (0) //scanner->host_discovery) + { + char filter[256]; + snprintf (filter, sizeof (filter), "ip6 and ip6[40]=129 and dst %s", + addr6_as_str(&(scanner->ipv6_net->src))); + scanner->pcap_handle = open_live (NULL, filter); + } + else + { + scanner->pcap_handle = open_live (NULL, FILTER_STR); + } + if (scanner->pcap_handle == NULL) { g_warning ("%s: Unable to open valid pcap handle.", __func__); diff --git a/boreas/util.c b/boreas/util.c index dc5025fa6..cae0d4c0c 100644 --- a/boreas/util.c +++ b/boreas/util.c @@ -6,6 +6,8 @@ #include "util.h" #include "../base/networking.h" /* for range_t */ +#include "alivedetection.h" +#include "boreas_error.h" #include #include @@ -534,6 +536,61 @@ set_socket (socket_type_t socket_type, int *scanner_socket) return error; } +boreas_error_t +set_udp6_socket (scanner_t *scanner) +{ + boreas_error_t error = NO_ERROR; + error = set_socket (UDPV6, &(scanner->udpv6soc)); + return error; +} + +boreas_error_t +init_ipv6_net_data (scanner_t *scanner, const char *net) +{ + + struct in6_addr first, last; + struct sockaddr_in6 socs; + int soc; + boreas_error_t error = NO_ERROR; + // IPv6 net data for host discovery + scanner->ipv6_net = g_malloc0 (sizeof (ipv6_net_data_t)); + scanner->ipv6_net->net = g_strdup(net); + + /* Get source address for IPv6 header. */ + gvm_cidr6_block_ips (scanner->ipv6_net->net, &first, &last); + + error = get_source_addr_v6 (&(scanner->udpv6soc), + &first, &(scanner->ipv6_net->src)); + if (error) + { + char destination_str[INET_ADDRSTRLEN]; + inet_ntop (AF_INET6, (const void *) &first, destination_str, + INET_ADDRSTRLEN); + printf ("%s: Destination: %s. %s", __func__, destination_str, + str_boreas_error (error)); + return BOREAS_INVALID_IPV6_NETWORK; + } + + int opt_on = 1; + soc = socket (AF_INET6, SOCK_RAW, IPPROTO_RAW); + setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on, + sizeof (opt_on)); + + // Enable multicast + setsockopt (soc, SOL_SOCKET, SO_BROADCAST, &opt_on, sizeof (opt_on)); + + // Create source address + memset (&socs, 0, sizeof (socs)); + socs.sin6_family = AF_INET6; + socs.sin6_addr = scanner->ipv6_net->src; + // and set the source address to the socket + bind(soc, (struct sockaddr *) &socs, sizeof(socs)); + scanner->icmpv6soc = soc; + + return error; +} + + /** * @brief Set all sockets needed for the chosen detection methods. * @@ -583,17 +640,6 @@ set_all_needed_sockets (scanner_t *scanner, alive_test_t alive_test) return error; } - if ((alive_test & 32)) - { - // Set UDP socket for getting the src address - error = set_socket (UDPV6, &(scanner->udpv6soc)); - if (error != 0) - return error; - error = set_socket (ICMPV6, &(scanner->icmpv6soc)); - if (error != 0) - return error; - } - return error; } diff --git a/boreas/util.h b/boreas/util.h index d0963c92c..a0cb1382f 100644 --- a/boreas/util.h +++ b/boreas/util.h @@ -28,6 +28,12 @@ void fill_ports_array (gpointer, gpointer); boreas_error_t set_all_needed_sockets (scanner_t *, alive_test_t); +boreas_error_t +set_udp6_socket (scanner_t *); + +boreas_error_t +init_ipv6_net_data (scanner_t *, const char *); + boreas_error_t close_all_needed_sockets (scanner_t *, alive_test_t); From a4c685a0fcf1830cee498674f9a6ebb9c55ec0f2 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Fri, 6 Mar 2026 08:58:21 -0300 Subject: [PATCH 03/11] format --- boreas/alivedetection.c | 2 +- boreas/alivedetection.h | 2 +- boreas/cli.c | 19 ++++++++----------- boreas/cli.h | 2 +- boreas/ping.c | 14 +++++++------- boreas/sniffer.c | 9 ++++----- boreas/util.c | 19 ++++++++----------- 7 files changed, 30 insertions(+), 37 deletions(-) diff --git a/boreas/alivedetection.c b/boreas/alivedetection.c index 395d7142b..f318f2f6a 100644 --- a/boreas/alivedetection.c +++ b/boreas/alivedetection.c @@ -464,7 +464,7 @@ alive_detection_free (void *error) g_free (scanner.hosts_data); g_free (scanner.ipv6_net->net); g_free (scanner.ipv6_net); - + /* Set error. */ *(boreas_error_t *) error = error_out; } diff --git a/boreas/alivedetection.h b/boreas/alivedetection.h index 9cb603ecb..baf56f50b 100644 --- a/boreas/alivedetection.h +++ b/boreas/alivedetection.h @@ -77,7 +77,7 @@ struct ipv6_net_data char *net; struct in6_addr src; }; - + /** * @brief The hosts_data struct holds the alive hosts and target hosts in * separate hashtables. diff --git a/boreas/cli.c b/boreas/cli.c index 27b1eceb5..8555327d3 100644 --- a/boreas/cli.c +++ b/boreas/cli.c @@ -16,9 +16,9 @@ #include #include +#include #include #include -#include #undef G_LOG_DOMAIN /** @@ -101,11 +101,11 @@ init_cli_for_host_discovery (scanner_t *scanner, const char *net, return error; } - error = init_ipv6_net_data(scanner, net); + error = init_ipv6_net_data (scanner, net); if (error != 0) { - printf ("%s:Not possible to initialize data: %s", - __func__, str_boreas_error (error)); + printf ("%s:Not possible to initialize data: %s", __func__, + str_boreas_error (error)); return error; } @@ -258,7 +258,6 @@ run_cli_extended (gvm_hosts_t *hosts, alive_test_t alive_test, return NO_ERROR; } - /** * @brief * @@ -277,16 +276,14 @@ run_cli_for_ipv6_network (const char *net) boreas_error_t free_err; int print_results = 1; - if (net == NULL || gvm_get_host_type(net) != HOST_TYPE_CIDR6_BLOCK) + if (net == NULL || gvm_get_host_type (net) != HOST_TYPE_CIDR6_BLOCK) return BOREAS_INVALID_IPV6_NETWORK; - if (gvm_cidr6_get_block (net, &block) < 0 || - gvm_cidr6_get_ip (net, &target) < 0) + if (gvm_cidr6_get_block (net, &block) < 0 + || gvm_cidr6_get_ip (net, &target) < 0) return BOREAS_INVALID_IPV6_NETWORK; - init_err = - init_cli_for_host_discovery (&scanner, net, - print_results); + init_err = init_cli_for_host_discovery (&scanner, net, print_results); if (init_err) { printf ("Error initializing scanner.\n"); diff --git a/boreas/cli.h b/boreas/cli.h index 6ec3bc184..754cf2a6b 100644 --- a/boreas/cli.h +++ b/boreas/cli.h @@ -19,7 +19,7 @@ run_cli (gvm_hosts_t *, alive_test_t, const gchar *); boreas_error_t run_cli_for_ipv6_network (const char *); - boreas_error_t +boreas_error_t is_host_alive (const char *, int *); #endif /* not _GVM_BOREAS_CLI_H */ diff --git a/boreas/ping.c b/boreas/ping.c index 04ce40b86..fc907b737 100644 --- a/boreas/ping.c +++ b/boreas/ping.c @@ -5,8 +5,8 @@ #include "ping.h" -#include "../base/prefs.h" /* for prefs_get() */ #include "../base/networking.h" +#include "../base/prefs.h" /* for prefs_get() */ #include "arp.h" #include "util.h" @@ -330,7 +330,7 @@ send_icmp_v6_multicast (gpointer scanner_p) /* IPv6 */ ip->ip6_flow = htonl ((6 << 28) | (0 << 20) | 0); ip->ip6_plen = htons (8); // ICMP6_HDRLEN - ip->ip6_nxt= IPPROTO_ICMPV6; + ip->ip6_nxt = IPPROTO_ICMPV6; ip->ip6_hops = 255; // max value ip->ip6_src = scanner->ipv6_net->src; inet_pton (AF_INET6, "FF02::1", &ip->ip6_dst); @@ -350,14 +350,14 @@ send_icmp_v6_multicast (gpointer scanner_p) memcpy (&pseudoheader.d6addr, &ip->ip6_dst, sizeof (struct in6_addr)); pseudoheader.protocol = IPPROTO_ICMPV6; - pseudoheader.length = htons(8); + pseudoheader.length = htons (8); memcpy ((char *) &pseudoheader.icmpheader, (char *) icmp, sizeof (struct icmp6_hdr)); icmp->icmp6_cksum = - in_cksum((unsigned short *) &pseudoheader, sizeof(packet)); + in_cksum ((unsigned short *) &pseudoheader, sizeof (packet)); } - /* Get size of empty SO_SNDBUF */ + /* Get size of empty SO_SNDBUF */ if (init == -1) { if (get_so_sndbuf (soc, &so_sndbuf) == 0) @@ -373,8 +373,8 @@ send_icmp_v6_multicast (gpointer scanner_p) soca.sin6_addr = ip->ip6_dst; /* ICMP6_HDRLEN(8) IP6_HDRLEN(40) */ - if (sendto (soc, (const void *) ip, 40 + 8, 0, - (struct sockaddr *) &soca, sizeof (struct sockaddr_in6)) + if (sendto (soc, (const void *) ip, 40 + 8, 0, (struct sockaddr *) &soca, + sizeof (struct sockaddr_in6)) < 0) { g_debug ("%s: sendto(): %s", __func__, strerror (errno)); diff --git a/boreas/sniffer.c b/boreas/sniffer.c index 6fddeded0..edda932bd 100644 --- a/boreas/sniffer.c +++ b/boreas/sniffer.c @@ -173,15 +173,14 @@ got_packet (u_char *user_data, __func__, strerror (errno)); } - /* Only put unique hosts on queue and in hash table. Use short circuit * evaluation to not add hosts to the hash table which are not in our * target list.*/ if (((scanner->host_discovery == 0) && (g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE) && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str)))) - || - (scanner->host_discovery && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))))) + || (scanner->host_discovery + && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))))) { /* handle max_scan_hosts related restrictions. */ handle_scan_restrictions (scanner, addr_str); @@ -290,11 +289,11 @@ start_sniffer_thread (scanner_t *scanner, pthread_t *sniffer_thread_id) { int err; - if (0) //scanner->host_discovery) + if (0) // scanner->host_discovery) { char filter[256]; snprintf (filter, sizeof (filter), "ip6 and ip6[40]=129 and dst %s", - addr6_as_str(&(scanner->ipv6_net->src))); + addr6_as_str (&(scanner->ipv6_net->src))); scanner->pcap_handle = open_live (NULL, filter); } else diff --git a/boreas/util.c b/boreas/util.c index cae0d4c0c..a754f41d4 100644 --- a/boreas/util.c +++ b/boreas/util.c @@ -159,7 +159,7 @@ get_source_addr_v6 (int *udpv6soc, struct in6_addr *dst, struct in6_addr *src) sock_len = sizeof (storage); if (connect (*udpv6soc, (const struct sockaddr *) &storage, sock_len) < 0) { - g_warning("%s: connect() on udpv6soc failed: %s %d", __func__, + g_warning ("%s: connect() on udpv6soc failed: %s %d", __func__, strerror (errno), errno); /* State of the socket is unspecified. Close the socket and create a new * one. */ @@ -547,20 +547,19 @@ set_udp6_socket (scanner_t *scanner) boreas_error_t init_ipv6_net_data (scanner_t *scanner, const char *net) { - struct in6_addr first, last; - struct sockaddr_in6 socs; + struct sockaddr_in6 socs; int soc; boreas_error_t error = NO_ERROR; // IPv6 net data for host discovery scanner->ipv6_net = g_malloc0 (sizeof (ipv6_net_data_t)); - scanner->ipv6_net->net = g_strdup(net); + scanner->ipv6_net->net = g_strdup (net); /* Get source address for IPv6 header. */ gvm_cidr6_block_ips (scanner->ipv6_net->net, &first, &last); - error = get_source_addr_v6 (&(scanner->udpv6soc), - &first, &(scanner->ipv6_net->src)); + error = get_source_addr_v6 (&(scanner->udpv6soc), &first, + &(scanner->ipv6_net->src)); if (error) { char destination_str[INET_ADDRSTRLEN]; @@ -573,8 +572,7 @@ init_ipv6_net_data (scanner_t *scanner, const char *net) int opt_on = 1; soc = socket (AF_INET6, SOCK_RAW, IPPROTO_RAW); - setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on, - sizeof (opt_on)); + setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on, sizeof (opt_on)); // Enable multicast setsockopt (soc, SOL_SOCKET, SO_BROADCAST, &opt_on, sizeof (opt_on)); @@ -583,14 +581,13 @@ init_ipv6_net_data (scanner_t *scanner, const char *net) memset (&socs, 0, sizeof (socs)); socs.sin6_family = AF_INET6; socs.sin6_addr = scanner->ipv6_net->src; - // and set the source address to the socket - bind(soc, (struct sockaddr *) &socs, sizeof(socs)); + // and set the source address to the socket + bind (soc, (struct sockaddr *) &socs, sizeof (socs)); scanner->icmpv6soc = soc; return error; } - /** * @brief Set all sockets needed for the chosen detection methods. * From fd7980923cf37afe64627f217ef74476bd94c097 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Mon, 9 Mar 2026 08:18:27 -0300 Subject: [PATCH 04/11] fix host count --- boreas/cli.c | 7 ++++--- boreas/sniffer.c | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/boreas/cli.c b/boreas/cli.c index 8555327d3..61aded9c8 100644 --- a/boreas/cli.c +++ b/boreas/cli.c @@ -205,8 +205,12 @@ run_cli_scan (scanner_t *scanner, alive_test_t alive_test) stop_sniffer_thread (scanner, sniffer_thread_id); + if (scanner->host_discovery) + number_of_targets = g_hash_table_size (scanner->hosts_data->targethosts); + number_of_dead_hosts = count_difference (scanner->hosts_data->targethosts, scanner->hosts_data->alivehosts); + gettimeofday (&end_time, NULL); if (scanner->print_results == 1) printf ("Alive scan finished in %ld seconds: %d alive hosts of %d.\n", @@ -290,9 +294,6 @@ run_cli_for_ipv6_network (const char *net) return init_err; } - send_icmp_v6_multicast (&scanner); - wait_until_so_sndbuf_empty ((&scanner)->icmpv6soc, 10); - run_err = run_cli_scan (&scanner, ALIVE_TEST_IPV6_HOST_DISCOVERY); if (run_err) { diff --git a/boreas/sniffer.c b/boreas/sniffer.c index edda932bd..95879588b 100644 --- a/boreas/sniffer.c +++ b/boreas/sniffer.c @@ -179,8 +179,9 @@ got_packet (u_char *user_data, if (((scanner->host_discovery == 0) && (g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE) && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str)))) - || (scanner->host_discovery - && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))))) + || ((scanner->host_discovery == 1) + && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))) + && (g_hash_table_add (hosts_data->targethosts, g_strdup (addr_str))) )) { /* handle max_scan_hosts related restrictions. */ handle_scan_restrictions (scanner, addr_str); From 388d6e3c779d36c8253fa7b11ffd7a360c35b820 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Wed, 11 Mar 2026 13:44:50 -0300 Subject: [PATCH 05/11] return found host list --- boreas/alivedetection.c | 2 +- boreas/cli.c | 19 ++++++++++++++++++- boreas/cli.h | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/boreas/alivedetection.c b/boreas/alivedetection.c index f318f2f6a..83b772e4f 100644 --- a/boreas/alivedetection.c +++ b/boreas/alivedetection.c @@ -462,7 +462,7 @@ alive_detection_free (void *error) * gvm_host_t are freed by caller of start_alive_detection()! */ g_hash_table_destroy (scanner.hosts_data->targethosts); g_free (scanner.hosts_data); - g_free (scanner.ipv6_net->net); + g_free (&(scanner.ipv6_net)->net); g_free (scanner.ipv6_net); /* Set error. */ diff --git a/boreas/cli.c b/boreas/cli.c index 61aded9c8..e87a4da24 100644 --- a/boreas/cli.c +++ b/boreas/cli.c @@ -262,15 +262,26 @@ run_cli_extended (gvm_hosts_t *hosts, alive_test_t alive_test, return NO_ERROR; } +static void +create_host_list (gpointer key, gpointer value, gpointer *userdata) +{ + (void) value; + GString *host_str = (GString *) *userdata; + g_string_append (host_str, key); + g_string_append (host_str, ","); + + +} /** * @brief * * @param[in] net IPv6 network + * @param[out] hosts_found Discovered alive hosts in comma separated list * * @return NO_ERROR (0) on success, boreas_error_t on error. */ boreas_error_t -run_cli_for_ipv6_network (const char *net) +run_cli_for_ipv6_network (const char *net, char **hosts_found ) { unsigned int block; struct in6_addr target; @@ -300,7 +311,13 @@ run_cli_for_ipv6_network (const char *net) printf ("Error while running the scan.\n"); return run_err; } + + GString *host_str = g_string_new(""); + g_hash_table_foreach (scanner.hosts_data->alivehosts, (GHFunc) create_host_list, (gpointer) &host_str); + *hosts_found = g_strdup (host_str->str); + g_string_free (host_str, TRUE); + free_err = free_cli (&scanner, ALIVE_TEST_IPV6_HOST_DISCOVERY); if (free_err) { diff --git a/boreas/cli.h b/boreas/cli.h index 754cf2a6b..717c31efd 100644 --- a/boreas/cli.h +++ b/boreas/cli.h @@ -17,7 +17,7 @@ boreas_error_t run_cli (gvm_hosts_t *, alive_test_t, const gchar *); boreas_error_t -run_cli_for_ipv6_network (const char *); +run_cli_for_ipv6_network (const char *, char **); boreas_error_t is_host_alive (const char *, int *); From 25171910a4527d5554339c1e901c4e945d2435ef Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Thu, 12 Mar 2026 15:09:21 -0300 Subject: [PATCH 06/11] Add feature macro for backward compatibility --- base/hosts.c | 4 ++-- base/hosts.h | 2 +- boreas/cli.c | 24 ++++++++++++------------ boreas/cli.h | 4 +++- boreas/sniffer.c | 2 +- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/base/hosts.c b/base/hosts.c index 02a507a60..dfd03fab7 100644 --- a/base/hosts.c +++ b/base/hosts.c @@ -509,7 +509,6 @@ gvm_is_cidr6_block (const char *str) return is_cidr6_block (str); } - /** * @brief Gets the network block value from a CIDR-expressed block string. * For "192.168.1.1/24" it is 24. @@ -652,7 +651,8 @@ cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) } int -gvm_cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) +gvm_cidr6_block_ips (const char *str, struct in6_addr *first, + struct in6_addr *last) { return cidr6_block_ips (str, first, last); } diff --git a/base/hosts.h b/base/hosts.h index a0604336e..95a8d1b1e 100644 --- a/base/hosts.h +++ b/base/hosts.h @@ -219,6 +219,6 @@ gvm_cidr6_get_ip (const char *, struct in6_addr *); int gvm_cidr6_block_ips (const char *str, struct in6_addr *first, - struct in6_addr *last); + struct in6_addr *last); #endif /* not _GVM_BASE_HOSTS_H */ diff --git a/boreas/cli.c b/boreas/cli.c index e87a4da24..7715c6220 100644 --- a/boreas/cli.c +++ b/boreas/cli.c @@ -269,8 +269,6 @@ create_host_list (gpointer key, gpointer value, gpointer *userdata) GString *host_str = (GString *) *userdata; g_string_append (host_str, key); g_string_append (host_str, ","); - - } /** * @brief @@ -281,7 +279,8 @@ create_host_list (gpointer key, gpointer value, gpointer *userdata) * @return NO_ERROR (0) on success, boreas_error_t on error. */ boreas_error_t -run_cli_for_ipv6_network (const char *net, char **hosts_found ) +run_cli_for_ipv6_network (const char *net, char **hosts_found, + int print_results) { unsigned int block; struct in6_addr target; @@ -289,7 +288,6 @@ run_cli_for_ipv6_network (const char *net, char **hosts_found ) boreas_error_t init_err; boreas_error_t run_err; boreas_error_t free_err; - int print_results = 1; if (net == NULL || gvm_get_host_type (net) != HOST_TYPE_CIDR6_BLOCK) return BOREAS_INVALID_IPV6_NETWORK; @@ -311,13 +309,17 @@ run_cli_for_ipv6_network (const char *net, char **hosts_found ) printf ("Error while running the scan.\n"); return run_err; } - - GString *host_str = g_string_new(""); - g_hash_table_foreach (scanner.hosts_data->alivehosts, (GHFunc) create_host_list, (gpointer) &host_str); - *hosts_found = g_strdup (host_str->str); - g_string_free (host_str, TRUE); - + if (hosts_found != NULL) + { + GString *host_str = g_string_new (""); + g_hash_table_foreach (scanner.hosts_data->alivehosts, + (GHFunc) create_host_list, (gpointer) &host_str); + + *hosts_found = g_strdup (host_str->str); + g_string_free (host_str, TRUE); + } + free_err = free_cli (&scanner, ALIVE_TEST_IPV6_HOST_DISCOVERY); if (free_err) { @@ -326,8 +328,6 @@ run_cli_for_ipv6_network (const char *net, char **hosts_found ) } return NO_ERROR; - - return 0; } /** diff --git a/boreas/cli.h b/boreas/cli.h index 717c31efd..ea1d34ab6 100644 --- a/boreas/cli.h +++ b/boreas/cli.h @@ -9,6 +9,8 @@ #include "alivedetection.h" #include "boreas_error.h" +#define FEATURE_HOST_DISCOVERY_IPV6 + boreas_error_t run_cli_extended (gvm_hosts_t *, alive_test_t, const gchar *, const unsigned int); @@ -17,7 +19,7 @@ boreas_error_t run_cli (gvm_hosts_t *, alive_test_t, const gchar *); boreas_error_t -run_cli_for_ipv6_network (const char *, char **); +run_cli_for_ipv6_network (const char *, char **, int); boreas_error_t is_host_alive (const char *, int *); diff --git a/boreas/sniffer.c b/boreas/sniffer.c index 95879588b..acdf6b7bd 100644 --- a/boreas/sniffer.c +++ b/boreas/sniffer.c @@ -181,7 +181,7 @@ got_packet (u_char *user_data, && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str)))) || ((scanner->host_discovery == 1) && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))) - && (g_hash_table_add (hosts_data->targethosts, g_strdup (addr_str))) )) + && (g_hash_table_add (hosts_data->targethosts, g_strdup (addr_str))))) { /* handle max_scan_hosts related restrictions. */ handle_scan_restrictions (scanner, addr_str); From dc2143f5c31b2cc1409e0a8e4cb1b24140a11c02 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Mon, 16 Mar 2026 08:53:08 -0300 Subject: [PATCH 07/11] fix unit test --- boreas/util_tests.c | 1 + 1 file changed, 1 insertion(+) diff --git a/boreas/util_tests.c b/boreas/util_tests.c index 5a6bff78d..e5430e6a5 100644 --- a/boreas/util_tests.c +++ b/boreas/util_tests.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ +#include "boreas_error.c" #include "util.c" #include From fac05221ae06924db9324094e24bc7c956a547a7 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Thu, 19 Mar 2026 08:54:01 -0300 Subject: [PATCH 08/11] apply suggestions --- base/hosts.c | 50 +++++++++++------------------------------ boreas/alivedetection.c | 2 -- boreas/boreas_error.h | 1 + boreas/cli.c | 22 ++++++++++++++---- boreas/sniffer.c | 2 +- boreas/util.c | 30 ++++++++++++++++++++++--- 6 files changed, 60 insertions(+), 47 deletions(-) diff --git a/base/hosts.c b/base/hosts.c index dfd03fab7..3ec5d17fd 100644 --- a/base/hosts.c +++ b/base/hosts.c @@ -466,8 +466,8 @@ is_hostname (const char *str) * * @return 1 if valid IPv6 CIDR-expressed block, 0 otherwise. */ -static int -is_cidr6_block (const char *str) +int +gvm_is_cidr6_block (const char *str) { long block; char *addr6_str, *block_str, *p; @@ -503,12 +503,6 @@ is_cidr6_block (const char *str) return 1; } -int -gvm_is_cidr6_block (const char *str) -{ - return is_cidr6_block (str); -} - /** * @brief Gets the network block value from a CIDR-expressed block string. * For "192.168.1.1/24" it is 24. @@ -518,8 +512,8 @@ gvm_is_cidr6_block (const char *str) * * @return -1 if error, 0 otherwise. */ -static int -cidr6_get_block (const char *str, unsigned int *block) +int +gvm_cidr6_get_block (const char *str, unsigned int *block) { if (str == NULL || block == NULL) return -1; @@ -530,12 +524,6 @@ cidr6_get_block (const char *str, unsigned int *block) return 0; } -int -gvm_cidr6_get_block (const char *str, unsigned int *block) -{ - return cidr6_get_block (str, block); -} - /** * @brief Gets the IPv4 value from a CIDR-expressed block. * eg. For "192.168.1.10/24" it is "192.168.1.10". @@ -545,8 +533,8 @@ gvm_cidr6_get_block (const char *str, unsigned int *block) * * @return -1 if error, 0 otherwise. */ -static int -cidr6_get_ip (const char *str, struct in6_addr *addr6) +int +gvm_cidr6_get_ip (const char *str, struct in6_addr *addr6) { gchar *addr6_str, *tmp; @@ -569,12 +557,6 @@ cidr6_get_ip (const char *str, struct in6_addr *addr6) return 0; } -int -gvm_cidr6_get_ip (const char *str, struct in6_addr *addr6) -{ - return cidr6_get_ip (str, addr6); -} - /** * @brief Gets the first and last usable IPv4 addresses from a CIDR-expressed * block. eg. "192.168.1.0/24 would give 192.168.1.1 as first and 192.168.1.254 @@ -586,8 +568,9 @@ gvm_cidr6_get_ip (const char *str, struct in6_addr *addr6) * * @return -1 if error, 0 else. */ -static int -cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) +int +gvm_cidr6_block_ips (const char *str, struct in6_addr *first, + struct in6_addr *last) { unsigned int block; int i, j; @@ -596,9 +579,9 @@ cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) return -1; /* Get IP and block values. */ - if (cidr6_get_block (str, &block) == -1) + if (gvm_cidr6_get_block (str, &block) == -1) return -1; - if (cidr6_get_ip (str, first) == -1) + if (gvm_cidr6_get_ip (str, first) == -1) return -1; memcpy (&last->s6_addr, &first->s6_addr, 16); @@ -650,13 +633,6 @@ cidr6_block_ips (const char *str, struct in6_addr *first, struct in6_addr *last) return 0; } -int -gvm_cidr6_block_ips (const char *str, struct in6_addr *first, - struct in6_addr *last) -{ - return cidr6_block_ips (str, first, last); -} - /** * @brief Checks if a buffer points to a valid long IPv6 range-expressed * network. "::fee5-::1:530" is valid. @@ -869,7 +845,7 @@ gvm_get_host_type (const gchar *str_stripped) return HOST_TYPE_RANGE_LONG; /* Check for regular IPv6 CIDR-expressed block like "2620:0:2d0:200::7/120" */ - if (is_cidr6_block (str_stripped)) + if (gvm_is_cidr6_block (str_stripped)) return HOST_TYPE_CIDR6_BLOCK; /* Check for short range-expressed networks "::1-ef12" */ @@ -1241,7 +1217,7 @@ gvm_hosts_new_with_max (const gchar *hosts_str, unsigned int max_hosts) struct in6_addr *); if (host_type == HOST_TYPE_CIDR6_BLOCK) - ips_func = cidr6_block_ips; + ips_func = gvm_cidr6_block_ips; else if (host_type == HOST_TYPE_RANGE6_SHORT) ips_func = short_range6_network_ips; else diff --git a/boreas/alivedetection.c b/boreas/alivedetection.c index 83b772e4f..5cd25a69f 100644 --- a/boreas/alivedetection.c +++ b/boreas/alivedetection.c @@ -462,8 +462,6 @@ alive_detection_free (void *error) * gvm_host_t are freed by caller of start_alive_detection()! */ g_hash_table_destroy (scanner.hosts_data->targethosts); g_free (scanner.hosts_data); - g_free (&(scanner.ipv6_net)->net); - g_free (scanner.ipv6_net); /* Set error. */ *(boreas_error_t *) error = error_out; diff --git a/boreas/boreas_error.h b/boreas/boreas_error.h index 1fd416095..ff82d644b 100644 --- a/boreas/boreas_error.h +++ b/boreas/boreas_error.h @@ -13,6 +13,7 @@ typedef enum { BOREAS_OPENING_SOCKET_FAILED = -100, BOREAS_SETTING_SOCKET_OPTION_FAILED, + BOREAS_BIND_SOCKET_FAILED, BOREAS_NO_VALID_ALIVE_TEST_SPECIFIED, BOREAS_CLEANUP_ERROR, BOREAS_NO_SRC_ADDR_FOUND, diff --git a/boreas/cli.c b/boreas/cli.c index 7715c6220..f64abd3c2 100644 --- a/boreas/cli.c +++ b/boreas/cli.c @@ -104,7 +104,7 @@ init_cli_for_host_discovery (scanner_t *scanner, const char *net, error = init_ipv6_net_data (scanner, net); if (error != 0) { - printf ("%s:Not possible to initialize data: %s", __func__, + printf ("%s: Not possible to initialize data: %s", __func__, str_boreas_error (error)); return error; } @@ -130,6 +130,12 @@ free_cli (scanner_t *scanner, alive_test_t alive_test) g_hash_table_destroy (scanner->hosts_data->targethosts); g_free (scanner->hosts_data); + if (alive_test & ALIVE_TEST_IPV6_HOST_DISCOVERY) + { + g_free (scanner->ipv6_net->net); + g_free (scanner->ipv6_net); + } + return close_err; } @@ -262,6 +268,13 @@ run_cli_extended (gvm_hosts_t *hosts, alive_test_t alive_test, return NO_ERROR; } +/** + * @brief GHFunc helper function to create a comma separated list of host + * + * @param[in] key host + * @param [in] value Not used + * @param[in/out] userdata comma separated list where new keys are appended to. + */ static void create_host_list (gpointer key, gpointer value, gpointer *userdata) { @@ -270,8 +283,9 @@ create_host_list (gpointer key, gpointer value, gpointer *userdata) g_string_append (host_str, key); g_string_append (host_str, ","); } + /** - * @brief + * @brief Runs a host discovery for large ipv6 network * * @param[in] net IPv6 network * @param[out] hosts_found Discovered alive hosts in comma separated list @@ -316,14 +330,14 @@ run_cli_for_ipv6_network (const char *net, char **hosts_found, g_hash_table_foreach (scanner.hosts_data->alivehosts, (GHFunc) create_host_list, (gpointer) &host_str); - *hosts_found = g_strdup (host_str->str); - g_string_free (host_str, TRUE); + *hosts_found = g_string_free (host_str, FALSE); } free_err = free_cli (&scanner, ALIVE_TEST_IPV6_HOST_DISCOVERY); if (free_err) { printf ("Error freeing scan data.\n"); + g_free (*hosts_found); return free_err; } diff --git a/boreas/sniffer.c b/boreas/sniffer.c index acdf6b7bd..f1e03c90d 100644 --- a/boreas/sniffer.c +++ b/boreas/sniffer.c @@ -290,7 +290,7 @@ start_sniffer_thread (scanner_t *scanner, pthread_t *sniffer_thread_id) { int err; - if (0) // scanner->host_discovery) + if (scanner->host_discovery) { char filter[256]; snprintf (filter, sizeof (filter), "ip6 and ip6[40]=129 and dst %s", diff --git a/boreas/util.c b/boreas/util.c index a754f41d4..4add9dff1 100644 --- a/boreas/util.c +++ b/boreas/util.c @@ -572,17 +572,41 @@ init_ipv6_net_data (scanner_t *scanner, const char *net) int opt_on = 1; soc = socket (AF_INET6, SOCK_RAW, IPPROTO_RAW); - setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on, sizeof (opt_on)); + if (soc < 0) + { + g_warning ("%s: failed to open ICPMV6 socket: %s", __func__, + strerror (errno)); + error = BOREAS_OPENING_SOCKET_FAILED; + } + + if (setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on, + sizeof (opt_on)) + < 0) + { + g_warning ("%s: failed to set socket option IP_HDRINCL: %s", __func__, + strerror (errno)); + error = BOREAS_SETTING_SOCKET_OPTION_FAILED; + } // Enable multicast - setsockopt (soc, SOL_SOCKET, SO_BROADCAST, &opt_on, sizeof (opt_on)); + if (!error) + { + error = set_broadcast (soc); + if (error != 0) + return error; + } // Create source address memset (&socs, 0, sizeof (socs)); socs.sin6_family = AF_INET6; socs.sin6_addr = scanner->ipv6_net->src; // and set the source address to the socket - bind (soc, (struct sockaddr *) &socs, sizeof (socs)); + if (bind (soc, (struct sockaddr *) &socs, sizeof (socs)) < 0) + { + g_warning ("%s: failed to bind socket to source address: %s", __func__, + strerror (errno)); + return BOREAS_BIND_SOCKET_FAILED; + } scanner->icmpv6soc = soc; return error; From e19d4cd1816de8358c7080f7c7b8dbd96a07b8f7 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Thu, 19 Mar 2026 13:02:44 -0300 Subject: [PATCH 09/11] fix filter to only get those ips which belong to the subnet --- boreas/sniffer.c | 2 ++ boreas/util.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ boreas/util.h | 3 +++ 3 files changed, 53 insertions(+) diff --git a/boreas/sniffer.c b/boreas/sniffer.c index f1e03c90d..51ff38368 100644 --- a/boreas/sniffer.c +++ b/boreas/sniffer.c @@ -8,6 +8,7 @@ #include "../base/networking.h" /* for range_t */ #include "alivedetection.h" #include "boreas_io.h" +#include "util.h" #include #include @@ -180,6 +181,7 @@ got_packet (u_char *user_data, && (g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE) && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str)))) || ((scanner->host_discovery == 1) + && (cidr6block_contains (scanner->ipv6_net->net, addr_str) > 0) && (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))) && (g_hash_table_add (hosts_data->targethosts, g_strdup (addr_str))))) { diff --git a/boreas/util.c b/boreas/util.c index 4add9dff1..23de0f6ba 100644 --- a/boreas/util.c +++ b/boreas/util.c @@ -735,3 +735,51 @@ wait_until_so_sndbuf_empty (int soc, int timeout) usleep (100000); } } + +/** + * @brief Check if the address is contained in the CIDR block + * + * @param cidr a valid IPv6 CIDR-expressed block + * @param address IPv6 address to check if it is contained. + * + * @return 1 if it is contained, 0 if not. Boreas error type on error; + */ +int +cidr6block_contains (const char *cidr, const char *address) +{ + struct in6_addr net, ip; + unsigned int prefix_len = 0; + + if (gvm_cidr6_get_ip (cidr, &net) || gvm_cidr6_get_block (cidr, &prefix_len)) + + g_debug ("Checking if %s belongs to the CIDR block %s", address, cidr); + + if (inet_pton (AF_INET6, address, &ip) != 1) + return -1; + + const uint8_t *addr_bytes = (const uint8_t *) &ip; + const uint8_t *net_bytes = (const uint8_t *) &net; + + int bytes_to_compare = prefix_len / 8; + int bits_to_compare = prefix_len % 8; + + if (bytes_to_compare > 0) + { + if (memcmp (addr_bytes, net_bytes, bytes_to_compare) != 0) + { + return 0; + } + } + + if (bits_to_compare > 0) + { + uint8_t mask = 0xFF << (8 - bits_to_compare); + if ((addr_bytes[bytes_to_compare] & mask) + != (net_bytes[bytes_to_compare] & mask)) + { + return 0; + } + } + + return 1; // All network bits match +} diff --git a/boreas/util.h b/boreas/util.h index a0cb1382f..108542378 100644 --- a/boreas/util.h +++ b/boreas/util.h @@ -23,6 +23,9 @@ get_source_addr_v6 (int *, struct in6_addr *, struct in6_addr *); boreas_error_t get_source_addr_v4 (int *, struct in_addr *, struct in_addr *); +int +cidr6block_contains (const char *, const char *); + void fill_ports_array (gpointer, gpointer); boreas_error_t From a69ffc8d2e6f5149b3c63ab8989cf537ceef9d2d Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Thu, 19 Mar 2026 14:13:40 -0300 Subject: [PATCH 10/11] add test --- boreas/util_tests.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boreas/util_tests.c b/boreas/util_tests.c index e5430e6a5..b099896dd 100644 --- a/boreas/util_tests.c +++ b/boreas/util_tests.c @@ -233,6 +233,15 @@ Ensure (util, fill_ports_array) g_array_free (ports_garray, TRUE); } +Ensure (util, cidr6_contains_ip) +{ + assert_that (cidr6block_contains ("5858::/64", "5858::1"), is_equal_to (1)); + assert_that (cidr6block_contains ("5858::/64", "5858::ff"), is_equal_to (1)); + assert_that (cidr6block_contains ("5858::/120", "5858::ff"), is_equal_to (1)); + assert_that (cidr6block_contains ("5858::/120", "5858::252"), + is_equal_to (0)); +} + int main (int argc, char **argv) { @@ -248,6 +257,7 @@ main (int argc, char **argv) add_test_with_context (suite, util, set_socket); add_test_with_context (suite, util, get_source_addr_v4); add_test_with_context (suite, util, get_source_addr_v6); + add_test_with_context (suite, util, cidr6_contains_ip); if (argc > 1) ret = run_single_test (suite, argv[1], create_text_reporter ()); From e6e56c16c010440c812fa00c9401bf007357ab57 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Thu, 19 Mar 2026 14:51:39 -0300 Subject: [PATCH 11/11] fix leak and close socket --- boreas/cli.c | 3 ++- boreas/sniffer.c | 4 +++- boreas/util.c | 14 ++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/boreas/cli.c b/boreas/cli.c index f64abd3c2..f563c741a 100644 --- a/boreas/cli.c +++ b/boreas/cli.c @@ -337,7 +337,8 @@ run_cli_for_ipv6_network (const char *net, char **hosts_found, if (free_err) { printf ("Error freeing scan data.\n"); - g_free (*hosts_found); + if (hosts_found) + g_free (*hosts_found); return free_err; } diff --git a/boreas/sniffer.c b/boreas/sniffer.c index 51ff38368..f657f79c8 100644 --- a/boreas/sniffer.c +++ b/boreas/sniffer.c @@ -295,8 +295,10 @@ start_sniffer_thread (scanner_t *scanner, pthread_t *sniffer_thread_id) if (scanner->host_discovery) { char filter[256]; + char *addr = addr6_as_str (&(scanner->ipv6_net->src)); snprintf (filter, sizeof (filter), "ip6 and ip6[40]=129 and dst %s", - addr6_as_str (&(scanner->ipv6_net->src))); + addr); + g_free (addr); scanner->pcap_handle = open_live (NULL, filter); } else diff --git a/boreas/util.c b/boreas/util.c index 23de0f6ba..edc511f3b 100644 --- a/boreas/util.c +++ b/boreas/util.c @@ -576,7 +576,7 @@ init_ipv6_net_data (scanner_t *scanner, const char *net) { g_warning ("%s: failed to open ICPMV6 socket: %s", __func__, strerror (errno)); - error = BOREAS_OPENING_SOCKET_FAILED; + return BOREAS_OPENING_SOCKET_FAILED; } if (setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on, @@ -585,15 +585,16 @@ init_ipv6_net_data (scanner_t *scanner, const char *net) { g_warning ("%s: failed to set socket option IP_HDRINCL: %s", __func__, strerror (errno)); - error = BOREAS_SETTING_SOCKET_OPTION_FAILED; + close (soc); + return BOREAS_SETTING_SOCKET_OPTION_FAILED; } // Enable multicast - if (!error) + error = set_broadcast (soc); + if (error != 0) { - error = set_broadcast (soc); - if (error != 0) - return error; + close (soc); + return error; } // Create source address @@ -605,6 +606,7 @@ init_ipv6_net_data (scanner_t *scanner, const char *net) { g_warning ("%s: failed to bind socket to source address: %s", __func__, strerror (errno)); + close (soc); return BOREAS_BIND_SOCKET_FAILED; } scanner->icmpv6soc = soc;