This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix resolver option rotate


Hi!

options rotate
in /etc/resolv.conf doesn't work, at least if RES_STAYOPEN is not set.
That's because res_nclose clears nsinit and on next res_send nsaddrs
array is reinitialized.
The following patch tries to fix this, by using nsmap array;
nsmap[X] = Y means that nsaddrs[X] corresponds to nsaddr_list[Y]
if Y < MAXNS, nsaddrs[X] is unused slot if Y == MAXNS and nsaddrs[X]
is an IPv6 address if Y == MAXNS + 1 (to speed things up, so that sock_eq
doesn't have to be called that often).
It also should prevent problems if res_state is initialized with some IPv6
nameservers and then some IPv4 are added in the public part of the
structure, such that sum of both is > MAXNS. Also it should close sockets
even if there are holes, such as if res_state is initialized with
IPv4, IPv4, IPv6 ns and then the public part of the structure is changed
for just one or zero IPv4 nameservers.

2002-05-21  Jakub Jelinek  <jakub@redhat.com>

	* resolv/resolv.h (struct __res_state): Remove unused nstimes.
	Add nsmap.
	* resolv/res_init.c (__res_vinit): Initialize nsmap array.
	Remove nstimes setting.
	(res_nclose): Check all MAXNS nameservers with non-NULL nsaddrs.
	* resolv/res_send.c (res_nsend): Don't close unconditionally if
	there is mix of IPv6 and IPv4 nameservers.
	Use nsmap array to find free slots and preserve nameserver ordering.
	Fix RES_ROTATE.

--- libc/resolv/res_init.c.jj	Thu Aug 23 18:49:01 2001
+++ libc/resolv/res_init.c	Tue May 21 18:03:44 2002
@@ -182,8 +182,10 @@ __res_vinit(res_state statp, int preinit
 	statp->_u._ext.nscount = 0;
 #ifdef _LIBC
 	statp->_u._ext.nscount6 = 0;
-	for (n = 0; n < MAXNS; n++)
-	    statp->_u._ext.nsaddrs[n] = NULL;
+	for (n = 0; n < MAXNS; n++) {
+		statp->_u._ext.nsaddrs[n] = NULL;
+		statp->_u._ext.nsmap[n] = MAXNS;
+	}
 #endif
 
 	/* Allow user to override the local domain definition */
@@ -323,8 +325,8 @@ __res_vinit(res_state statp, int preinit
                                 sa6->sin6_family = AF_INET6;
                                 sa6->sin6_port = htons(NAMESERVER_PORT);
 				statp->_u._ext.nsaddrs[nservall] = sa6;
-				statp->_u._ext.nstimes[nservall] = RES_MAXTIME;
 				statp->_u._ext.nssocks[nservall] = -1;
+				statp->_u._ext.nsmap[nservall] = MAXNS + 1;
                                 nservall++;
                             }
                         }
@@ -537,16 +539,14 @@ res_nclose(res_state statp) {
 		statp->_flags &= ~(RES_F_VC | RES_F_CONN);
 	}
 #ifdef _LIBC
-	for (ns = 0; ns < statp->_u._ext.nscount + statp->_u._ext.nscount6;
-	     ns++)
+	for (ns = 0; ns < MAXNS; ns++)
 #else
 	for (ns = 0; ns < statp->_u._ext.nscount; ns++)
 #endif
-	{
-		if (statp->_u._ext.nssocks[ns] != -1) {
+		if (statp->_u._ext.nsaddrs[ns]
+		    && statp->_u._ext.nssocks[ns] != -1) {
 			(void) __close(statp->_u._ext.nssocks[ns]);
 			statp->_u._ext.nssocks[ns] = -1;
 		}
-	}
 	statp->_u._ext.nsinit = 0;
 }
--- libc/resolv/res_send.c.jj	Fri Feb 16 11:53:48 2001
+++ libc/resolv/res_send.c	Tue May 21 19:06:40 2002
@@ -400,12 +400,15 @@ res_nsend(res_state statp,
 		if (EXT(statp).nscount != statp->nscount)
 			needclose++;
 		else
-			for (ns = 0; ns < statp->nscount; ns++)
 #ifdef _LIBC
-				if (!sock_eq((struct sockaddr_in6 *)
-					     &statp->nsaddr_list[ns],
-					     EXT(statp).nsaddrs[ns]))
+			for (ns = 0; ns < MAXNS; ns++) {
+				unsigned int map = EXT(statp).nsmap[ns];
+				if (map < MAXNS
+				    && !sock_eq((struct sockaddr_in6 *)
+						&statp->nsaddr_list[map],
+						EXT(statp).nsaddrs[ns]))
 #else
+			for (ns = 0; ns < statp->nscount; ns++) {
 				if (!sock_eq(&statp->nsaddr_list[ns],
 					     &EXT(statp).nsaddrs[ns]))
 #endif
@@ -413,6 +416,7 @@ res_nsend(res_state statp,
 					needclose++;
 					break;
 				}
+			}
 		if (needclose)
 			res_nclose(statp);
 	}
@@ -422,20 +426,34 @@ res_nsend(res_state statp,
 	 */
 	if (EXT(statp).nsinit == 0) {
 #ifdef _LIBC
-		n = 0;
-#endif
-		for (ns = 0; ns < statp->nscount; ns++) {
-#ifdef _LIBC
-			/* find a hole */
-		  	while ((n < MAXNS) &&
-			    (EXT(statp).nsaddrs[n] != NULL) &&
-			    (EXT(statp).nsaddrs[n]->sin6_family == AF_INET6) &&
-			    !IN6_IS_ADDR_V4MAPPED(
-			        &EXT(statp).nsaddrs[n]->sin6_addr))
-				n++;
-			if (n == MAXNS)
-				break;
+		unsigned char map[MAXNS];
 
+		memset (map, MAXNS, sizeof (map));
+		for (n = 0; n < MAXNS; n++) {
+			ns = EXT(statp).nsmap[n];
+			if (ns < statp->nscount)
+				map[ns] = n;
+			else if (ns < MAXNS) {
+				free(EXT(statp).nsaddrs[n]);
+				EXT(statp).nsaddrs[n] = NULL;
+				EXT(statp).nsmap[n] = MAXNS;
+			}
+		}
+		n = statp->nscount;
+		if (statp->nscount > EXT(statp).nscount)
+			for (n = EXT(statp).nscount, ns = 0;
+			     n < statp->nscount; n++) {
+				while (ns < MAXNS
+				       && EXT(statp).nsmap[ns] != MAXNS)
+					ns++;
+				if (ns == MAXNS)
+					break;
+				EXT(statp).nsmap[ns] = n;
+				map[n] = ns++;
+			}
+		EXT(statp).nscount = n;
+		for (ns = 0; ns < EXT(statp).nscount; ns++) {
+			n = map[ns];
 			if (EXT(statp).nsaddrs[n] == NULL)
 				EXT(statp).nsaddrs[n] =
 				    malloc(sizeof (struct sockaddr_in6));
@@ -443,31 +461,18 @@ res_nsend(res_state statp,
 				memcpy(EXT(statp).nsaddrs[n],
 				       &statp->nsaddr_list[ns],
 				       sizeof (struct sockaddr_in));
-				EXT(statp).nstimes[n] = RES_MAXTIME;
 				EXT(statp).nssocks[n] = -1;
 				n++;
 			}
+		}
 #else
+		for (ns = 0; ns < statp->nscount; ns++) {
 			EXT(statp).nsaddrs[ns] = statp->nsaddr_list[ns];
-			EXT(statp).nstimes[ns] = RES_MAXTIME;
 			EXT(statp).nssocks[ns] = -1;
-#endif
-		}
-		EXT(statp).nscount = statp->nscount;
-		EXT(statp).nsinit = 1;
-#ifdef _LIBC
-		/* If holes left, free memory and set to NULL */
-		while (n < MAXNS) {
-			if ((EXT(statp).nsaddrs[n] != NULL) &&
-			    ((EXT(statp).nsaddrs[n]->sin6_family != AF_INET6)
-			    || IN6_IS_ADDR_V4MAPPED(
-				   &EXT(statp).nsaddrs[n]->sin6_addr))) {
-				free(EXT(statp).nsaddrs[n]);
-				EXT(statp).nsaddrs[n] = NULL;
-			}
-			n++;
 		}
+		EXT(statp).nscount = ns;
 #endif
+		EXT(statp).nsinit = 1;
 	}
 
 	/*
@@ -478,12 +483,28 @@ res_nsend(res_state statp,
 	    (statp->options & RES_BLAST) == 0) {
 #ifdef _LIBC
 		struct sockaddr_in6 *ina;
-		int lastns = statp->nscount + EXT(statp).nscount6 - 1;
+		unsigned int map;
 
-		ina = EXT(statp).nsaddrs[0];
-		for (ns = 0; ns < lastns; ns++)
-			EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1];
-		EXT(statp).nsaddrs[lastns] = ina;
+		n = 0;
+		while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
+			n++;
+		if (n < MAXNS) {
+			ina = EXT(statp).nsaddrs[n];
+			map = EXT(statp).nsmap[n];
+			for (;;) {
+				ns = n + 1;
+				while (ns < MAXNS
+				       && EXT(statp).nsmap[ns] == MAXNS)
+					ns++;
+				if (ns == MAXNS)
+					break;
+				EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
+				EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
+				n = ns;
+			}
+			EXT(statp).nsaddrs[n] = ina;
+			EXT(statp).nsmap[n] = map;
+		}
 #else
 		struct sockaddr_in ina;
 		int lastns = statp->nscount - 1;
--- libc/resolv/resolv.h.jj	Fri Feb  8 12:04:18 2002
+++ libc/resolv/resolv.h	Tue May 21 15:57:47 2002
@@ -130,7 +130,7 @@ struct __res_state {
 		char	pad[52];	/* On an i386 this means 512b total. */
 		struct {
 			u_int16_t		nscount;
-			u_int16_t		nstimes[MAXNS];	/* ms. */
+			u_int16_t		nsmap[MAXNS];
 			int			nssocks[MAXNS];
 			u_int16_t		nscount6;
 			u_int16_t		nsinit;

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]