From cca45baf8353d1e338d232f5bdb2d1d6b357f1da Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 3 Feb 2010 00:11:34 +0100 Subject: /etc/resolv.conf: support "timeout:n" and "attempts:n" options 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 Signed-off-by: Denys Vlasenko --- include/resolv.h | 14 ++++++-------- libc/inet/resolv.c | 54 +++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/include/resolv.h b/include/resolv.h index e0cd35db1..6f69806c4 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -114,22 +114,20 @@ typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *ns, * 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 --git a/libc/inet/resolv.c b/libc/inet/resolv.c index ee1323e76..0a6fd7aaf 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -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) attribute_hidden; * 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) attribute_hidden; * * 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, PTHREAD_MUTEX_INITIALIZER); /* 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(void) 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(void) 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 char *name, 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 char *name, 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 char *name, } 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 -- cgit v1.2.3