X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Fnetwork%2F__dns.c;h=45d9b438f6de009e12b767ab7ea2b0ea25dcd548;hp=b3c876f36b921e53de927c119725efed9a33c48b;hb=f42bad9ccb2af7cde8a676d57c4d161455256456;hpb=43ee4df3384853a9c53f4f45b31d190ff9b0d7f0 diff --git a/src/network/__dns.c b/src/network/__dns.c index b3c876f3..45d9b438 100644 --- a/src/network/__dns.c +++ b/src/network/__dns.c @@ -5,8 +5,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -16,10 +15,15 @@ #include "stdio_impl.h" #define TIMEOUT 5 -#define RETRY 1 +#define RETRY 1000 #define PACKET_MAX 512 #define PTR_MAX (64 + sizeof ".in-addr.arpa") +static void cleanup(void *p) +{ + close((intptr_t)p); +} + int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) { time_t t0 = time(0); @@ -40,11 +44,13 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) int got = 0, failed = 0; int errcode = EAI_AGAIN; int i, j; - struct timeval tv; - fd_set fds; + struct timespec ts; + struct pollfd pfd; int id; int cs; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + /* Construct query template - RR and ID will be filled later */ if (strlen(name)-1 >= 254U) return EAI_NONAME; q[2] = q[5] = 1; @@ -58,8 +64,8 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) ql = i+4; /* Make a reasonably unpredictable id */ - gettimeofday(&tv, 0); - id = tv.tv_usec + tv.tv_usec/256 & 0xffff; + clock_gettime(CLOCK_REALTIME, &ts); + id = ts.tv_nsec + ts.tv_nsec/65536UL & 0xffff; /* Get nameservers from resolv.conf, fallback to localhost */ f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf); @@ -82,7 +88,8 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) sl = sizeof sa.sin; } - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + pthread_cleanup_push(cleanup, (void *)(intptr_t)fd); + pthread_setcancelstate(cs, 0); /* Get local address and open/bind a socket */ sa.sin.sin_family = family; @@ -94,6 +101,9 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) /* Nonblocking to work around Linux UDP select bug */ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); + pfd.fd = fd; + pfd.events = POLLIN; + /* Loop until we timeout; break early on success */ for (; time(0)-t0 < TIMEOUT; ) { @@ -106,11 +116,7 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) } /* Wait for a response, or until time to retry */ - FD_ZERO(&fds); - FD_SET(fd, &fds); - tv.tv_sec = RETRY; - tv.tv_usec = 0; - if (select(fd+1, &fds, 0, 0, &tv) <= 0) continue; + if (poll(&pfd, 1, RETRY) <= 0) continue; /* Process any and all replies */ while (got+failed < rrcnt && (rlen = recvfrom(fd, r, 512, 0, @@ -145,8 +151,7 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) if (got+failed == rrcnt) break; } out: - close(fd); - pthread_setcancelstate(cs, 0); + pthread_cleanup_pop(1); /* Return the number of results, or an error code if none */ if (got) return got;