tags 285316 + patch upstream ipv6 important
thank

Below is a patch for this problem. It should fix bug #294636 as well.

It might be a good idea to forward it upstream.

-- 
Rémi Denis-Courmont
http://www.simphalempin.com/home/
diff -ru ntp-4.2.0a+stable.orig/ntpdate/ntpdate.c ntp-4.2.0a+stable/ntpdate/ntpdate.c
--- ntp-4.2.0a+stable.orig/ntpdate/ntpdate.c	2005-02-17 22:11:09.665424200 +0100
+++ ntp-4.2.0a+stable/ntpdate/ntpdate.c	2005-02-17 22:17:33.604056656 +0100
@@ -1321,6 +1321,30 @@
 }
 
 
+/*
+ * 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 @@
 {
 	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 @@
 	}
 #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;
-
-		for (sp = sys_servers; sp->next_server != NULL;
-		     sp = sp->next_server) ;
-		sp->next_server = server;
+	/* 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;
+			}
+		}
 	}
+
+	freeaddrinfo(addrResult);
 }
 
 

Reply via email to