From e01cf2fcd9caffc1d0941300124963f0ec18cce1 Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 18 Jan 2008 21:34:25 +0000 Subject: [PATCH] libresolv-25.tar.gz --- dns.c | 126 +++++++++++++++++++++++++++++++++++-------------- dns.h | 21 ++++----- dns_util.c | 22 ++++----- dns_util.h | 21 ++++----- res_private.h | 9 ++++ res_query.c | 7 ++- res_send.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++---- 7 files changed, 256 insertions(+), 78 deletions(-) diff --git a/dns.c b/dns.c index b121691..fa5ddfa 100644 --- 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 d63803c..6cee32e 100644 --- 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@ */ diff --git a/dns_util.c b/dns_util.c index 96b1f28..adb1324 100644 --- a/dns_util.c +++ b/dns_util.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@ */ @@ -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; } diff --git a/dns_util.h b/dns_util.h index a291584..c29dfd7 100644 --- a/dns_util.h +++ b/dns_util.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@ */ diff --git a/res_private.h b/res_private.h index 562d5ab..b9e076d 100644 --- a/res_private.h +++ b/res_private.h @@ -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 diff --git a/res_query.c b/res_query.c index 27217cc..7df8c6c 100644 --- a/res_query.c +++ b/res_query.c @@ -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 diff --git a/res_send.c b/res_send.c index 44f40ed..e70c2e4 100644 --- a/res_send.c +++ b/res_send.c @@ -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 #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: -- 2.45.2