From: Harlan Stenn Date: Wed, 2 Mar 2005 21:18:07 +0000 (-0500) Subject: [Bug 389] Fix from Remi Demis-Courmont, via Loic Minier (http://bugs.debian.org/293793 X-Git-Tag: NTP_4_2_0B_RC1~11^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9114195231144bd6d3fd5b3cd87a1e75e7a79a12;p=thirdparty%2Fntp.git [Bug 389] Fix from Remi Demis-Courmont, via Loic Minier (http://bugs.debian.org/293793 bk: 42262d8fH2lVb1ZYI2YAIe5BLM-BqQ --- diff --git a/ntpdate/ntpdate.c b/ntpdate/ntpdate.c index 0408d7472..9ce701b04 100644 --- a/ntpdate/ntpdate.c +++ b/ntpdate/ntpdate.c @@ -1321,6 +1321,30 @@ clock_adjust(void) } +/* + * is_unreachable - check to see if we have a route to given destination + * (non-blocking). + */ +static int +is_reachable (struct sockaddr_storage *dst) +{ + SOCKET sockfd; + + sockfd = socket(dst->ss_family, SOCK_DGRAM, 0); + if (sockfd == -1) { + return 0; + } + + if(connect(sockfd, (struct sockaddr *)dst, SOCKLEN(dst))) { + closesocket(sockfd); + return 0; + } + closesocket(sockfd); + return 1; +} + + + /* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */ /* * addserver - determine a server's address and allocate a new structure @@ -1333,7 +1357,7 @@ addserver( { register struct server *server; /* Address infos structure to store result of getaddrinfo */ - struct addrinfo *addrResult; + struct addrinfo *addrResult, *ptr; /* Address infos structure to store hints for getaddrinfo */ struct addrinfo hints; /* Error variable for getaddrinfo */ @@ -1364,22 +1388,28 @@ addserver( } #endif - server = (struct server *)emalloc(sizeof(struct server)); - memset((char *)server, 0, sizeof(struct server)); - - /* For now we only get the first returned server of the addrinfo list */ - memset(&(server->srcadr), 0, sizeof(struct sockaddr_storage)); - memcpy(&(server->srcadr), addrResult->ai_addr, addrResult->ai_addrlen); - server->event_time = ++sys_numservers; - if (sys_servers == NULL) - sys_servers = server; - else { - struct server *sp; + /* We must get all returned server in case the first one fails */ + for (ptr = addrResult; ptr != NULL; ptr = ptr->ai_next) { + if (is_reachable ((struct sockaddr_storage *)ptr->ai_addr)) { + server = (struct server *)emalloc(sizeof(struct server)); + memset((char *)server, 0, sizeof(struct server)); + + memset(&(server->srcadr), 0, sizeof(struct sockaddr_storage)); + memcpy(&(server->srcadr), ptr->ai_addr, ptr->ai_addrlen); + server->event_time = ++sys_numservers; + if (sys_servers == NULL) + sys_servers = server; + else { + struct server *sp; - for (sp = sys_servers; sp->next_server != NULL; - sp = sp->next_server) ; - sp->next_server = server; + for (sp = sys_servers; sp->next_server != NULL; + sp = sp->next_server) ; + sp->next_server = server; + } + } } + + freeaddrinfo(addrResult); }