Facing issue in dns timeout

Denys Vlasenko vda.linux at googlemail.com
Tue Feb 2 23:11:14 UTC 2010


On Tuesday 02 February 2010 20:05, Bernhard Reutner-Fischer wrote:
> >Looks correct.
> >
> >-               reply_timeout = RES_TIMEOUT * 1000;
> >+               reply_timeout = _RES_RETRANS * 1000;
> >
> >Since we don't care about precision here, you may well
> >use   reply_timeout = _RES_RETRANS * 1024   :)
> 
> I didn't look, why would be 1024 superiour to 1000 (i don't like the
> skew this would introduce for odd timeout:999 or the like)

x * 1024 is shift, not mul.

Anyway. I looked closely and it needs to be done differently.
We should avoid pulling in _res unless absolutely necessary.
Comments in resolv.c explain how.

I am going to apply the patch below, but please review it
nevertheless. Sizes:

    text           data     bss     dec     hex filename
-   1745              2       4    1751     6d7 libc/inet/dnslookup.o
+   1760              2       4    1766     6e6 libc/inet/dnslookup.o
-    962              0       4     966     3c6 libc/inet/opennameservers.o
+   1099              0       4    1103     44f libc/inet/opennameservers.o
-    462              4     472     938     3aa libc/inet/res_init.o
+    454              4     468     926     39e libc/inet/res_init.o
-    870              0       0     870     366 libc/inet/res_query.o
+    867              0       0     867     363 libc/inet/res_query.o



diff -d -urpN uClibc.6/include/resolv.h uClibc.7/include/resolv.h
--- uClibc.6/include/resolv.h	2009-10-13 22:26:32.000000000 +0200
+++ uClibc.7/include/resolv.h	2010-02-03 00:01:19.000000000 +0100
@@ -114,22 +114,20 @@ typedef res_sendhookact (*res_send_rhook
  * I guess it's safe to set that to N.
  */
 struct __res_state {
-#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__
-	int	retrans;		/* retransmission time interval */
-	int	retry;			/* number of times to retransmit */
-#endif
+	/*int retrans, retry; - moved, was here */
 	u_int32_t options;		/* (was: ulong) option flags - see below. */
 	struct sockaddr_in nsaddr_list[MAXNS]; /* address of name server */
 #define nsaddr nsaddr_list[0]		/* for backward compatibility */
 	char	*dnsrch[MAXDNSRCH + 1];	/* components of domain to search */
+	/*char defdname[256]; - moved, was here */
+	u_int8_t nscount;		/* (was: int) number of name servers */
+	u_int8_t ndots;			/* (was: unsigned:4) threshold for initial abs. query */
+	u_int8_t retrans;		/* (was: int) retransmission time interval */
+	u_int8_t retry;			/* (was: int) number of times to retransmit */
 #ifdef __UCLIBC_HAS_COMPAT_RES_STATE__
 	/* googling for "_res.defdname" says it's still sometimes used.
 	 * Pity. It's huge, I want to move it to EXTRA_COMPAT... */
 	char	defdname[256];		/* default domain (deprecated) */
-#endif
-	u_int8_t nscount;		/* (was: int) number of name servers */
-	u_int8_t ndots;			/* (was: unsigned:4) threshold for initial abs. query */
-#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__
 	u_int8_t nsort;			/* (was: unsigned:4) number of elements in sort_list[] */
 	u_int16_t pfcode;		/* (was: ulong) RES_PRF_ flags. Used by dig. */
 	unsigned short id;		/* current message id */
diff -d -urpN uClibc.6/libc/inet/resolv.c uClibc.7/libc/inet/resolv.c
--- uClibc.6/libc/inet/resolv.c	2010-02-02 23:03:43.000000000 +0100
+++ uClibc.7/libc/inet/resolv.c	2010-02-03 00:05:45.000000000 +0100
@@ -407,6 +407,8 @@ __UCLIBC_MUTEX_EXTERN(__resolv_lock);
 /* Protected by __resolv_lock */
 extern void (*__res_sync)(void) attribute_hidden;
 /*extern uint32_t __resolv_opts attribute_hidden; */
+extern uint8_t __resolv_timeout attribute_hidden;
+extern uint8_t __resolv_attempts attribute_hidden;
 extern unsigned __nameservers attribute_hidden;
 extern unsigned __searchdomains attribute_hidden;
 extern sockaddr46_t *__nameserver attribute_hidden;
@@ -499,7 +501,7 @@ extern void __close_nameservers(void) at
  *		Allows addresses returned by gethostbyname to be sorted.
  *		Not supported.
  * options option[ option]...
- *		(so far we support none)
+ *		(so far we support timeout:n and attempts:n)
  *		$RES_OPTIONS (space-separated list) is to be added to "options"
  *  debug	sets RES_DEBUG in _res.options
  *  ndots:n	how many dots there should be so that name will be tried
@@ -526,7 +528,7 @@ extern void __close_nameservers(void) at
  *
  * We will read and analyze /etc/resolv.conf as needed before
  * we do a DNS request. This happens in __dns_lookup.
- * (TODO: also re-parse it after a timeout, to catch updates).
+ * It is reread if its mtime is changed.
  *
  * BSD has res_init routine which is used to initialize resolver state
  * which is held in global structure _res.
@@ -903,6 +905,8 @@ __UCLIBC_MUTEX_INIT(__resolv_lock, PTHRE
 /* Protected by __resolv_lock */
 void (*__res_sync)(void);
 /*uint32_t __resolv_opts; */
+uint8_t __resolv_timeout;
+uint8_t __resolv_attempts;
 unsigned __nameservers;
 unsigned __searchdomains;
 sockaddr46_t *__nameserver;
@@ -970,6 +974,9 @@ void attribute_hidden __open_nameservers
 	if (__nameservers)
 		goto sync;
 
+	__resolv_timeout = RES_TIMEOUT;
+	__resolv_attempts = RES_DFLRETRY;
+
 	fp = fopen("/etc/resolv.conf", "r");
 #ifdef FALLBACK_TO_CONFIG_RESOLVCONF
 	if (!fp) {
@@ -1048,7 +1055,24 @@ void attribute_hidden __open_nameservers
 				continue;
 			}
 			/* if (strcmp(keyword, "sortlist") == 0)... */
-			/* if (strcmp(keyword, "options") == 0)... */
+			if (strcmp(keyword, "options") == 0) {
+				char *p1;
+				uint8_t *what;
+
+				if (p == NULL || (p1 = strchr(p, ':')) == NULL)
+					continue;
+				*p1++ = '\0';
+				if (p1 == NULL)
+					continue;
+				if (strcmp(p, "timeout") == 0)
+					what = &__resolv_timeout;
+				else if (strcmp(p, "attempts") == 0)
+					what = &__resolv_attempts;
+				else
+					continue;
+				*what = atoi(p1);
+				DPRINTF("option %s:%d\n", p, *what);
+			}
 		}
 		fclose(fp);
 	}
@@ -1285,8 +1309,7 @@ int attribute_hidden __dns_lookup(const 
 			local_ns_num = 0;
 			if (_res.options & RES_ROTATE) */
 				local_ns_num = last_ns_num;
-/*TODO: use _res.retry */
-			retries_left = __nameservers * RES_DFLRETRY;
+			retries_left = __nameservers * __resolv_attempts;
 		}
 		retries_left--;
 		if (local_ns_num >= __nameservers)
@@ -1345,8 +1368,7 @@ int attribute_hidden __dns_lookup(const 
 		send(fd, packet, packet_len, 0);
 
 #ifdef USE_SELECT
-/*TODO: use _res.retrans*/
-		reply_timeout = RES_TIMEOUT;
+		reply_timeout = __resolv_timeout;
  wait_again:
 		FD_ZERO(&fds);
 		FD_SET(fd, &fds);
@@ -1360,7 +1382,7 @@ int attribute_hidden __dns_lookup(const 
 		}
 		reply_timeout--;
 #else
-		reply_timeout = RES_TIMEOUT * 1000;
+		reply_timeout = __resolv_timeout * 1000;
  wait_again:
 		fds.fd = fd;
 		fds.events = POLLIN;
@@ -2878,6 +2900,8 @@ static void res_sync_func(void)
 			__nameserver[n].sa4 = rp->nsaddr_list[n]; /* struct copy */
 #endif
 	}
+	__resolv_timeout = rp->retrans;
+	__resolv_attempts = rp->retry;
 	/* Extend and comment what program is known
 	 * to use which _res.XXX member(s).
 
@@ -2904,13 +2928,17 @@ int res_init(void)
 
 	memset(rp, 0, sizeof(*rp));
 	rp->options = RES_INIT;
-#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__
 	rp->retrans = RES_TIMEOUT;
-	rp->retry = 4;
-/*TODO: pulls in largish static buffers... use simpler one? */
-	rp->id = random();
-#endif
+	rp->retry = RES_DFLRETRY;
 	rp->ndots = 1;
+#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__
+	/* Was: "rp->id = random();" but:
+	 * - random() pulls in largish static buffers
+	 * - isn't actually random unless, say, srandom(time(NULL)) was called
+	 * - is not used by uclibc anyway :)
+	 */
+	/* rp->id = 0; - memset did it */
+#endif
 #ifdef __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__
 	rp->_vcsock = -1;
 #endif


More information about the uClibc mailing list