OSDN Git Service

/etc/resolv.conf: support "timeout:n" and "attempts:n" options
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 2 Feb 2010 23:11:34 +0000 (00:11 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 2 Feb 2010 23:11:34 +0000 (00:11 +0100)
    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 <vda.linux@googlemail.com>
include/resolv.h
libc/inet/resolv.c

index e0cd35d..6f69806 100644 (file)
@@ -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 */
index ee1323e..0a6fd7a 100644 (file)
@@ -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