static unsigned long mtime()
{
struct timespec ts;
- clock_gettime(CLOCK_REALTIME, &ts);
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0 && errno == ENOSYS)
+ clock_gettime(CLOCK_REALTIME, &ts);
return (unsigned long)ts.tv_sec * 1000
+ ts.tv_nsec / 1000000;
}
family = AF_INET;
sl = sizeof sa.sin;
}
+
+ /* Convert any IPv4 addresses in a mixed environment to v4-mapped */
+ if (fd >= 0 && family == AF_INET6) {
+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0);
+ for (i=0; i<nns; i++) {
+ if (ns[i].sin.sin_family != AF_INET) continue;
+ memcpy(ns[i].sin6.sin6_addr.s6_addr+12,
+ &ns[i].sin.sin_addr, 4);
+ memcpy(ns[i].sin6.sin6_addr.s6_addr,
+ "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
+ ns[i].sin6.sin6_family = AF_INET6;
+ ns[i].sin6.sin6_flowinfo = 0;
+ ns[i].sin6.sin6_scope_id = 0;
+ }
+ }
+
sa.sin.sin_family = family;
if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) {
if (fd >= 0) close(fd);
pthread_cleanup_push(cleanup, pfd);
pthread_setcancelstate(cs, 0);
- /* Convert any IPv4 addresses in a mixed environment to v4-mapped */
- if (family == AF_INET6) {
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0);
- for (i=0; i<nns; i++) {
- if (ns[i].sin.sin_family != AF_INET) continue;
- memcpy(ns[i].sin6.sin6_addr.s6_addr+12,
- &ns[i].sin.sin_addr, 4);
- memcpy(ns[i].sin6.sin6_addr.s6_addr,
- "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
- ns[i].sin6.sin6_family = AF_INET6;
- ns[i].sin6.sin6_flowinfo = 0;
- ns[i].sin6.sin6_scope_id = 0;
- }
- }
-
memset(alens, 0, sizeof *alens * nqueries);
retry_interval = timeout / attempts;
/* Wait for a response, or until time to retry */
if (poll(pfd, nqueries+1, t1+retry_interval-t2) <= 0) continue;
- while (next < nqueries &&
- (rlen = recvfrom(fd, answers[next], asize, 0,
- (void *)&sa, (socklen_t[1]){sl})) >= 0) {
+ while (next < nqueries) {
+ struct msghdr mh = {
+ .msg_name = (void *)&sa,
+ .msg_namelen = sl,
+ .msg_iovlen = 1,
+ .msg_iov = (struct iovec []){
+ { .iov_base = (void *)answers[next],
+ .iov_len = asize }
+ }
+ };
+ rlen = recvmsg(fd, &mh, 0);
+ if (rlen < 0) break;
/* Ignore non-identifiable packets */
if (rlen < 4) continue;
if (next == nqueries) pfd[nqueries].events = 0;
/* If answer is truncated (TC bit), fallback to TCP */
- if (answers[i][2] & 2) {
+ if ((answers[i][2] & 2) || (mh.msg_flags & MSG_TRUNC)) {
alens[i] = -1;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
r = start_tcp(pfd+i, family, ns+j, sl, queries[i], qlens[i]);
};
step_mh(&mh, apos[i]);
r = recvmsg(pfd[i].fd, &mh, 0);
- if (r < 0) goto out;
+ if (r <= 0) goto out;
apos[i] += r;
if (apos[i] < 2) continue;
int alen = alen_buf[i][0]*256 + alen_buf[i][1];