]> git.saurik.com Git - apple/libresolv.git/commitdiff
libresolv-25.tar.gz mac-os-x-1052 mac-os-x-1053 mac-os-x-1054 v25
authorApple <opensource@apple.com>
Fri, 18 Jan 2008 21:34:25 +0000 (21:34 +0000)
committerApple <opensource@apple.com>
Fri, 18 Jan 2008 21:34:25 +0000 (21:34 +0000)
dns.c
dns.h
dns_util.c
dns_util.h
res_private.h
res_query.c
res_send.c

diff --git a/dns.c b/dns.c
index b121691fdfd55c185df58ea8134c368d1bb5af75..fa5ddfa0471ab39b61294060ac848437f3917acb 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -1,23 +1,22 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
@@ -1361,11 +1360,15 @@ _sdns_send(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type,
        char *qname;
        pdns_handle_t **pdns;
        uint32_t pdns_count;
-       int i, n, m;
+       int i, n;
+       int m, tmin, minstate;
 
        pdns = NULL;
        pdns_count = 0;
        n = -1;
+       minstate = 0;
+       *min = -1;
+       m = -1;
 
        pdns_count = _pdns_get_handles_for_name(sdns, name, &pdns);
 
@@ -1377,17 +1380,26 @@ _sdns_send(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type,
 
        for (i = 0; i < pdns_count; i++)
        {
-               m = -1;
-               n = _pdns_query(sdns, pdns[i], qname, class, type, buf, len, from, fromlen, &m);
-               if (min != NULL)
+               tmin = -1;
+               n = _pdns_query(sdns, pdns[i], qname, class, type, buf, len, from, fromlen, &tmin);
+               if (n <= 0)
                {
-                       if (*min == -1) *min = m;
-                       else if ((m >= 0) && (m < *min)) *min = m;
+                       if (tmin < 0)
+                       {
+                               minstate = -1;
+                       }
+                       else if (minstate == 0)
+                       {
+                               if (m == -1) m = tmin;
+                               else if (tmin < m) m = tmin;
+                       }
                }
 
                if (n > 0) break;
        }
 
+       if (minstate == 0) *min = m;
+
        free(pdns);
        free(qname);
        return n;
@@ -1397,13 +1409,28 @@ __private_extern__ int
 _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, uint32_t recurse, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, int *min)
 {
        pdns_handle_t *primary, **pdns;
-       int i, n, ndots, status, m;
+       int i, n, ndots, status;
+       int m, tmin, minstate;
        char *dot, *qname;
        uint32_t pdns_count;
 
        if (sdns == NULL) return -1;
        if (name == NULL) return -1;
 
+       /*
+        * A minimum TTL derived from the minimim of all SOA records
+        * that are received with NXDOMAIN or no data is returned to
+        * the caller if every call returns an NXDOMAIN or no data
+        * and a SOA min ttl.  If any call times out or returns some
+        * other error, we return "-1" in the "min" out parameter.
+        * The minstate variable is set to -1 if we must return -1.
+        */
+       minstate = 0;
+       *min = -1;
+
+       /* m is the lowest of all minima.  -1 is unset */
+       m = -1;
+
        /* ndots is the threshold for trying a qualified name "as is" */
        ndots = 1;
        primary = sdns->pdns_primary;
@@ -1431,16 +1458,20 @@ _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t typ
         */
        if ((n >= ndots) || (fqdn == 1) || (type == ns_t_ptr))
        {
-               status = _sdns_send(sdns, name, class, type, fqdn, buf, len, from, fromlen, min);
+               tmin = -1;
+               status = _sdns_send(sdns, name, class, type, fqdn, buf, len, from, fromlen, &tmin);
                if (status > 0) return status;
+
+               if (tmin < 0) minstate = -1;
+               else m = tmin;
        }
 
        /* end of the line for FQDNs or PTR queries */
-       if (fqdn == 1) return -1;
-       if (type == ns_t_ptr) return -1;
-
-       if (recurse == 0) return -1;
-       if (primary == NULL) return -1;
+       if ((fqdn == 1) || (type == ns_t_ptr) || (recurse == 0) || (primary == NULL))
+       {
+               if (minstate == 0) *min = m;
+               return -1;
+       }
 
        /* Try appending names from the search list */
        if (primary->search_count == SEARCH_COUNT_INIT) _pdns_process_res_search_list(primary);
@@ -1454,17 +1485,26 @@ _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t typ
                        asprintf(&qname, "%s.%s", name, primary->search_list[i]);
                        if (qname == NULL) return -1;
 
-                       m = -1;
-                       status = _sdns_search(sdns, qname, class, type, fqdn, 0, buf, len, from, fromlen, &m);
+                       tmin = -1;
+                       status = _sdns_search(sdns, qname, class, type, fqdn, 0, buf, len, from, fromlen, &tmin);
+                       if (status <= 0)
                        {
-                               if (*min == -1) *min = m;
-                               else if ((m >= 0) && (m < *min)) *min = m;
+                               if (tmin < 0)
+                               {
+                                       minstate = -1;
+                               }
+                               else if (minstate == 0)
+                               {
+                                       if (m == -1) m = tmin;
+                                       else if (tmin < m) m = tmin;
+                               }
                        }
-                       
+
                        free(qname);
                        if (status > 0) return status;
                }
 
+               if (minstate == 0) *min = m;
                return -1;
        }
 
@@ -1476,27 +1516,43 @@ _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t typ
        pdns_count = _pdns_get_default_handles(sdns, &pdns);
        status = -1;
 
-       if (pdns_count == 0) return -1;
+       if (pdns_count == 0)
+       {
+               if (minstate == 0) *min = m;
+               return -1;
+       }
 
        for (i = 0; i < pdns_count; i++)
        {
                qname = NULL;
                if (pdns[i]->name == NULL) asprintf(&qname, "%s", name);
                else asprintf(&qname, "%s.%s", name, pdns[i]->name);
+
+               /* leave *min at -1 in case of a malloc failure */
                if (qname == NULL) return -1;
 
-               m = -1;
-               status = _pdns_query(sdns, pdns[i], qname, class, type, buf, len, from, fromlen, min);
+               tmin = -1;
+               status = _pdns_query(sdns, pdns[i], qname, class, type, buf, len, from, fromlen, &tmin);
+               if (status <= 0)
                {
-                       if (*min == -1) *min = m;
-                       else if ((m >= 0) && (m < *min)) *min = m;
+                       if (tmin < 0)
+                       {
+                               minstate = -1;
+                       }
+                       else if (minstate == 0)
+                       {
+                               if (m == -1) m = tmin;
+                               else if (tmin < m) m = tmin;
+                       }
                }
-               
+
                free(qname);
                if (status > 0) break;
        }
 
        free(pdns);
+
+       if (minstate == 0) *min = m;
        return status;
 }
 
diff --git a/dns.h b/dns.h
index d63803c57401c40a9a205b2ac0651c6dc569f81a..6cee32ec9e4bb5069416c5b83a07e4cda6e5907b 100644 (file)
--- a/dns.h
+++ b/dns.h
@@ -1,23 +1,22 @@
 /*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003-2006 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * "Portions Copyright (c) 2003 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
index 96b1f283f2fe3244c36e507ed5bc8435395b8b37..adb13249f617c7dcff6554980a2175ab2ade4c2d 100644 (file)
@@ -1,23 +1,22 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
@@ -1471,6 +1470,7 @@ dns_type_number(const char *t, uint16_t *n)
        if (!strcasecmp(t, "PTR"))     { *n = ns_t_ptr;      return 0; }
        if (!strcasecmp(t, "HINFO"))   { *n = ns_t_hinfo;    return 0; }
        if (!strcasecmp(t, "MINFO"))   { *n = ns_t_minfo;    return 0; }
+       if (!strcasecmp(t, "MX"))      { *n = ns_t_mx;       return 0; }
        if (!strcasecmp(t, "TXT"))     { *n = ns_t_txt;      return 0; }
        if (!strcasecmp(t, "RP"))      { *n = ns_t_rp;       return 0; }
        if (!strcasecmp(t, "AFSDB"))   { *n = ns_t_afsdb;    return 0; }
index a291584f12e08cf8110e23f445621c4fec641e96..c29dfd76319310bf6a8cda4502c900394b02e5a2 100644 (file)
@@ -1,23 +1,22 @@
 /*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003-2006 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * "Portions Copyright (c) 2003 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
index 562d5abcd002bf68951d72ff8aefbe8b24ff44d3..b9e076d3074acf8b259018f142f7518e10c6fcc5 100644 (file)
@@ -98,4 +98,13 @@ __private_extern__ int res_query_mDNSResponder(res_state statp, const char *name
 
 int dns_res_once(struct sockaddr *server, struct timeval *timeout, int options, const char *name, int class, int type, u_char *res, int *reslen);
 
+/*
+ * Interrupt a thread blocked in select()
+ */
+void res_interrupt_requests_enable(void);
+void res_interrupt_requests_disable(void);
+void res_interrupt_requests(void* token);
+void* res_init_interrupt_token(void);
+void res_delete_interrupt_token(void* token);
+
 #endif
index 27217ccb391c0f15625c25d5c8d3e20810268a75..7df8c6c42a36230a12a9fe2992ca953aeb575616 100644 (file)
@@ -546,14 +546,17 @@ again:
                return (n);
        }
 
-       if (hp->rcode != ns_r_noerror || ntohs(hp->ancount) == 0)
+       if ((hp->rcode == ns_r_nxdomain) || ((hp->rcode == ns_r_noerror) && (ntohs(hp->ancount) == 0)))
        {
                if (min != NULL)
                {
                        *min = res_soa_minimum(answer, anslen);
-                       if (statp->options & RES_DEBUG) printf(";; res_nquery: SOA minimum = %d\n", *min);
+                       if (statp->options & RES_DEBUG) printf(";; res_nquery: SOA minimum TTL = %d\n", *min);
                }
+       }
 
+       if (hp->rcode != ns_r_noerror || ntohs(hp->ancount) == 0)
+       {
 #ifdef DEBUG
                if (statp->options & RES_DEBUG) printf(";; rcode = %d, ancount=%d\n", hp->rcode, ntohs(hp->ancount));
 #endif
index 44f40ed02928b56994a7b6c27309cfad83f7b0c2..e70c2e422f1c7bc1ae507128fae84165bdff075b 100644 (file)
@@ -125,6 +125,7 @@ static const char rcsid[] = "$Id: res_send.c,v 1.1 2006/03/01 19:01:38 majka Exp
 
 #include "res_debug.h"
 #include "res_private.h"
+#include <sys/fcntl.h>
 
 #define EXT(res) ((res)->_u._ext)
 
@@ -145,6 +146,87 @@ static int         pselect(int, void *, void *, void *, struct timespec *, const sigset
 #endif
 
 static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+static int interrupt_pipe_enabled = 0;
+static pthread_key_t interrupt_pipe_key;
+
+void
+res_delete_interrupt_token(void *token)
+{
+       int *interrupt_pipe;
+
+       interrupt_pipe = token;
+       if (interrupt_pipe == NULL) return;
+
+       if (interrupt_pipe[0] >= 0)
+       {
+               close(interrupt_pipe[0]);
+               interrupt_pipe[0] = -1;
+       }
+
+       if (interrupt_pipe[1] >= 0)
+       {
+               close(interrupt_pipe[1]);
+               interrupt_pipe[1] = -1;
+       }
+
+       pthread_setspecific(interrupt_pipe_key, NULL);
+       free(interrupt_pipe);
+}
+
+void *
+res_init_interrupt_token(void)
+{
+       int *interrupt_pipe;
+
+       interrupt_pipe = (int *)malloc(2 * sizeof(int));
+       if (interrupt_pipe == NULL) return NULL;
+
+       if (pipe(interrupt_pipe) < 0)
+       {
+               /* this shouldn't happen */
+               interrupt_pipe[0] = -1;
+               interrupt_pipe[1] = -1;
+       } 
+       else
+       {
+               fcntl(interrupt_pipe[0], F_SETFD, FD_CLOEXEC | O_NONBLOCK);
+               fcntl(interrupt_pipe[1], F_SETFD, FD_CLOEXEC | O_NONBLOCK);
+       }
+
+       pthread_setspecific(interrupt_pipe_key, interrupt_pipe);
+
+       return interrupt_pipe;
+}
+
+void
+res_interrupt_requests_enable(void)
+{
+       interrupt_pipe_enabled = 1;
+       pthread_key_create(&interrupt_pipe_key, NULL);
+}
+
+void
+res_interrupt_requests_disable(void)
+{
+       interrupt_pipe_enabled = 0;
+       pthread_key_delete(interrupt_pipe_key);
+}
+
+void
+res_interrupt_request(void *token)
+{
+       int oldwrite;
+       int *interrupt_pipe;
+
+       interrupt_pipe = token;
+
+       if ((interrupt_pipe == NULL) || (interrupt_pipe_enabled == 0)) return;
+
+       oldwrite = interrupt_pipe[1];
+       interrupt_pipe[1] = -1;
+
+       if (oldwrite >= 0) close(oldwrite);
+}
 
 #ifdef __APPLE__
 static struct iovec
@@ -359,7 +441,7 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1, const u_char *buf2, con
         * dynamic update packets.
         */
        if ((((const HEADER *)buf1)->opcode == ns_o_update) &&
-           (((const HEADER *)buf2)->opcode == ns_o_update))
+               (((const HEADER *)buf2)->opcode == ns_o_update))
                return (1);
 
        if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) return (0);
@@ -531,7 +613,7 @@ dns_res_send(res_state statp, const u_char *buf, int buflen, u_char *ans, int *a
         */
        for (try = 0; try < statp->retry; try++)
        {
-           for (ns = 0; ns < statp->nscount; ns++)
+               for (ns = 0; ns < statp->nscount; ns++)
                {
                        struct sockaddr *nsap;
                        int nsaplen;
@@ -579,6 +661,7 @@ send_same_ns:
                                status = notify_get_state(notify_token, &exit_requested);
                                if (exit_requested == ThreadStateExitRequested)
                                {
+                                       Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
                                        res_nclose(statp);
                                        notify_cancel(notify_token);
                                        return DNS_RES_STATUS_CANCELLED;
@@ -775,6 +858,7 @@ vc_same_ns:
                status = notify_get_state(notify_token, &exit_requested);
                if (exit_requested == ThreadStateExitRequested)
                {
+                       Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
                        *terrno = EINTR;
                        return DNS_RES_STATUS_CANCELLED;
                }
@@ -855,11 +939,12 @@ vc_same_ns:
                status = notify_get_state(notify_token, &exit_requested);
                if (exit_requested == ThreadStateExitRequested)
                {
+                       Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
                        *terrno = EINTR;
                        return DNS_RES_STATUS_CANCELLED;
                }
        }
-       
+
        cp = ans;
        len = NS_INT16SZ;
        while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0)
@@ -1035,11 +1120,12 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz
        const HEADER *hp = (const HEADER *) buf;
        HEADER *anhp = (HEADER *) ans;
        const struct sockaddr *nsap;
-       int nsaplen;
+       int nsaplen, nfds;
        struct timespec now, timeout, finish;
        fd_set dsmask;
        int iface, rif, status;
        uint64_t exit_requested;
+       int *interrupt_pipe;
 #ifndef __APPLE__
        struct sockaddr_storage from;
        ISC_SOCKLEN_T fromlen;
@@ -1049,6 +1135,8 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz
        int multicast;
 #endif
 
+       interrupt_pipe = NULL;
+
        nsap = get_nsaddr(statp, ns);
        nsaplen = get_salen(nsap);
        if (EXT(statp).nssocks[ns] == -1)
@@ -1195,6 +1283,8 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz
        timeout.tv_nsec *= 1000000;
        now = evNowTime();
        finish = evAddTime(now, timeout);
+
+       if (interrupt_pipe_enabled != 0) interrupt_pipe = pthread_getspecific(interrupt_pipe_key);
 #else
        seconds = (statp->retrans << ns);
        if (ns > 0) seconds /= statp->nscount;
@@ -1209,20 +1299,35 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz
        now = evNowTime();
 
  nonow:
-       
+
        if (notify_token != -1)
        {
                exit_requested = 0;
                status = notify_get_state(notify_token, &exit_requested);
-               if (exit_requested == ThreadStateExitRequested) return DNS_RES_STATUS_CANCELLED;
+               if (exit_requested == ThreadStateExitRequested)
+               {
+                       Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
+                       return DNS_RES_STATUS_CANCELLED;
+               }
        }
 
        FD_ZERO(&dsmask);
        FD_SET(s, &dsmask);
+
+       nfds = s + 1;
+       if ((interrupt_pipe_enabled != 0) && (interrupt_pipe != NULL))
+       {
+               if (interrupt_pipe[0] >= 0)
+               {
+                       FD_SET(interrupt_pipe[0], &dsmask);
+                       nfds = MAX(s, interrupt_pipe[0]) + 1;
+               }
+       }
+
        if (evCmpTime(finish, now) > 0) timeout = evSubTime(finish, now);
        else timeout = evConsTime(0, 0);
 
-       n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
+       n = pselect(nfds, &dsmask, NULL, NULL, &timeout, NULL);
        if (n == 0)
        {
                Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
@@ -1238,6 +1343,13 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz
                return DNS_RES_STATUS_SYSTEM_ERROR;
        }
 
+       /* socket s and/or interrupt pipe got data */
+       if ((interrupt_pipe_enabled != 0) && (interrupt_pipe != NULL) && ((interrupt_pipe[0] < 0) || (FD_ISSET(interrupt_pipe[0], &dsmask))))
+       {
+               Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
+               return DNS_RES_STATUS_CANCELLED;
+       }
+
        errno = 0;
        iface = 0;
        resplen = internal_recvfrom(s, (char *)ans, *anssiz, from, fromlen, &iface);
@@ -1391,7 +1503,7 @@ sock_eq(struct sockaddr *a, struct sockaddr *b)
        struct sockaddr_in6 *a6, *b6;
 
        if (a->sa_family != b->sa_family) return 0;
-       
+
        switch (a->sa_family)
        {
                case AF_INET: