17c478bd9Sstevel@tonic-gate /* 29525b14bSRao Shoaib * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*b3700b07SGordon Ross * 5*b3700b07SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 67c478bd9Sstevel@tonic-gate */ 77c478bd9Sstevel@tonic-gate 89525b14bSRao Shoaib 99525b14bSRao Shoaib /* 109525b14bSRao Shoaib * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") 119525b14bSRao Shoaib * Portions Copyright (C) 1996-2003 Internet Software Consortium. 129525b14bSRao Shoaib * 139525b14bSRao Shoaib * Permission to use, copy, modify, and/or distribute this software for any 149525b14bSRao Shoaib * purpose with or without fee is hereby granted, provided that the above 159525b14bSRao Shoaib * copyright notice and this permission notice appear in all copies. 169525b14bSRao Shoaib * 179525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 189525b14bSRao Shoaib * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 199525b14bSRao Shoaib * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 209525b14bSRao Shoaib * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 219525b14bSRao Shoaib * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 229525b14bSRao Shoaib * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 239525b14bSRao Shoaib * PERFORMANCE OF THIS SOFTWARE. 249525b14bSRao Shoaib */ 259525b14bSRao Shoaib 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Copyright (c) 1985, 1989, 1993 287c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 299525b14bSRao Shoaib * 307c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 317c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 327c478bd9Sstevel@tonic-gate * are met: 337c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 347c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 357c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 367c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 377c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 387c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 397c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 407c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 417c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 427c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 437c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 447c478bd9Sstevel@tonic-gate * without specific prior written permission. 459525b14bSRao Shoaib * 467c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 477c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 487c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 497c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 507c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 517c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 527c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 537c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 547c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 557c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 567c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Portions Copyright (c) 1993 by Digital Equipment Corporation. 619525b14bSRao Shoaib * 627c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 637c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 647c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies, and that 657c478bd9Sstevel@tonic-gate * the name of Digital Equipment Corporation not be used in advertising or 667c478bd9Sstevel@tonic-gate * publicity pertaining to distribution of the document or software without 677c478bd9Sstevel@tonic-gate * specific, written prior permission. 689525b14bSRao Shoaib * 697c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 707c478bd9Sstevel@tonic-gate * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 717c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 727c478bd9Sstevel@tonic-gate * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 737c478bd9Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 747c478bd9Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 757c478bd9Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 767c478bd9Sstevel@tonic-gate * SOFTWARE. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 807c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 819525b14bSRao Shoaib static const char rcsid[] = "$Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp $"; 827c478bd9Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */ 837c478bd9Sstevel@tonic-gate 849525b14bSRao Shoaib /*! \file 859525b14bSRao Shoaib * \brief 867c478bd9Sstevel@tonic-gate * Send query to name server and wait for reply. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #include "port_before.h" 907c478bd9Sstevel@tonic-gate #include "fd_setsize.h" 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate #include <sys/types.h> 937c478bd9Sstevel@tonic-gate #include <sys/param.h> 947c478bd9Sstevel@tonic-gate #include <sys/time.h> 957c478bd9Sstevel@tonic-gate #include <sys/socket.h> 967c478bd9Sstevel@tonic-gate #include <sys/uio.h> 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate #include <netinet/in.h> 99*b3700b07SGordon Ross #include <netinet/tcp.h> 1007c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 1017c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate #include <errno.h> 1047c478bd9Sstevel@tonic-gate #include <netdb.h> 1057c478bd9Sstevel@tonic-gate #include <resolv.h> 1067c478bd9Sstevel@tonic-gate #include <signal.h> 1077c478bd9Sstevel@tonic-gate #include <stdio.h> 1087c478bd9Sstevel@tonic-gate #include <stdlib.h> 1097c478bd9Sstevel@tonic-gate #include <string.h> 1107c478bd9Sstevel@tonic-gate #include <unistd.h> 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate #include <isc/eventlib.h> 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate #include "port_after.h" 1157c478bd9Sstevel@tonic-gate 1169525b14bSRao Shoaib #ifdef USE_POLL 1179525b14bSRao Shoaib #ifdef HAVE_STROPTS_H 1187c478bd9Sstevel@tonic-gate #include <stropts.h> 119e8031f0aSraf #endif 1209525b14bSRao Shoaib #include <poll.h> 1219525b14bSRao Shoaib #endif /* USE_POLL */ 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* Options. Leave them on. */ 1247c478bd9Sstevel@tonic-gate #define DEBUG 1257c478bd9Sstevel@tonic-gate #include "res_debug.h" 1267c478bd9Sstevel@tonic-gate #include "res_private.h" 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate #define EXT(res) ((res)->_u._ext) 1297c478bd9Sstevel@tonic-gate 1309525b14bSRao Shoaib #ifndef USE_POLL 1317c478bd9Sstevel@tonic-gate static const int highestFD = FD_SETSIZE - 1; 1327c478bd9Sstevel@tonic-gate #else 1337c478bd9Sstevel@tonic-gate static int highestFD = 0; 1347c478bd9Sstevel@tonic-gate #endif 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate /* Forward. */ 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate static int get_salen __P((const struct sockaddr *)); 1397c478bd9Sstevel@tonic-gate static struct sockaddr * get_nsaddr __P((res_state, size_t)); 1407c478bd9Sstevel@tonic-gate static int send_vc(res_state, const u_char *, int, 1417c478bd9Sstevel@tonic-gate u_char *, int, int *, int); 1427c478bd9Sstevel@tonic-gate static int send_dg(res_state, const u_char *, int, 1439525b14bSRao Shoaib u_char *, int, int *, int, int, 1447c478bd9Sstevel@tonic-gate int *, int *); 1457c478bd9Sstevel@tonic-gate static void Aerror(const res_state, FILE *, const char *, int, 1467c478bd9Sstevel@tonic-gate const struct sockaddr *, int); 1477c478bd9Sstevel@tonic-gate static void Perror(const res_state, FILE *, const char *, int); 1487c478bd9Sstevel@tonic-gate static int sock_eq(struct sockaddr *, struct sockaddr *); 1499525b14bSRao Shoaib #if defined(NEED_PSELECT) && !defined(USE_POLL) 1507c478bd9Sstevel@tonic-gate static int pselect(int, void *, void *, void *, 1517c478bd9Sstevel@tonic-gate struct timespec *, 1527c478bd9Sstevel@tonic-gate const sigset_t *); 1537c478bd9Sstevel@tonic-gate #endif 1547c478bd9Sstevel@tonic-gate void res_pquery(const res_state, const u_char *, int, FILE *); 1557c478bd9Sstevel@tonic-gate 1569525b14bSRao Shoaib #ifndef ORIGINAL_ISC_CODE 1577c478bd9Sstevel@tonic-gate #pragma weak __res_nameinquery = res_nameinquery 1587c478bd9Sstevel@tonic-gate #pragma weak __res_queriesmatch = res_queriesmatch 1597c478bd9Sstevel@tonic-gate #pragma weak res_nisourserver = res_ourserver_p 1607c478bd9Sstevel@tonic-gate #endif /* ORIGINAL_ISC_CODE */ 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* Public. */ 1657c478bd9Sstevel@tonic-gate 1669525b14bSRao Shoaib /*% 1677c478bd9Sstevel@tonic-gate * looks up "ina" in _res.ns_addr_list[] 1689525b14bSRao Shoaib * 1697c478bd9Sstevel@tonic-gate * returns: 1709525b14bSRao Shoaib *\li 0 : not found 1719525b14bSRao Shoaib *\li >0 : found 1729525b14bSRao Shoaib * 1737c478bd9Sstevel@tonic-gate * author: 1749525b14bSRao Shoaib *\li paul vixie, 29may94 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate int 1777c478bd9Sstevel@tonic-gate res_ourserver_p(const res_state statp, const struct sockaddr *sa) { 1787c478bd9Sstevel@tonic-gate const struct sockaddr_in *inp, *srv; 1797c478bd9Sstevel@tonic-gate const struct sockaddr_in6 *in6p, *srv6; 1807c478bd9Sstevel@tonic-gate int ns; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate switch (sa->sa_family) { 1837c478bd9Sstevel@tonic-gate case AF_INET: 1847c478bd9Sstevel@tonic-gate inp = (const struct sockaddr_in *)sa; 1857c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 1867c478bd9Sstevel@tonic-gate srv = (struct sockaddr_in *)get_nsaddr(statp, ns); 1877c478bd9Sstevel@tonic-gate if (srv->sin_family == inp->sin_family && 1887c478bd9Sstevel@tonic-gate srv->sin_port == inp->sin_port && 1897c478bd9Sstevel@tonic-gate (srv->sin_addr.s_addr == INADDR_ANY || 1907c478bd9Sstevel@tonic-gate srv->sin_addr.s_addr == inp->sin_addr.s_addr)) 1917c478bd9Sstevel@tonic-gate return (1); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate break; 1947c478bd9Sstevel@tonic-gate case AF_INET6: 1957c478bd9Sstevel@tonic-gate if (EXT(statp).ext == NULL) 1967c478bd9Sstevel@tonic-gate break; 1977c478bd9Sstevel@tonic-gate in6p = (const struct sockaddr_in6 *)sa; 1987c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 1997c478bd9Sstevel@tonic-gate srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); 2007c478bd9Sstevel@tonic-gate if (srv6->sin6_family == in6p->sin6_family && 2017c478bd9Sstevel@tonic-gate srv6->sin6_port == in6p->sin6_port && 2027c478bd9Sstevel@tonic-gate #ifdef HAVE_SIN6_SCOPE_ID 2039525b14bSRao Shoaib (srv6->sin6_scope_id == 0 || 2049525b14bSRao Shoaib srv6->sin6_scope_id == in6p->sin6_scope_id) && 2057c478bd9Sstevel@tonic-gate #endif 2067c478bd9Sstevel@tonic-gate (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || 2077c478bd9Sstevel@tonic-gate IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) 2087c478bd9Sstevel@tonic-gate return (1); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate break; 2117c478bd9Sstevel@tonic-gate default: 2127c478bd9Sstevel@tonic-gate break; 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate return (0); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2179525b14bSRao Shoaib /*% 2187c478bd9Sstevel@tonic-gate * look for (name,type,class) in the query section of packet (buf,eom) 2199525b14bSRao Shoaib * 2207c478bd9Sstevel@tonic-gate * requires: 2219525b14bSRao Shoaib *\li buf + HFIXEDSZ <= eom 2229525b14bSRao Shoaib * 2237c478bd9Sstevel@tonic-gate * returns: 2249525b14bSRao Shoaib *\li -1 : format error 2259525b14bSRao Shoaib *\li 0 : not found 2269525b14bSRao Shoaib *\li >0 : found 2279525b14bSRao Shoaib * 2287c478bd9Sstevel@tonic-gate * author: 2299525b14bSRao Shoaib *\li paul vixie, 29may94 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate int 2327c478bd9Sstevel@tonic-gate res_nameinquery(const char *name, int type, int class, 2337c478bd9Sstevel@tonic-gate const u_char *buf, const u_char *eom) 2347c478bd9Sstevel@tonic-gate { 2357c478bd9Sstevel@tonic-gate const u_char *cp = buf + HFIXEDSZ; 2367c478bd9Sstevel@tonic-gate int qdcount = ntohs(((const HEADER*)buf)->qdcount); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate while (qdcount-- > 0) { 2397c478bd9Sstevel@tonic-gate char tname[MAXDNAME+1]; 2407c478bd9Sstevel@tonic-gate int n, ttype, tclass; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate n = dn_expand(buf, eom, cp, tname, sizeof tname); 2437c478bd9Sstevel@tonic-gate if (n < 0) 2447c478bd9Sstevel@tonic-gate return (-1); 2457c478bd9Sstevel@tonic-gate cp += n; 2467c478bd9Sstevel@tonic-gate if (cp + 2 * INT16SZ > eom) 2477c478bd9Sstevel@tonic-gate return (-1); 2487c478bd9Sstevel@tonic-gate ttype = ns_get16(cp); cp += INT16SZ; 2497c478bd9Sstevel@tonic-gate tclass = ns_get16(cp); cp += INT16SZ; 2507c478bd9Sstevel@tonic-gate if (ttype == type && tclass == class && 2517c478bd9Sstevel@tonic-gate ns_samename(tname, name) == 1) 2527c478bd9Sstevel@tonic-gate return (1); 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate return (0); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2579525b14bSRao Shoaib /*% 2587c478bd9Sstevel@tonic-gate * is there a 1:1 mapping of (name,type,class) 2597c478bd9Sstevel@tonic-gate * in (buf1,eom1) and (buf2,eom2)? 2609525b14bSRao Shoaib * 2617c478bd9Sstevel@tonic-gate * returns: 2629525b14bSRao Shoaib *\li -1 : format error 2639525b14bSRao Shoaib *\li 0 : not a 1:1 mapping 2649525b14bSRao Shoaib *\li >0 : is a 1:1 mapping 2659525b14bSRao Shoaib * 2667c478bd9Sstevel@tonic-gate * author: 2679525b14bSRao Shoaib *\li paul vixie, 29may94 2687c478bd9Sstevel@tonic-gate */ 2697c478bd9Sstevel@tonic-gate int 2707c478bd9Sstevel@tonic-gate res_queriesmatch(const u_char *buf1, const u_char *eom1, 2717c478bd9Sstevel@tonic-gate const u_char *buf2, const u_char *eom2) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate const u_char *cp = buf1 + HFIXEDSZ; 2747c478bd9Sstevel@tonic-gate int qdcount = ntohs(((const HEADER*)buf1)->qdcount); 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) 2777c478bd9Sstevel@tonic-gate return (-1); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * Only header section present in replies to 2817c478bd9Sstevel@tonic-gate * dynamic update packets. 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate if ((((const HEADER *)buf1)->opcode == ns_o_update) && 2847c478bd9Sstevel@tonic-gate (((const HEADER *)buf2)->opcode == ns_o_update)) 2857c478bd9Sstevel@tonic-gate return (1); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) 2887c478bd9Sstevel@tonic-gate return (0); 2897c478bd9Sstevel@tonic-gate while (qdcount-- > 0) { 2907c478bd9Sstevel@tonic-gate char tname[MAXDNAME+1]; 2917c478bd9Sstevel@tonic-gate int n, ttype, tclass; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate n = dn_expand(buf1, eom1, cp, tname, sizeof tname); 2947c478bd9Sstevel@tonic-gate if (n < 0) 2957c478bd9Sstevel@tonic-gate return (-1); 2967c478bd9Sstevel@tonic-gate cp += n; 2977c478bd9Sstevel@tonic-gate if (cp + 2 * INT16SZ > eom1) 2987c478bd9Sstevel@tonic-gate return (-1); 2997c478bd9Sstevel@tonic-gate ttype = ns_get16(cp); cp += INT16SZ; 3007c478bd9Sstevel@tonic-gate tclass = ns_get16(cp); cp += INT16SZ; 3017c478bd9Sstevel@tonic-gate if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) 3027c478bd9Sstevel@tonic-gate return (0); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate return (1); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate int 3087c478bd9Sstevel@tonic-gate res_nsend(res_state statp, 3097c478bd9Sstevel@tonic-gate const u_char *buf, int buflen, u_char *ans, int anssiz) 3107c478bd9Sstevel@tonic-gate { 3119525b14bSRao Shoaib int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n; 3127c478bd9Sstevel@tonic-gate char abuf[NI_MAXHOST]; 3137c478bd9Sstevel@tonic-gate 3149525b14bSRao Shoaib #ifdef USE_POLL 3157c478bd9Sstevel@tonic-gate highestFD = sysconf(_SC_OPEN_MAX) - 1; 3167c478bd9Sstevel@tonic-gate #endif 3177c478bd9Sstevel@tonic-gate 3189525b14bSRao Shoaib /* No name servers or res_init() failure */ 319c16fc660Ssm if (statp->nscount == 0 || EXT(statp).ext == NULL) { 3207c478bd9Sstevel@tonic-gate errno = ESRCH; 3217c478bd9Sstevel@tonic-gate return (-1); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate if (anssiz < HFIXEDSZ) { 3247c478bd9Sstevel@tonic-gate errno = EINVAL; 3257c478bd9Sstevel@tonic-gate return (-1); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), 3287c478bd9Sstevel@tonic-gate (stdout, ";; res_send()\n"), buf, buflen); 3297c478bd9Sstevel@tonic-gate v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; 3307c478bd9Sstevel@tonic-gate gotsomewhere = 0; 3317c478bd9Sstevel@tonic-gate terrno = ETIMEDOUT; 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * If the ns_addr_list in the resolver context has changed, then 3357c478bd9Sstevel@tonic-gate * invalidate our cached copy and the associated timing data. 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate if (EXT(statp).nscount != 0) { 3387c478bd9Sstevel@tonic-gate int needclose = 0; 3397c478bd9Sstevel@tonic-gate struct sockaddr_storage peer; 3407c478bd9Sstevel@tonic-gate ISC_SOCKLEN_T peerlen; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate if (EXT(statp).nscount != statp->nscount) 3437c478bd9Sstevel@tonic-gate needclose++; 3447c478bd9Sstevel@tonic-gate else 3457c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 3467c478bd9Sstevel@tonic-gate if (statp->nsaddr_list[ns].sin_family && 3477c478bd9Sstevel@tonic-gate !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], 3487c478bd9Sstevel@tonic-gate (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { 3497c478bd9Sstevel@tonic-gate needclose++; 3507c478bd9Sstevel@tonic-gate break; 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate if (EXT(statp).nssocks[ns] == -1) 3547c478bd9Sstevel@tonic-gate continue; 3557c478bd9Sstevel@tonic-gate peerlen = sizeof(peer); 3569525b14bSRao Shoaib if (getpeername(EXT(statp).nssocks[ns], 3577c478bd9Sstevel@tonic-gate (struct sockaddr *)&peer, &peerlen) < 0) { 3587c478bd9Sstevel@tonic-gate needclose++; 3597c478bd9Sstevel@tonic-gate break; 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate if (!sock_eq((struct sockaddr *)&peer, 3627c478bd9Sstevel@tonic-gate get_nsaddr(statp, ns))) { 3637c478bd9Sstevel@tonic-gate needclose++; 3647c478bd9Sstevel@tonic-gate break; 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate if (needclose) { 3687c478bd9Sstevel@tonic-gate res_nclose(statp); 3697c478bd9Sstevel@tonic-gate EXT(statp).nscount = 0; 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* 3747c478bd9Sstevel@tonic-gate * Maybe initialize our private copy of the ns_addr_list. 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate if (EXT(statp).nscount == 0) { 3777c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 3787c478bd9Sstevel@tonic-gate EXT(statp).nstimes[ns] = RES_MAXTIME; 3797c478bd9Sstevel@tonic-gate EXT(statp).nssocks[ns] = -1; 3807c478bd9Sstevel@tonic-gate if (!statp->nsaddr_list[ns].sin_family) 3817c478bd9Sstevel@tonic-gate continue; 3827c478bd9Sstevel@tonic-gate EXT(statp).ext->nsaddrs[ns].sin = 3837c478bd9Sstevel@tonic-gate statp->nsaddr_list[ns]; 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate EXT(statp).nscount = statp->nscount; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* 3897c478bd9Sstevel@tonic-gate * Some resolvers want to even out the load on their nameservers. 3907c478bd9Sstevel@tonic-gate * Note that RES_BLAST overrides RES_ROTATE. 3917c478bd9Sstevel@tonic-gate */ 3929525b14bSRao Shoaib if ((statp->options & RES_ROTATE) != 0U && 3939525b14bSRao Shoaib (statp->options & RES_BLAST) == 0U) { 3947c478bd9Sstevel@tonic-gate union res_sockaddr_union inu; 3957c478bd9Sstevel@tonic-gate struct sockaddr_in ina; 3967c478bd9Sstevel@tonic-gate int lastns = statp->nscount - 1; 3977c478bd9Sstevel@tonic-gate int fd; 3987c478bd9Sstevel@tonic-gate u_int16_t nstime; 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate if (EXT(statp).ext != NULL) 4017c478bd9Sstevel@tonic-gate inu = EXT(statp).ext->nsaddrs[0]; 4027c478bd9Sstevel@tonic-gate ina = statp->nsaddr_list[0]; 4037c478bd9Sstevel@tonic-gate fd = EXT(statp).nssocks[0]; 4047c478bd9Sstevel@tonic-gate nstime = EXT(statp).nstimes[0]; 4057c478bd9Sstevel@tonic-gate for (ns = 0; ns < lastns; ns++) { 4067c478bd9Sstevel@tonic-gate if (EXT(statp).ext != NULL) 4079525b14bSRao Shoaib EXT(statp).ext->nsaddrs[ns] = 4087c478bd9Sstevel@tonic-gate EXT(statp).ext->nsaddrs[ns + 1]; 4097c478bd9Sstevel@tonic-gate statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; 4107c478bd9Sstevel@tonic-gate EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; 4117c478bd9Sstevel@tonic-gate EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate if (EXT(statp).ext != NULL) 4147c478bd9Sstevel@tonic-gate EXT(statp).ext->nsaddrs[lastns] = inu; 4157c478bd9Sstevel@tonic-gate statp->nsaddr_list[lastns] = ina; 4167c478bd9Sstevel@tonic-gate EXT(statp).nssocks[lastns] = fd; 4177c478bd9Sstevel@tonic-gate EXT(statp).nstimes[lastns] = nstime; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * Send request, RETRY times, or until successful. 4227c478bd9Sstevel@tonic-gate */ 4239525b14bSRao Shoaib for (tries = 0; tries < statp->retry; tries++) { 4247c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 4257c478bd9Sstevel@tonic-gate struct sockaddr *nsap; 4267c478bd9Sstevel@tonic-gate int nsaplen; 4277c478bd9Sstevel@tonic-gate nsap = get_nsaddr(statp, ns); 4287c478bd9Sstevel@tonic-gate nsaplen = get_salen(nsap); 4297c478bd9Sstevel@tonic-gate statp->_flags &= ~RES_F_LASTMASK; 4307c478bd9Sstevel@tonic-gate statp->_flags |= (ns << RES_F_LASTSHIFT); 4317c478bd9Sstevel@tonic-gate same_ns: 4327c478bd9Sstevel@tonic-gate if (statp->qhook) { 4337c478bd9Sstevel@tonic-gate int done = 0, loops = 0; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate do { 4367c478bd9Sstevel@tonic-gate res_sendhookact act; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate act = (*statp->qhook)(&nsap, &buf, &buflen, 4397c478bd9Sstevel@tonic-gate ans, anssiz, &resplen); 4407c478bd9Sstevel@tonic-gate switch (act) { 4417c478bd9Sstevel@tonic-gate case res_goahead: 4427c478bd9Sstevel@tonic-gate done = 1; 4437c478bd9Sstevel@tonic-gate break; 4447c478bd9Sstevel@tonic-gate case res_nextns: 4457c478bd9Sstevel@tonic-gate res_nclose(statp); 4467c478bd9Sstevel@tonic-gate goto next_ns; 4477c478bd9Sstevel@tonic-gate case res_done: 4487c478bd9Sstevel@tonic-gate return (resplen); 4497c478bd9Sstevel@tonic-gate case res_modified: 4507c478bd9Sstevel@tonic-gate /* give the hook another try */ 4517c478bd9Sstevel@tonic-gate if (++loops < 42) /*doug adams*/ 4527c478bd9Sstevel@tonic-gate break; 4537c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 4547c478bd9Sstevel@tonic-gate case res_error: 4557c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 4567c478bd9Sstevel@tonic-gate default: 4577c478bd9Sstevel@tonic-gate goto fail; 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate } while (!done); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate Dprint(((statp->options & RES_DEBUG) && 4637c478bd9Sstevel@tonic-gate getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), 4647c478bd9Sstevel@tonic-gate NULL, 0, niflags) == 0), 4657c478bd9Sstevel@tonic-gate (stdout, ";; Querying server (# %d) address = %s\n", 4667c478bd9Sstevel@tonic-gate ns + 1, abuf)); 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate if (v_circuit) { 4707c478bd9Sstevel@tonic-gate /* Use VC; at most one attempt per server. */ 4719525b14bSRao Shoaib tries = statp->retry; 4727c478bd9Sstevel@tonic-gate n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, 4737c478bd9Sstevel@tonic-gate ns); 4747c478bd9Sstevel@tonic-gate if (n < 0) 4757c478bd9Sstevel@tonic-gate goto fail; 4767c478bd9Sstevel@tonic-gate if (n == 0) 4777c478bd9Sstevel@tonic-gate goto next_ns; 4787c478bd9Sstevel@tonic-gate resplen = n; 4797c478bd9Sstevel@tonic-gate } else { 4807c478bd9Sstevel@tonic-gate /* Use datagrams. */ 4817c478bd9Sstevel@tonic-gate n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, 4829525b14bSRao Shoaib ns, tries, &v_circuit, &gotsomewhere); 4837c478bd9Sstevel@tonic-gate if (n < 0) 4847c478bd9Sstevel@tonic-gate goto fail; 4857c478bd9Sstevel@tonic-gate if (n == 0) 4867c478bd9Sstevel@tonic-gate goto next_ns; 4877c478bd9Sstevel@tonic-gate if (v_circuit) 4887c478bd9Sstevel@tonic-gate goto same_ns; 4897c478bd9Sstevel@tonic-gate resplen = n; 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate Dprint((statp->options & RES_DEBUG) || 4937c478bd9Sstevel@tonic-gate ((statp->pfcode & RES_PRF_REPLY) && 4947c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_HEAD1)), 4957c478bd9Sstevel@tonic-gate (stdout, ";; got answer:\n")); 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 4987c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 4997c478bd9Sstevel@tonic-gate (stdout, "%s", ""), 5007c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * If we have temporarily opened a virtual circuit, 5047c478bd9Sstevel@tonic-gate * or if we haven't been asked to keep a socket open, 5057c478bd9Sstevel@tonic-gate * close the socket. 5067c478bd9Sstevel@tonic-gate */ 5079525b14bSRao Shoaib if ((v_circuit && (statp->options & RES_USEVC) == 0U) || 5089525b14bSRao Shoaib (statp->options & RES_STAYOPEN) == 0U) { 5097c478bd9Sstevel@tonic-gate res_nclose(statp); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate if (statp->rhook) { 5127c478bd9Sstevel@tonic-gate int done = 0, loops = 0; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate do { 5157c478bd9Sstevel@tonic-gate res_sendhookact act; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate act = (*statp->rhook)(nsap, buf, buflen, 5187c478bd9Sstevel@tonic-gate ans, anssiz, &resplen); 5197c478bd9Sstevel@tonic-gate switch (act) { 5207c478bd9Sstevel@tonic-gate case res_goahead: 5217c478bd9Sstevel@tonic-gate case res_done: 5227c478bd9Sstevel@tonic-gate done = 1; 5237c478bd9Sstevel@tonic-gate break; 5247c478bd9Sstevel@tonic-gate case res_nextns: 5257c478bd9Sstevel@tonic-gate res_nclose(statp); 5267c478bd9Sstevel@tonic-gate goto next_ns; 5277c478bd9Sstevel@tonic-gate case res_modified: 5287c478bd9Sstevel@tonic-gate /* give the hook another try */ 5297c478bd9Sstevel@tonic-gate if (++loops < 42) /*doug adams*/ 5307c478bd9Sstevel@tonic-gate break; 5317c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 5327c478bd9Sstevel@tonic-gate case res_error: 5337c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 5347c478bd9Sstevel@tonic-gate default: 5357c478bd9Sstevel@tonic-gate goto fail; 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate } while (!done); 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate return (resplen); 5417c478bd9Sstevel@tonic-gate next_ns: ; 5427c478bd9Sstevel@tonic-gate } /*foreach ns*/ 5437c478bd9Sstevel@tonic-gate } /*foreach retry*/ 5447c478bd9Sstevel@tonic-gate res_nclose(statp); 5457c478bd9Sstevel@tonic-gate if (!v_circuit) { 5467c478bd9Sstevel@tonic-gate if (!gotsomewhere) 5479525b14bSRao Shoaib errno = ECONNREFUSED; /*%< no nameservers found */ 5487c478bd9Sstevel@tonic-gate else 5499525b14bSRao Shoaib errno = ETIMEDOUT; /*%< no answer obtained */ 5507c478bd9Sstevel@tonic-gate } else 5517c478bd9Sstevel@tonic-gate errno = terrno; 5527c478bd9Sstevel@tonic-gate return (-1); 5537c478bd9Sstevel@tonic-gate fail: 5547c478bd9Sstevel@tonic-gate res_nclose(statp); 5557c478bd9Sstevel@tonic-gate return (-1); 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate /* Private */ 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate static int 5617c478bd9Sstevel@tonic-gate get_salen(sa) 5627c478bd9Sstevel@tonic-gate const struct sockaddr *sa; 5637c478bd9Sstevel@tonic-gate { 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate #ifdef HAVE_SA_LEN 5667c478bd9Sstevel@tonic-gate /* There are people do not set sa_len. Be forgiving to them. */ 5677c478bd9Sstevel@tonic-gate if (sa->sa_len) 5687c478bd9Sstevel@tonic-gate return (sa->sa_len); 5697c478bd9Sstevel@tonic-gate #endif 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate if (sa->sa_family == AF_INET) 5727c478bd9Sstevel@tonic-gate return (sizeof(struct sockaddr_in)); 5737c478bd9Sstevel@tonic-gate else if (sa->sa_family == AF_INET6) 5747c478bd9Sstevel@tonic-gate return (sizeof(struct sockaddr_in6)); 5757c478bd9Sstevel@tonic-gate else 5769525b14bSRao Shoaib return (0); /*%< unknown, die on connect */ 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5799525b14bSRao Shoaib /*% 5807c478bd9Sstevel@tonic-gate * pick appropriate nsaddr_list for use. see res_init() for initialization. 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate static struct sockaddr * 5837c478bd9Sstevel@tonic-gate get_nsaddr(statp, n) 5847c478bd9Sstevel@tonic-gate res_state statp; 5857c478bd9Sstevel@tonic-gate size_t n; 5867c478bd9Sstevel@tonic-gate { 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * - EXT(statp).ext->nsaddrs[n] holds an address that is larger 5917c478bd9Sstevel@tonic-gate * than struct sockaddr, and 5927c478bd9Sstevel@tonic-gate * - user code did not update statp->nsaddr_list[n]. 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; 5957c478bd9Sstevel@tonic-gate } else { 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * - user code updated statp->nsaddr_list[n], or 5987c478bd9Sstevel@tonic-gate * - statp->nsaddr_list[n] has the same content as 5997c478bd9Sstevel@tonic-gate * EXT(statp).ext->nsaddrs[n]. 6007c478bd9Sstevel@tonic-gate */ 6017c478bd9Sstevel@tonic-gate return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate static int 6067c478bd9Sstevel@tonic-gate send_vc(res_state statp, 6077c478bd9Sstevel@tonic-gate const u_char *buf, int buflen, u_char *ans, int anssiz, 6087c478bd9Sstevel@tonic-gate int *terrno, int ns) 6097c478bd9Sstevel@tonic-gate { 6107c478bd9Sstevel@tonic-gate const HEADER *hp = (const HEADER *) buf; 6117c478bd9Sstevel@tonic-gate HEADER *anhp = (HEADER *) ans; 6127c478bd9Sstevel@tonic-gate struct sockaddr *nsap; 6137c478bd9Sstevel@tonic-gate int nsaplen; 6147c478bd9Sstevel@tonic-gate int truncating, connreset, resplen, n; 6157c478bd9Sstevel@tonic-gate struct iovec iov[2]; 6167c478bd9Sstevel@tonic-gate u_short len; 6177c478bd9Sstevel@tonic-gate u_char *cp; 6187c478bd9Sstevel@tonic-gate void *tmp; 6199525b14bSRao Shoaib #ifdef SO_NOSIGPIPE 6209525b14bSRao Shoaib int on = 1; 6219525b14bSRao Shoaib #endif 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate nsap = get_nsaddr(statp, ns); 6247c478bd9Sstevel@tonic-gate nsaplen = get_salen(nsap); 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate connreset = 0; 6277c478bd9Sstevel@tonic-gate same_ns: 6287c478bd9Sstevel@tonic-gate truncating = 0; 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate /* Are we still talking to whom we want to talk to? */ 6317c478bd9Sstevel@tonic-gate if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { 6327c478bd9Sstevel@tonic-gate struct sockaddr_storage peer; 6337c478bd9Sstevel@tonic-gate ISC_SOCKLEN_T size = sizeof peer; 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate if (getpeername(statp->_vcsock, 6367c478bd9Sstevel@tonic-gate (struct sockaddr *)&peer, &size) < 0 || 6377c478bd9Sstevel@tonic-gate !sock_eq((struct sockaddr *)&peer, nsap)) { 6387c478bd9Sstevel@tonic-gate res_nclose(statp); 6397c478bd9Sstevel@tonic-gate statp->_flags &= ~RES_F_VC; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { 6447c478bd9Sstevel@tonic-gate if (statp->_vcsock >= 0) 6457c478bd9Sstevel@tonic-gate res_nclose(statp); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); 6487c478bd9Sstevel@tonic-gate if (statp->_vcsock > highestFD) { 6497c478bd9Sstevel@tonic-gate res_nclose(statp); 6507c478bd9Sstevel@tonic-gate errno = ENOTSOCK; 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate if (statp->_vcsock < 0) { 6539525b14bSRao Shoaib switch (errno) { 6549525b14bSRao Shoaib case EPROTONOSUPPORT: 6559525b14bSRao Shoaib #ifdef EPFNOSUPPORT 6569525b14bSRao Shoaib case EPFNOSUPPORT: 6579525b14bSRao Shoaib #endif 6589525b14bSRao Shoaib case EAFNOSUPPORT: 6599525b14bSRao Shoaib Perror(statp, stderr, "socket(vc)", errno); 6609525b14bSRao Shoaib return (0); 6619525b14bSRao Shoaib default: 6629525b14bSRao Shoaib *terrno = errno; 6639525b14bSRao Shoaib Perror(statp, stderr, "socket(vc)", errno); 6649525b14bSRao Shoaib return (-1); 6659525b14bSRao Shoaib } 6667c478bd9Sstevel@tonic-gate } 6679525b14bSRao Shoaib #ifdef SO_NOSIGPIPE 6689525b14bSRao Shoaib /* 6699525b14bSRao Shoaib * Disable generation of SIGPIPE when writing to a closed 6709525b14bSRao Shoaib * socket. Write should return -1 and set errno to EPIPE 6719525b14bSRao Shoaib * instead. 6729525b14bSRao Shoaib * 6739525b14bSRao Shoaib * Push on even if setsockopt(SO_NOSIGPIPE) fails. 6749525b14bSRao Shoaib */ 6759525b14bSRao Shoaib (void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on, 6769525b14bSRao Shoaib sizeof(on)); 677*b3700b07SGordon Ross #endif 678*b3700b07SGordon Ross #ifdef TCP_CONN_ABORT_THRESHOLD 679*b3700b07SGordon Ross /* 680*b3700b07SGordon Ross * The default connection timeout is over two minutes. 681*b3700b07SGordon Ross * We need something more reasonable here. The default 682*b3700b07SGordon Ross * retrans value is 5 sec., then 10, 20, 40, on retries. 683*b3700b07SGordon Ross * TCP connect does its own retries, so we want just one 684*b3700b07SGordon Ross * reasonable timeout value. Using 2X retrans, which 685*b3700b07SGordon Ross * gives us a 10 sec. connect timeout. If we're waiting 686*b3700b07SGordon Ross * that long to connect, we probably want to give up and 687*b3700b07SGordon Ross * try the next DNS server in our list. 688*b3700b07SGordon Ross * 689*b3700b07SGordon Ross * It might be reasonable to do this for all callers, 690*b3700b07SGordon Ross * but for now do it only when we see MS_INTEROP in the 691*b3700b07SGordon Ross * environment (set in smbd and idmapd) 692*b3700b07SGordon Ross */ 693*b3700b07SGordon Ross if (getenv("MS_INTEROP") != NULL) { 694*b3700b07SGordon Ross int conn_tmo; 695*b3700b07SGordon Ross conn_tmo = statp->retrans * 2000; /* mSec */ 696*b3700b07SGordon Ross (void)setsockopt(statp->_vcsock, IPPROTO_TCP, 697*b3700b07SGordon Ross TCP_CONN_ABORT_THRESHOLD, &conn_tmo, 698*b3700b07SGordon Ross sizeof(conn_tmo)); 699*b3700b07SGordon Ross } 7009525b14bSRao Shoaib #endif 7017c478bd9Sstevel@tonic-gate errno = 0; 7027c478bd9Sstevel@tonic-gate if (connect(statp->_vcsock, nsap, nsaplen) < 0) { 7037c478bd9Sstevel@tonic-gate *terrno = errno; 7047c478bd9Sstevel@tonic-gate Aerror(statp, stderr, "connect/vc", errno, nsap, 7057c478bd9Sstevel@tonic-gate nsaplen); 7067c478bd9Sstevel@tonic-gate res_nclose(statp); 7077c478bd9Sstevel@tonic-gate return (0); 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate statp->_flags |= RES_F_VC; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate /* 7137c478bd9Sstevel@tonic-gate * Send length & message 7147c478bd9Sstevel@tonic-gate */ 7157c478bd9Sstevel@tonic-gate ns_put16((u_short)buflen, (u_char*)&len); 7167c478bd9Sstevel@tonic-gate iov[0] = evConsIovec(&len, INT16SZ); 7177c478bd9Sstevel@tonic-gate DE_CONST(buf, tmp); 7187c478bd9Sstevel@tonic-gate iov[1] = evConsIovec(tmp, buflen); 7197c478bd9Sstevel@tonic-gate if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { 7207c478bd9Sstevel@tonic-gate *terrno = errno; 7217c478bd9Sstevel@tonic-gate Perror(statp, stderr, "write failed", errno); 7227c478bd9Sstevel@tonic-gate res_nclose(statp); 7237c478bd9Sstevel@tonic-gate return (0); 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate /* 7267c478bd9Sstevel@tonic-gate * Receive length & response 7277c478bd9Sstevel@tonic-gate */ 7287c478bd9Sstevel@tonic-gate read_len: 7297c478bd9Sstevel@tonic-gate cp = ans; 7307c478bd9Sstevel@tonic-gate len = INT16SZ; 7317c478bd9Sstevel@tonic-gate while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) { 7327c478bd9Sstevel@tonic-gate cp += n; 7339525b14bSRao Shoaib if ((len -= n) == 0) 7347c478bd9Sstevel@tonic-gate break; 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate if (n <= 0) { 7377c478bd9Sstevel@tonic-gate *terrno = errno; 7387c478bd9Sstevel@tonic-gate Perror(statp, stderr, "read failed", errno); 7397c478bd9Sstevel@tonic-gate res_nclose(statp); 7407c478bd9Sstevel@tonic-gate /* 7417c478bd9Sstevel@tonic-gate * A long running process might get its TCP 7427c478bd9Sstevel@tonic-gate * connection reset if the remote server was 7437c478bd9Sstevel@tonic-gate * restarted. Requery the server instead of 7447c478bd9Sstevel@tonic-gate * trying a new one. When there is only one 7457c478bd9Sstevel@tonic-gate * server, this means that a query might work 7467c478bd9Sstevel@tonic-gate * instead of failing. We only allow one reset 7477c478bd9Sstevel@tonic-gate * per query to prevent looping. 7487c478bd9Sstevel@tonic-gate */ 7497c478bd9Sstevel@tonic-gate if (*terrno == ECONNRESET && !connreset) { 7507c478bd9Sstevel@tonic-gate connreset = 1; 7517c478bd9Sstevel@tonic-gate res_nclose(statp); 7527c478bd9Sstevel@tonic-gate goto same_ns; 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate res_nclose(statp); 7557c478bd9Sstevel@tonic-gate return (0); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate resplen = ns_get16(ans); 7587c478bd9Sstevel@tonic-gate if (resplen > anssiz) { 7597c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 7607c478bd9Sstevel@tonic-gate (stdout, ";; response truncated\n") 7617c478bd9Sstevel@tonic-gate ); 7627c478bd9Sstevel@tonic-gate truncating = 1; 7637c478bd9Sstevel@tonic-gate len = anssiz; 7647c478bd9Sstevel@tonic-gate } else 7657c478bd9Sstevel@tonic-gate len = resplen; 7667c478bd9Sstevel@tonic-gate if (len < HFIXEDSZ) { 7677c478bd9Sstevel@tonic-gate /* 7687c478bd9Sstevel@tonic-gate * Undersized message. 7697c478bd9Sstevel@tonic-gate */ 7707c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 7717c478bd9Sstevel@tonic-gate (stdout, ";; undersized: %d\n", len)); 7727c478bd9Sstevel@tonic-gate *terrno = EMSGSIZE; 7737c478bd9Sstevel@tonic-gate res_nclose(statp); 7747c478bd9Sstevel@tonic-gate return (0); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate cp = ans; 7777c478bd9Sstevel@tonic-gate while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ 7787c478bd9Sstevel@tonic-gate cp += n; 7797c478bd9Sstevel@tonic-gate len -= n; 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate if (n <= 0) { 7827c478bd9Sstevel@tonic-gate *terrno = errno; 7837c478bd9Sstevel@tonic-gate Perror(statp, stderr, "read(vc)", errno); 7847c478bd9Sstevel@tonic-gate res_nclose(statp); 7857c478bd9Sstevel@tonic-gate return (0); 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate if (truncating) { 7887c478bd9Sstevel@tonic-gate /* 7897c478bd9Sstevel@tonic-gate * Flush rest of answer so connection stays in synch. 7907c478bd9Sstevel@tonic-gate */ 7917c478bd9Sstevel@tonic-gate anhp->tc = 1; 7927c478bd9Sstevel@tonic-gate len = resplen - anssiz; 7937c478bd9Sstevel@tonic-gate while (len != 0) { 7947c478bd9Sstevel@tonic-gate char junk[PACKETSZ]; 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate n = read(statp->_vcsock, junk, 7977c478bd9Sstevel@tonic-gate (len > sizeof junk) ? sizeof junk : len); 7987c478bd9Sstevel@tonic-gate if (n > 0) 7997c478bd9Sstevel@tonic-gate len -= n; 8007c478bd9Sstevel@tonic-gate else 8017c478bd9Sstevel@tonic-gate break; 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate /* 8057c478bd9Sstevel@tonic-gate * If the calling applicating has bailed out of 8067c478bd9Sstevel@tonic-gate * a previous call and failed to arrange to have 8077c478bd9Sstevel@tonic-gate * the circuit closed or the server has got 8087c478bd9Sstevel@tonic-gate * itself confused, then drop the packet and 8097c478bd9Sstevel@tonic-gate * wait for the correct one. 8107c478bd9Sstevel@tonic-gate */ 8117c478bd9Sstevel@tonic-gate if (hp->id != anhp->id) { 8127c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 8137c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 8147c478bd9Sstevel@tonic-gate (stdout, ";; old answer (unexpected):\n"), 8157c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz: resplen); 8167c478bd9Sstevel@tonic-gate goto read_len; 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate /* 8207c478bd9Sstevel@tonic-gate * All is well, or the error is fatal. Signal that the 8217c478bd9Sstevel@tonic-gate * next nameserver ought not be tried. 8227c478bd9Sstevel@tonic-gate */ 8237c478bd9Sstevel@tonic-gate return (resplen); 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate static int 8279525b14bSRao Shoaib send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, 8289525b14bSRao Shoaib int anssiz, int *terrno, int ns, int tries, int *v_circuit, 8299525b14bSRao Shoaib int *gotsomewhere) 8307c478bd9Sstevel@tonic-gate { 8317c478bd9Sstevel@tonic-gate const HEADER *hp = (const HEADER *) buf; 8327c478bd9Sstevel@tonic-gate HEADER *anhp = (HEADER *) ans; 8337c478bd9Sstevel@tonic-gate const struct sockaddr *nsap; 8347c478bd9Sstevel@tonic-gate int nsaplen; 8357c478bd9Sstevel@tonic-gate struct timespec now, timeout, finish; 8367c478bd9Sstevel@tonic-gate struct sockaddr_storage from; 8377c478bd9Sstevel@tonic-gate ISC_SOCKLEN_T fromlen; 8387c478bd9Sstevel@tonic-gate int resplen, seconds, n, s; 8399525b14bSRao Shoaib #ifdef USE_POLL 8409525b14bSRao Shoaib int polltimeout; 8417c478bd9Sstevel@tonic-gate struct pollfd pollfd; 8429525b14bSRao Shoaib #else 8439525b14bSRao Shoaib fd_set dsmask; 8447c478bd9Sstevel@tonic-gate #endif 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate nsap = get_nsaddr(statp, ns); 8477c478bd9Sstevel@tonic-gate nsaplen = get_salen(nsap); 8487c478bd9Sstevel@tonic-gate if (EXT(statp).nssocks[ns] == -1) { 8497c478bd9Sstevel@tonic-gate EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); 8507c478bd9Sstevel@tonic-gate if (EXT(statp).nssocks[ns] > highestFD) { 8517c478bd9Sstevel@tonic-gate res_nclose(statp); 8527c478bd9Sstevel@tonic-gate errno = ENOTSOCK; 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate if (EXT(statp).nssocks[ns] < 0) { 8559525b14bSRao Shoaib switch (errno) { 8569525b14bSRao Shoaib case EPROTONOSUPPORT: 8579525b14bSRao Shoaib #ifdef EPFNOSUPPORT 8589525b14bSRao Shoaib case EPFNOSUPPORT: 8599525b14bSRao Shoaib #endif 8609525b14bSRao Shoaib case EAFNOSUPPORT: 8619525b14bSRao Shoaib Perror(statp, stderr, "socket(dg)", errno); 8629525b14bSRao Shoaib return (0); 8639525b14bSRao Shoaib default: 8649525b14bSRao Shoaib *terrno = errno; 8659525b14bSRao Shoaib Perror(statp, stderr, "socket(dg)", errno); 8669525b14bSRao Shoaib return (-1); 8679525b14bSRao Shoaib } 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate #ifndef CANNOT_CONNECT_DGRAM 8707c478bd9Sstevel@tonic-gate /* 8717c478bd9Sstevel@tonic-gate * On a 4.3BSD+ machine (client and server, 8727c478bd9Sstevel@tonic-gate * actually), sending to a nameserver datagram 8737c478bd9Sstevel@tonic-gate * port with no nameserver will cause an 8747c478bd9Sstevel@tonic-gate * ICMP port unreachable message to be returned. 8757c478bd9Sstevel@tonic-gate * If our datagram socket is "connected" to the 8767c478bd9Sstevel@tonic-gate * server, we get an ECONNREFUSED error on the next 8777c478bd9Sstevel@tonic-gate * socket operation, and select returns if the 8787c478bd9Sstevel@tonic-gate * error message is received. We can thus detect 8797c478bd9Sstevel@tonic-gate * the absence of a nameserver without timing out. 8807c478bd9Sstevel@tonic-gate */ 8817c478bd9Sstevel@tonic-gate if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { 8827c478bd9Sstevel@tonic-gate Aerror(statp, stderr, "connect(dg)", errno, nsap, 8837c478bd9Sstevel@tonic-gate nsaplen); 8847c478bd9Sstevel@tonic-gate res_nclose(statp); 8857c478bd9Sstevel@tonic-gate return (0); 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate #endif /* !CANNOT_CONNECT_DGRAM */ 8887c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 8897c478bd9Sstevel@tonic-gate (stdout, ";; new DG socket\n")) 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate s = EXT(statp).nssocks[ns]; 8927c478bd9Sstevel@tonic-gate #ifndef CANNOT_CONNECT_DGRAM 8937c478bd9Sstevel@tonic-gate if (send(s, (const char*)buf, buflen, 0) != buflen) { 8947c478bd9Sstevel@tonic-gate Perror(statp, stderr, "send", errno); 8957c478bd9Sstevel@tonic-gate res_nclose(statp); 8967c478bd9Sstevel@tonic-gate return (0); 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate #else /* !CANNOT_CONNECT_DGRAM */ 8997c478bd9Sstevel@tonic-gate if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) 9007c478bd9Sstevel@tonic-gate { 9017c478bd9Sstevel@tonic-gate Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 9027c478bd9Sstevel@tonic-gate res_nclose(statp); 9037c478bd9Sstevel@tonic-gate return (0); 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate #endif /* !CANNOT_CONNECT_DGRAM */ 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate /* 9087c478bd9Sstevel@tonic-gate * Wait for reply. 9097c478bd9Sstevel@tonic-gate */ 9109525b14bSRao Shoaib seconds = (statp->retrans << tries); 9117c478bd9Sstevel@tonic-gate if (ns > 0) 9127c478bd9Sstevel@tonic-gate seconds /= statp->nscount; 9137c478bd9Sstevel@tonic-gate if (seconds <= 0) 9147c478bd9Sstevel@tonic-gate seconds = 1; 9157c478bd9Sstevel@tonic-gate now = evNowTime(); 9167c478bd9Sstevel@tonic-gate timeout = evConsTime(seconds, 0); 9177c478bd9Sstevel@tonic-gate finish = evAddTime(now, timeout); 9187c478bd9Sstevel@tonic-gate goto nonow; 9197c478bd9Sstevel@tonic-gate wait: 9207c478bd9Sstevel@tonic-gate now = evNowTime(); 9217c478bd9Sstevel@tonic-gate nonow: 9229525b14bSRao Shoaib #ifndef USE_POLL 9239525b14bSRao Shoaib FD_ZERO(&dsmask); 9249525b14bSRao Shoaib FD_SET(s, &dsmask); 9259525b14bSRao Shoaib if (evCmpTime(finish, now) > 0) 9269525b14bSRao Shoaib timeout = evSubTime(finish, now); 9279525b14bSRao Shoaib else 9289525b14bSRao Shoaib timeout = evConsTime(0, 0); 9299525b14bSRao Shoaib n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); 9309525b14bSRao Shoaib #else 9317c478bd9Sstevel@tonic-gate timeout = evSubTime(finish, now); 9327c478bd9Sstevel@tonic-gate if (timeout.tv_sec < 0) 9337c478bd9Sstevel@tonic-gate timeout = evConsTime(0, 0); 9347c478bd9Sstevel@tonic-gate polltimeout = 1000*timeout.tv_sec + 9357c478bd9Sstevel@tonic-gate timeout.tv_nsec/1000000; 9367c478bd9Sstevel@tonic-gate pollfd.fd = s; 9377c478bd9Sstevel@tonic-gate pollfd.events = POLLRDNORM; 9387c478bd9Sstevel@tonic-gate n = poll(&pollfd, 1, polltimeout); 9399525b14bSRao Shoaib #endif /* USE_POLL */ 9409525b14bSRao Shoaib 9417c478bd9Sstevel@tonic-gate if (n == 0) { 9427c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); 9437c478bd9Sstevel@tonic-gate *gotsomewhere = 1; 9447c478bd9Sstevel@tonic-gate return (0); 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate if (n < 0) { 9477c478bd9Sstevel@tonic-gate if (errno == EINTR) 9487c478bd9Sstevel@tonic-gate goto wait; 9499525b14bSRao Shoaib #ifndef USE_POLL 9507c478bd9Sstevel@tonic-gate Perror(statp, stderr, "select", errno); 9519525b14bSRao Shoaib #else 9529525b14bSRao Shoaib Perror(statp, stderr, "poll", errno); 9539525b14bSRao Shoaib #endif /* USE_POLL */ 9547c478bd9Sstevel@tonic-gate res_nclose(statp); 9557c478bd9Sstevel@tonic-gate return (0); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate errno = 0; 9587c478bd9Sstevel@tonic-gate fromlen = sizeof(from); 9597c478bd9Sstevel@tonic-gate resplen = recvfrom(s, (char*)ans, anssiz,0, 9607c478bd9Sstevel@tonic-gate (struct sockaddr *)&from, &fromlen); 9617c478bd9Sstevel@tonic-gate if (resplen <= 0) { 9627c478bd9Sstevel@tonic-gate Perror(statp, stderr, "recvfrom", errno); 9637c478bd9Sstevel@tonic-gate res_nclose(statp); 9647c478bd9Sstevel@tonic-gate return (0); 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate *gotsomewhere = 1; 9677c478bd9Sstevel@tonic-gate if (resplen < HFIXEDSZ) { 9687c478bd9Sstevel@tonic-gate /* 9697c478bd9Sstevel@tonic-gate * Undersized message. 9707c478bd9Sstevel@tonic-gate */ 9717c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 9727c478bd9Sstevel@tonic-gate (stdout, ";; undersized: %d\n", 9737c478bd9Sstevel@tonic-gate resplen)); 9747c478bd9Sstevel@tonic-gate *terrno = EMSGSIZE; 9757c478bd9Sstevel@tonic-gate res_nclose(statp); 9767c478bd9Sstevel@tonic-gate return (0); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate if (hp->id != anhp->id) { 9797c478bd9Sstevel@tonic-gate /* 9807c478bd9Sstevel@tonic-gate * response from old query, ignore it. 9817c478bd9Sstevel@tonic-gate * XXX - potential security hazard could 9827c478bd9Sstevel@tonic-gate * be detected here. 9837c478bd9Sstevel@tonic-gate */ 9847c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 9857c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 9867c478bd9Sstevel@tonic-gate (stdout, ";; old answer:\n"), 9877c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 9887c478bd9Sstevel@tonic-gate goto wait; 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate if (!(statp->options & RES_INSECURE1) && 9917c478bd9Sstevel@tonic-gate !res_ourserver_p(statp, (struct sockaddr *)&from)) { 9927c478bd9Sstevel@tonic-gate /* 9937c478bd9Sstevel@tonic-gate * response from wrong server? ignore it. 9947c478bd9Sstevel@tonic-gate * XXX - potential security hazard could 9957c478bd9Sstevel@tonic-gate * be detected here. 9967c478bd9Sstevel@tonic-gate */ 9977c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 9987c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 9997c478bd9Sstevel@tonic-gate (stdout, ";; not our server:\n"), 10007c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 10017c478bd9Sstevel@tonic-gate goto wait; 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate #ifdef RES_USE_EDNS0 10049525b14bSRao Shoaib if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) { 10057c478bd9Sstevel@tonic-gate /* 10067c478bd9Sstevel@tonic-gate * Do not retry if the server do not understand EDNS0. 10077c478bd9Sstevel@tonic-gate * The case has to be captured here, as FORMERR packet do not 10087c478bd9Sstevel@tonic-gate * carry query section, hence res_queriesmatch() returns 0. 10097c478bd9Sstevel@tonic-gate */ 10107c478bd9Sstevel@tonic-gate DprintQ(statp->options & RES_DEBUG, 10117c478bd9Sstevel@tonic-gate (stdout, "server rejected query with EDNS0:\n"), 10127c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 10137c478bd9Sstevel@tonic-gate /* record the error */ 10147c478bd9Sstevel@tonic-gate statp->_flags |= RES_F_EDNS0ERR; 10157c478bd9Sstevel@tonic-gate res_nclose(statp); 10167c478bd9Sstevel@tonic-gate return (0); 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate #endif 10197c478bd9Sstevel@tonic-gate if (!(statp->options & RES_INSECURE2) && 10207c478bd9Sstevel@tonic-gate !res_queriesmatch(buf, buf + buflen, 10217c478bd9Sstevel@tonic-gate ans, ans + anssiz)) { 10227c478bd9Sstevel@tonic-gate /* 10237c478bd9Sstevel@tonic-gate * response contains wrong query? ignore it. 10247c478bd9Sstevel@tonic-gate * XXX - potential security hazard could 10257c478bd9Sstevel@tonic-gate * be detected here. 10267c478bd9Sstevel@tonic-gate */ 10277c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 10287c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 10297c478bd9Sstevel@tonic-gate (stdout, ";; wrong query name:\n"), 10307c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 10317c478bd9Sstevel@tonic-gate goto wait; 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate if (anhp->rcode == SERVFAIL || 10347c478bd9Sstevel@tonic-gate anhp->rcode == NOTIMP || 10357c478bd9Sstevel@tonic-gate anhp->rcode == REFUSED) { 10367c478bd9Sstevel@tonic-gate DprintQ(statp->options & RES_DEBUG, 10377c478bd9Sstevel@tonic-gate (stdout, "server rejected query:\n"), 10387c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 10397c478bd9Sstevel@tonic-gate res_nclose(statp); 10407c478bd9Sstevel@tonic-gate /* don't retry if called from dig */ 10417c478bd9Sstevel@tonic-gate if (!statp->pfcode) 10427c478bd9Sstevel@tonic-gate return (0); 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate if (!(statp->options & RES_IGNTC) && anhp->tc) { 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * To get the rest of answer, 10477c478bd9Sstevel@tonic-gate * use TCP with same server. 10487c478bd9Sstevel@tonic-gate */ 10497c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 10507c478bd9Sstevel@tonic-gate (stdout, ";; truncated answer\n")); 10517c478bd9Sstevel@tonic-gate *v_circuit = 1; 10527c478bd9Sstevel@tonic-gate res_nclose(statp); 10537c478bd9Sstevel@tonic-gate return (1); 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate /* 10567c478bd9Sstevel@tonic-gate * All is well, or the error is fatal. Signal that the 10577c478bd9Sstevel@tonic-gate * next nameserver ought not be tried. 10587c478bd9Sstevel@tonic-gate */ 10597c478bd9Sstevel@tonic-gate return (resplen); 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate static void 10637c478bd9Sstevel@tonic-gate Aerror(const res_state statp, FILE *file, const char *string, int error, 10647c478bd9Sstevel@tonic-gate const struct sockaddr *address, int alen) 10657c478bd9Sstevel@tonic-gate { 10667c478bd9Sstevel@tonic-gate int save = errno; 10677c478bd9Sstevel@tonic-gate char hbuf[NI_MAXHOST]; 10687c478bd9Sstevel@tonic-gate char sbuf[NI_MAXSERV]; 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate alen = alen; 10717c478bd9Sstevel@tonic-gate 10729525b14bSRao Shoaib if ((statp->options & RES_DEBUG) != 0U) { 10737c478bd9Sstevel@tonic-gate if (getnameinfo(address, alen, hbuf, sizeof(hbuf), 10747c478bd9Sstevel@tonic-gate sbuf, sizeof(sbuf), niflags)) { 10757c478bd9Sstevel@tonic-gate strncpy(hbuf, "?", sizeof(hbuf) - 1); 10767c478bd9Sstevel@tonic-gate hbuf[sizeof(hbuf) - 1] = '\0'; 10777c478bd9Sstevel@tonic-gate strncpy(sbuf, "?", sizeof(sbuf) - 1); 10787c478bd9Sstevel@tonic-gate sbuf[sizeof(sbuf) - 1] = '\0'; 10797c478bd9Sstevel@tonic-gate } 10807c478bd9Sstevel@tonic-gate fprintf(file, "res_send: %s ([%s].%s): %s\n", 10817c478bd9Sstevel@tonic-gate string, hbuf, sbuf, strerror(error)); 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate errno = save; 10847c478bd9Sstevel@tonic-gate } 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate static void 10877c478bd9Sstevel@tonic-gate Perror(const res_state statp, FILE *file, const char *string, int error) { 10887c478bd9Sstevel@tonic-gate int save = errno; 10897c478bd9Sstevel@tonic-gate 10909525b14bSRao Shoaib if ((statp->options & RES_DEBUG) != 0U) 10917c478bd9Sstevel@tonic-gate fprintf(file, "res_send: %s: %s\n", 10927c478bd9Sstevel@tonic-gate string, strerror(error)); 10937c478bd9Sstevel@tonic-gate errno = save; 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate static int 10977c478bd9Sstevel@tonic-gate sock_eq(struct sockaddr *a, struct sockaddr *b) { 10987c478bd9Sstevel@tonic-gate struct sockaddr_in *a4, *b4; 10997c478bd9Sstevel@tonic-gate struct sockaddr_in6 *a6, *b6; 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate if (a->sa_family != b->sa_family) 11027c478bd9Sstevel@tonic-gate return 0; 11037c478bd9Sstevel@tonic-gate switch (a->sa_family) { 11047c478bd9Sstevel@tonic-gate case AF_INET: 11057c478bd9Sstevel@tonic-gate a4 = (struct sockaddr_in *)a; 11067c478bd9Sstevel@tonic-gate b4 = (struct sockaddr_in *)b; 11077c478bd9Sstevel@tonic-gate return a4->sin_port == b4->sin_port && 11087c478bd9Sstevel@tonic-gate a4->sin_addr.s_addr == b4->sin_addr.s_addr; 11097c478bd9Sstevel@tonic-gate case AF_INET6: 11107c478bd9Sstevel@tonic-gate a6 = (struct sockaddr_in6 *)a; 11117c478bd9Sstevel@tonic-gate b6 = (struct sockaddr_in6 *)b; 11127c478bd9Sstevel@tonic-gate return a6->sin6_port == b6->sin6_port && 11137c478bd9Sstevel@tonic-gate #ifdef HAVE_SIN6_SCOPE_ID 11147c478bd9Sstevel@tonic-gate a6->sin6_scope_id == b6->sin6_scope_id && 11157c478bd9Sstevel@tonic-gate #endif 11167c478bd9Sstevel@tonic-gate IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); 11177c478bd9Sstevel@tonic-gate default: 11187c478bd9Sstevel@tonic-gate return 0; 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate 11229525b14bSRao Shoaib #if defined(NEED_PSELECT) && !defined(USE_POLL) 11237c478bd9Sstevel@tonic-gate /* XXX needs to move to the porting library. */ 11247c478bd9Sstevel@tonic-gate static int 11257c478bd9Sstevel@tonic-gate pselect(int nfds, void *rfds, void *wfds, void *efds, 11267c478bd9Sstevel@tonic-gate struct timespec *tsp, const sigset_t *sigmask) 11277c478bd9Sstevel@tonic-gate { 11287c478bd9Sstevel@tonic-gate struct timeval tv, *tvp; 11297c478bd9Sstevel@tonic-gate sigset_t sigs; 11307c478bd9Sstevel@tonic-gate int n; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate if (tsp) { 11337c478bd9Sstevel@tonic-gate tvp = &tv; 11347c478bd9Sstevel@tonic-gate tv = evTimeVal(*tsp); 11357c478bd9Sstevel@tonic-gate } else 11367c478bd9Sstevel@tonic-gate tvp = NULL; 11377c478bd9Sstevel@tonic-gate if (sigmask) 11387c478bd9Sstevel@tonic-gate sigprocmask(SIG_SETMASK, sigmask, &sigs); 11397c478bd9Sstevel@tonic-gate n = select(nfds, rfds, wfds, efds, tvp); 11407c478bd9Sstevel@tonic-gate if (sigmask) 11417c478bd9Sstevel@tonic-gate sigprocmask(SIG_SETMASK, &sigs, NULL); 11427c478bd9Sstevel@tonic-gate if (tsp) 11437c478bd9Sstevel@tonic-gate *tsp = evTimeSpec(tv); 11447c478bd9Sstevel@tonic-gate return (n); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate #endif 1147