diff --git a/src/tools/dhcp-discover.c b/src/tools/dhcp-discover.c index 2579c78b6..4064235dc 100644 --- a/src/tools/dhcp-discover.c +++ b/src/tools/dhcp-discover.c @@ -49,8 +49,7 @@ // Maximum time we wait for incoming DHCPOFFERs // (seconds) -#define DHCPOFFER_TIMEOUT 6 -#define DHCPV6_TIMEOUT 4 +#define SCAN_TIMEOUT 6 // How many threads do we spawn at maximum? // This is also the limit for interfaces @@ -571,7 +570,7 @@ static void get_dhcp_offer(const int sock, const uint32_t xid, const char *iface time(&start_time); // receive as many responses as we can - while(time(¤t_time) && (current_time-start_time) < DHCPOFFER_TIMEOUT) + while(time(¤t_time) && (current_time-start_time) < SCAN_TIMEOUT) { memset(&source, 0, sizeof(source)); memset(&offer_packet, 0, sizeof(offer_packet)); @@ -675,10 +674,16 @@ static void get_dhcp_offer(const int sock, const uint32_t xid, const char *iface #endif } -static void *dhcp_discover_iface(void *args) +static void *dhcp_discover_iface_v4(void *args) { // Get interface details const char *iface = ((struct ifaddrs*)args)->ifa_name; + char *thread_name = malloc(strlen(iface) + 4); + sprintf(thread_name, "%s-v4", iface); + + // Set interface name as thread name + prctl(PR_SET_NAME, thread_name, 0, 0, 0); + free(thread_name); // Set interface name as thread name prctl(PR_SET_NAME, iface, 0, 0, 0); @@ -710,11 +715,24 @@ static void *dhcp_discover_iface(void *args) if(dhcp_socket > 0) close(dhcp_socket); + pthread_exit(NULL); +} + +static void *dhcp_discover_iface_v6(void *args) +{ + // Get interface details + const char *iface = ((struct ifaddrs*)args)->ifa_name; + char *thread_name = malloc(strlen(iface) + 4); + sprintf(thread_name, "%s-v6", iface); + + // Set interface name as thread name + prctl(PR_SET_NAME, thread_name, 0, 0, 0); + free(thread_name); + // Perform the same scan for DHCPv6 - const int responses = dhcpv6_discover_iface(iface, DHCPV6_TIMEOUT); - if(responses > -1) - printf("DHCPv6 packets received on %s%s%s: %i\n", - cli_bold(), iface, cli_normal(), responses); + const int responses = dhcpv6_discover_iface(iface, SCAN_TIMEOUT); + printf("RAs received on %s%s%s: %i\n", + cli_bold(), iface, cli_normal(), responses); pthread_exit(NULL); } @@ -741,12 +759,12 @@ int run_dhcp_discover(void) // Only print to terminal, disable log file log_ctrl(false, true); - printf("Scanning all your interfaces for DHCPv4 and DHCPv6 servers\n"); - printf("Timeout: %d + %d seconds\n", DHCPOFFER_TIMEOUT, DHCPV6_TIMEOUT); + printf("Scanning all your interfaces for DHCP servers and IPv6 routers\n"); + printf("Timeout: %d seconds\n", SCAN_TIMEOUT); // Get interface names for available interfaces on this machine // and launch a thread for each one - pthread_t scanthread[MAXTHREADS]; + pthread_t scanthread[2*MAXTHREADS]; pthread_attr_t attr; // Initialize thread attributes object with default attribute values pthread_attr_init(&attr); @@ -784,10 +802,19 @@ int run_dhcp_discover(void) continue; } - // Create a probing thread for this interface - if(pthread_create(&scanthread[tid], &attr, dhcp_discover_iface, tmp ) != 0) + // Create a DHCP probing thread for this interface + if(pthread_create(&scanthread[tid], &attr, dhcp_discover_iface_v4, tmp ) != 0) { - printf_locked("Unable to launch thread for interface %s, skipping...", + printf_locked("Unable to launch DHCP thread for interface %s, skipping...", + tmp->ifa_name); + tmp = tmp->ifa_next; + continue; + } + + // Create a RA probing thread for this interface + if(pthread_create(&scanthread[2*tid], &attr, dhcp_discover_iface_v6, tmp ) != 0) + { + printf_locked("Unable to launch RA thread for interface %s, skipping...", tmp->ifa_name); tmp = tmp->ifa_next; continue; @@ -803,7 +830,10 @@ int run_dhcp_discover(void) // Wait for all threads to join back with us for(tid--; tid > -1; tid--) + { pthread_join(scanthread[tid], NULL); + pthread_join(scanthread[2*tid], NULL); + } // Free linked-list of interfaces on this client freeifaddrs(addrs); diff --git a/src/tools/dhcpv6-discover.c b/src/tools/dhcpv6-discover.c index aed6b13cc..bbf729873 100644 --- a/src/tools/dhcpv6-discover.c +++ b/src/tools/dhcpv6-discover.c @@ -647,7 +647,7 @@ static ssize_t recv_adv(int fd, const struct sockaddr_in6 *tgt, const char *ifna unsigned responses = 0; // Get the current time and add the timeout - clock_gettime (CLOCK_MONOTONIC, &end); + clock_gettime(CLOCK_MONOTONIC, &end); end.tv_sec += timeout; // Receiving packets until timeout @@ -665,16 +665,21 @@ static ssize_t recv_adv(int fd, const struct sockaddr_in6 *tgt, const char *ifna if (val < 0) val = 0; } - // Wait for reply + // Wait for reply (retries on EINTR) struct pollfd pollfd = { .fd = fd, .events = POLLIN, .revents = 0 }; - val = poll(&pollfd, 1, val); + do { + val = poll(&pollfd, 1, val); + } while (val == -1 && errno == EINTR); // Check for errors - if (val < 0) + if(val < 0) + { + perror("Polling for ICMPv6 packet"); break; + } // Check for timeout - if (val == 0) + if(val == 0) return responses; // Received a packet @@ -721,7 +726,6 @@ static ssize_t recv_adv(int fd, const struct sockaddr_in6 *tgt, const char *ifna */ static int do_discoverv6(const int fd, const char *ifname, const unsigned int timeout) { - unsigned int retry = 3; struct sockaddr_in6 tgt = { 0 }; // Automatically close the socket on exec @@ -749,7 +753,10 @@ static int do_discoverv6(const int fd, const char *ifname, const unsigned int ti // Resolves target's IPv6 address const char *hostname = "ff02::2"; // All routers multicast address if(get_ipv6_by_name(hostname, ifname, &tgt) != 0) - goto error; + { + close(fd); + return -1; + } char s[INET6_ADDRSTRLEN] = { 0 }; inet_ntop (AF_INET6, &tgt.sin6_addr, s, sizeof (s)); @@ -762,39 +769,40 @@ static int do_discoverv6(const int fd, const char *ifname, const unsigned int ti // Build a Router Solicitation message const ssize_t plen = build_solicit(&packet); if(plen == -1) - goto error; + { + close(fd); + return -1; + } - while(retry > 0) + /* sends a Solitication */ + if(sendto(fd, &packet, plen, 0, + (const struct sockaddr *)&dst, + sizeof(dst)) != plen) { - /* sends a Solitication */ - if(sendto(fd, &packet, plen, 0, - (const struct sockaddr *)&dst, - sizeof(dst)) != plen) - { - perror("Sending ICMPv6 packet"); - goto error; - } - retry--; + perror("Sending ICMPv6 packet"); + close(fd); + return -1; + } - /* receives an Advertisement */ - const ssize_t val = recv_adv(fd, &tgt, ifname, timeout); - if(val > 0) - { - close(fd); - return val; - } -// else if(val == 0) // Timed out - if(val < 0) - goto error; + /* receives an Advertisement */ + const ssize_t val = recv_adv(fd, &tgt, ifname, timeout); + if(val > 0) + { + close(fd); + return val; + } +// else if(val == 0) // Timed out + if(val < 0) + { + // Error + perror("Receiving ICMPv6 packet"); + close(fd); + return -1; } - close(fd); // No DHCPv6 responses received - return 0; - -error: close(fd); - return -1; + return 0; } int dhcpv6_discover_iface(const char *ifname, const unsigned int timeout)