1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* 7*7c478bd9Sstevel@tonic-gate * Copyright (c) 1985, 1989, 1993 8*7c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 9*7c478bd9Sstevel@tonic-gate * 10*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 11*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 12*7c478bd9Sstevel@tonic-gate * are met: 13*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 14*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 15*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 16*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 17*7c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 18*7c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 19*7c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 20*7c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 21*7c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 22*7c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 23*7c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 24*7c478bd9Sstevel@tonic-gate * without specific prior written permission. 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27*7c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29*7c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30*7c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31*7c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32*7c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33*7c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34*7c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35*7c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36*7c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate /* 40*7c478bd9Sstevel@tonic-gate * Portions Copyright (c) 1993 by Digital Equipment Corporation. 41*7c478bd9Sstevel@tonic-gate * 42*7c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 43*7c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 44*7c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies, and that 45*7c478bd9Sstevel@tonic-gate * the name of Digital Equipment Corporation not be used in advertising or 46*7c478bd9Sstevel@tonic-gate * publicity pertaining to distribution of the document or software without 47*7c478bd9Sstevel@tonic-gate * specific, written prior permission. 48*7c478bd9Sstevel@tonic-gate * 49*7c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 50*7c478bd9Sstevel@tonic-gate * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 51*7c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 52*7c478bd9Sstevel@tonic-gate * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 53*7c478bd9Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 54*7c478bd9Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 55*7c478bd9Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 56*7c478bd9Sstevel@tonic-gate * SOFTWARE. 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 61*7c478bd9Sstevel@tonic-gate * 62*7c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 63*7c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 64*7c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 65*7c478bd9Sstevel@tonic-gate * 66*7c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 67*7c478bd9Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 68*7c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 69*7c478bd9Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 70*7c478bd9Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 71*7c478bd9Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 72*7c478bd9Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 73*7c478bd9Sstevel@tonic-gate * SOFTWARE. 74*7c478bd9Sstevel@tonic-gate */ 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 79*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 80*7c478bd9Sstevel@tonic-gate static const char rcsid[] = "$Id: res_send.c,v 8.52 2003/04/29 02:13:08 marka Exp $"; 81*7c478bd9Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */ 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* 84*7c478bd9Sstevel@tonic-gate * Send query to name server and wait for reply. 85*7c478bd9Sstevel@tonic-gate */ 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate #include "port_before.h" 88*7c478bd9Sstevel@tonic-gate #include "fd_setsize.h" 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 91*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 92*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 93*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 94*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 97*7c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 98*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate #include <errno.h> 101*7c478bd9Sstevel@tonic-gate #include <netdb.h> 102*7c478bd9Sstevel@tonic-gate #include <resolv.h> 103*7c478bd9Sstevel@tonic-gate #include <signal.h> 104*7c478bd9Sstevel@tonic-gate #include <stdio.h> 105*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 106*7c478bd9Sstevel@tonic-gate #include <string.h> 107*7c478bd9Sstevel@tonic-gate #include <unistd.h> 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate #include <isc/eventlib.h> 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate #include "port_after.h" 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate #ifdef SUNW_POLL 114*7c478bd9Sstevel@tonic-gate #include <stropts.h> 115*7c478bd9Sstevel@tonic-gate #include <poll.h> 116*7c478bd9Sstevel@tonic-gate #define pselect Pselect 117*7c478bd9Sstevel@tonic-gate #endif /* SUNW_POLL */ 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate /* Options. Leave them on. */ 120*7c478bd9Sstevel@tonic-gate #define DEBUG 121*7c478bd9Sstevel@tonic-gate #include "res_debug.h" 122*7c478bd9Sstevel@tonic-gate #include "res_private.h" 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate #define EXT(res) ((res)->_u._ext) 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate #ifdef ORIGINAL_ISC_CODE 127*7c478bd9Sstevel@tonic-gate static const int highestFD = FD_SETSIZE - 1; 128*7c478bd9Sstevel@tonic-gate #else 129*7c478bd9Sstevel@tonic-gate static int highestFD = 0; 130*7c478bd9Sstevel@tonic-gate #endif 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* Forward. */ 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate static int get_salen __P((const struct sockaddr *)); 135*7c478bd9Sstevel@tonic-gate static struct sockaddr * get_nsaddr __P((res_state, size_t)); 136*7c478bd9Sstevel@tonic-gate static int send_vc(res_state, const u_char *, int, 137*7c478bd9Sstevel@tonic-gate u_char *, int, int *, int); 138*7c478bd9Sstevel@tonic-gate static int send_dg(res_state, const u_char *, int, 139*7c478bd9Sstevel@tonic-gate u_char *, int, int *, int, 140*7c478bd9Sstevel@tonic-gate int *, int *); 141*7c478bd9Sstevel@tonic-gate static void Aerror(const res_state, FILE *, const char *, int, 142*7c478bd9Sstevel@tonic-gate const struct sockaddr *, int); 143*7c478bd9Sstevel@tonic-gate static void Perror(const res_state, FILE *, const char *, int); 144*7c478bd9Sstevel@tonic-gate static int sock_eq(struct sockaddr *, struct sockaddr *); 145*7c478bd9Sstevel@tonic-gate #ifdef NEED_PSELECT 146*7c478bd9Sstevel@tonic-gate static int pselect(int, void *, void *, void *, 147*7c478bd9Sstevel@tonic-gate struct timespec *, 148*7c478bd9Sstevel@tonic-gate const sigset_t *); 149*7c478bd9Sstevel@tonic-gate #endif 150*7c478bd9Sstevel@tonic-gate void res_pquery(const res_state, const u_char *, int, FILE *); 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate #ifdef ORIGINAL_ISC_CODE 153*7c478bd9Sstevel@tonic-gate #else 154*7c478bd9Sstevel@tonic-gate #pragma weak __res_nameinquery = res_nameinquery 155*7c478bd9Sstevel@tonic-gate #pragma weak __res_queriesmatch = res_queriesmatch 156*7c478bd9Sstevel@tonic-gate #pragma weak res_nisourserver = res_ourserver_p 157*7c478bd9Sstevel@tonic-gate #endif /* ORIGINAL_ISC_CODE */ 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* Public. */ 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* int 164*7c478bd9Sstevel@tonic-gate * res_isourserver(ina) 165*7c478bd9Sstevel@tonic-gate * looks up "ina" in _res.ns_addr_list[] 166*7c478bd9Sstevel@tonic-gate * returns: 167*7c478bd9Sstevel@tonic-gate * 0 : not found 168*7c478bd9Sstevel@tonic-gate * >0 : found 169*7c478bd9Sstevel@tonic-gate * author: 170*7c478bd9Sstevel@tonic-gate * paul vixie, 29may94 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate int 173*7c478bd9Sstevel@tonic-gate res_ourserver_p(const res_state statp, const struct sockaddr *sa) { 174*7c478bd9Sstevel@tonic-gate const struct sockaddr_in *inp, *srv; 175*7c478bd9Sstevel@tonic-gate const struct sockaddr_in6 *in6p, *srv6; 176*7c478bd9Sstevel@tonic-gate int ns; 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate switch (sa->sa_family) { 179*7c478bd9Sstevel@tonic-gate case AF_INET: 180*7c478bd9Sstevel@tonic-gate inp = (const struct sockaddr_in *)sa; 181*7c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 182*7c478bd9Sstevel@tonic-gate srv = (struct sockaddr_in *)get_nsaddr(statp, ns); 183*7c478bd9Sstevel@tonic-gate if (srv->sin_family == inp->sin_family && 184*7c478bd9Sstevel@tonic-gate srv->sin_port == inp->sin_port && 185*7c478bd9Sstevel@tonic-gate (srv->sin_addr.s_addr == INADDR_ANY || 186*7c478bd9Sstevel@tonic-gate srv->sin_addr.s_addr == inp->sin_addr.s_addr)) 187*7c478bd9Sstevel@tonic-gate return (1); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate case AF_INET6: 191*7c478bd9Sstevel@tonic-gate if (EXT(statp).ext == NULL) 192*7c478bd9Sstevel@tonic-gate break; 193*7c478bd9Sstevel@tonic-gate in6p = (const struct sockaddr_in6 *)sa; 194*7c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 195*7c478bd9Sstevel@tonic-gate srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); 196*7c478bd9Sstevel@tonic-gate if (srv6->sin6_family == in6p->sin6_family && 197*7c478bd9Sstevel@tonic-gate srv6->sin6_port == in6p->sin6_port && 198*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SIN6_SCOPE_ID 199*7c478bd9Sstevel@tonic-gate (srv6->sin6_scope_id == 0 || 200*7c478bd9Sstevel@tonic-gate srv6->sin6_scope_id == in6p->sin6_scope_id) && 201*7c478bd9Sstevel@tonic-gate #endif 202*7c478bd9Sstevel@tonic-gate (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || 203*7c478bd9Sstevel@tonic-gate IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) 204*7c478bd9Sstevel@tonic-gate return (1); 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate break; 207*7c478bd9Sstevel@tonic-gate default: 208*7c478bd9Sstevel@tonic-gate break; 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate return (0); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* int 214*7c478bd9Sstevel@tonic-gate * res_nameinquery(name, type, class, buf, eom) 215*7c478bd9Sstevel@tonic-gate * look for (name,type,class) in the query section of packet (buf,eom) 216*7c478bd9Sstevel@tonic-gate * requires: 217*7c478bd9Sstevel@tonic-gate * buf + HFIXEDSZ <= eom 218*7c478bd9Sstevel@tonic-gate * returns: 219*7c478bd9Sstevel@tonic-gate * -1 : format error 220*7c478bd9Sstevel@tonic-gate * 0 : not found 221*7c478bd9Sstevel@tonic-gate * >0 : found 222*7c478bd9Sstevel@tonic-gate * author: 223*7c478bd9Sstevel@tonic-gate * paul vixie, 29may94 224*7c478bd9Sstevel@tonic-gate */ 225*7c478bd9Sstevel@tonic-gate int 226*7c478bd9Sstevel@tonic-gate res_nameinquery(const char *name, int type, int class, 227*7c478bd9Sstevel@tonic-gate const u_char *buf, const u_char *eom) 228*7c478bd9Sstevel@tonic-gate { 229*7c478bd9Sstevel@tonic-gate const u_char *cp = buf + HFIXEDSZ; 230*7c478bd9Sstevel@tonic-gate int qdcount = ntohs(((const HEADER*)buf)->qdcount); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate while (qdcount-- > 0) { 233*7c478bd9Sstevel@tonic-gate char tname[MAXDNAME+1]; 234*7c478bd9Sstevel@tonic-gate int n, ttype, tclass; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate n = dn_expand(buf, eom, cp, tname, sizeof tname); 237*7c478bd9Sstevel@tonic-gate if (n < 0) 238*7c478bd9Sstevel@tonic-gate return (-1); 239*7c478bd9Sstevel@tonic-gate cp += n; 240*7c478bd9Sstevel@tonic-gate if (cp + 2 * INT16SZ > eom) 241*7c478bd9Sstevel@tonic-gate return (-1); 242*7c478bd9Sstevel@tonic-gate ttype = ns_get16(cp); cp += INT16SZ; 243*7c478bd9Sstevel@tonic-gate tclass = ns_get16(cp); cp += INT16SZ; 244*7c478bd9Sstevel@tonic-gate if (ttype == type && tclass == class && 245*7c478bd9Sstevel@tonic-gate ns_samename(tname, name) == 1) 246*7c478bd9Sstevel@tonic-gate return (1); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate return (0); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* int 252*7c478bd9Sstevel@tonic-gate * res_queriesmatch(buf1, eom1, buf2, eom2) 253*7c478bd9Sstevel@tonic-gate * is there a 1:1 mapping of (name,type,class) 254*7c478bd9Sstevel@tonic-gate * in (buf1,eom1) and (buf2,eom2)? 255*7c478bd9Sstevel@tonic-gate * returns: 256*7c478bd9Sstevel@tonic-gate * -1 : format error 257*7c478bd9Sstevel@tonic-gate * 0 : not a 1:1 mapping 258*7c478bd9Sstevel@tonic-gate * >0 : is a 1:1 mapping 259*7c478bd9Sstevel@tonic-gate * author: 260*7c478bd9Sstevel@tonic-gate * paul vixie, 29may94 261*7c478bd9Sstevel@tonic-gate */ 262*7c478bd9Sstevel@tonic-gate int 263*7c478bd9Sstevel@tonic-gate res_queriesmatch(const u_char *buf1, const u_char *eom1, 264*7c478bd9Sstevel@tonic-gate const u_char *buf2, const u_char *eom2) 265*7c478bd9Sstevel@tonic-gate { 266*7c478bd9Sstevel@tonic-gate const u_char *cp = buf1 + HFIXEDSZ; 267*7c478bd9Sstevel@tonic-gate int qdcount = ntohs(((const HEADER*)buf1)->qdcount); 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) 270*7c478bd9Sstevel@tonic-gate return (-1); 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate * Only header section present in replies to 274*7c478bd9Sstevel@tonic-gate * dynamic update packets. 275*7c478bd9Sstevel@tonic-gate */ 276*7c478bd9Sstevel@tonic-gate if ((((const HEADER *)buf1)->opcode == ns_o_update) && 277*7c478bd9Sstevel@tonic-gate (((const HEADER *)buf2)->opcode == ns_o_update)) 278*7c478bd9Sstevel@tonic-gate return (1); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) 281*7c478bd9Sstevel@tonic-gate return (0); 282*7c478bd9Sstevel@tonic-gate while (qdcount-- > 0) { 283*7c478bd9Sstevel@tonic-gate char tname[MAXDNAME+1]; 284*7c478bd9Sstevel@tonic-gate int n, ttype, tclass; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate n = dn_expand(buf1, eom1, cp, tname, sizeof tname); 287*7c478bd9Sstevel@tonic-gate if (n < 0) 288*7c478bd9Sstevel@tonic-gate return (-1); 289*7c478bd9Sstevel@tonic-gate cp += n; 290*7c478bd9Sstevel@tonic-gate if (cp + 2 * INT16SZ > eom1) 291*7c478bd9Sstevel@tonic-gate return (-1); 292*7c478bd9Sstevel@tonic-gate ttype = ns_get16(cp); cp += INT16SZ; 293*7c478bd9Sstevel@tonic-gate tclass = ns_get16(cp); cp += INT16SZ; 294*7c478bd9Sstevel@tonic-gate if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) 295*7c478bd9Sstevel@tonic-gate return (0); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate return (1); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate int 301*7c478bd9Sstevel@tonic-gate res_nsend(res_state statp, 302*7c478bd9Sstevel@tonic-gate const u_char *buf, int buflen, u_char *ans, int anssiz) 303*7c478bd9Sstevel@tonic-gate { 304*7c478bd9Sstevel@tonic-gate int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; 305*7c478bd9Sstevel@tonic-gate char abuf[NI_MAXHOST]; 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate #ifdef SUNW_POLL 308*7c478bd9Sstevel@tonic-gate highestFD = sysconf(_SC_OPEN_MAX) - 1; 309*7c478bd9Sstevel@tonic-gate #endif 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate if (statp->nscount == 0) { 312*7c478bd9Sstevel@tonic-gate errno = ESRCH; 313*7c478bd9Sstevel@tonic-gate return (-1); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate if (anssiz < HFIXEDSZ) { 316*7c478bd9Sstevel@tonic-gate errno = EINVAL; 317*7c478bd9Sstevel@tonic-gate return (-1); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), 320*7c478bd9Sstevel@tonic-gate (stdout, ";; res_send()\n"), buf, buflen); 321*7c478bd9Sstevel@tonic-gate v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; 322*7c478bd9Sstevel@tonic-gate gotsomewhere = 0; 323*7c478bd9Sstevel@tonic-gate terrno = ETIMEDOUT; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* 326*7c478bd9Sstevel@tonic-gate * If the ns_addr_list in the resolver context has changed, then 327*7c478bd9Sstevel@tonic-gate * invalidate our cached copy and the associated timing data. 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate if (EXT(statp).nscount != 0) { 330*7c478bd9Sstevel@tonic-gate int needclose = 0; 331*7c478bd9Sstevel@tonic-gate struct sockaddr_storage peer; 332*7c478bd9Sstevel@tonic-gate ISC_SOCKLEN_T peerlen; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate if (EXT(statp).nscount != statp->nscount) 335*7c478bd9Sstevel@tonic-gate needclose++; 336*7c478bd9Sstevel@tonic-gate else 337*7c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 338*7c478bd9Sstevel@tonic-gate if (statp->nsaddr_list[ns].sin_family && 339*7c478bd9Sstevel@tonic-gate !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], 340*7c478bd9Sstevel@tonic-gate (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { 341*7c478bd9Sstevel@tonic-gate needclose++; 342*7c478bd9Sstevel@tonic-gate break; 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate if (EXT(statp).nssocks[ns] == -1) 346*7c478bd9Sstevel@tonic-gate continue; 347*7c478bd9Sstevel@tonic-gate peerlen = sizeof(peer); 348*7c478bd9Sstevel@tonic-gate if (getsockname(EXT(statp).nssocks[ns], 349*7c478bd9Sstevel@tonic-gate (struct sockaddr *)&peer, &peerlen) < 0) { 350*7c478bd9Sstevel@tonic-gate needclose++; 351*7c478bd9Sstevel@tonic-gate break; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate if (!sock_eq((struct sockaddr *)&peer, 354*7c478bd9Sstevel@tonic-gate get_nsaddr(statp, ns))) { 355*7c478bd9Sstevel@tonic-gate needclose++; 356*7c478bd9Sstevel@tonic-gate break; 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate if (needclose) { 360*7c478bd9Sstevel@tonic-gate res_nclose(statp); 361*7c478bd9Sstevel@tonic-gate EXT(statp).nscount = 0; 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Maybe initialize our private copy of the ns_addr_list. 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate if (EXT(statp).nscount == 0) { 369*7c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 370*7c478bd9Sstevel@tonic-gate EXT(statp).nstimes[ns] = RES_MAXTIME; 371*7c478bd9Sstevel@tonic-gate EXT(statp).nssocks[ns] = -1; 372*7c478bd9Sstevel@tonic-gate if (!statp->nsaddr_list[ns].sin_family) 373*7c478bd9Sstevel@tonic-gate continue; 374*7c478bd9Sstevel@tonic-gate EXT(statp).ext->nsaddrs[ns].sin = 375*7c478bd9Sstevel@tonic-gate statp->nsaddr_list[ns]; 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate EXT(statp).nscount = statp->nscount; 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * Some resolvers want to even out the load on their nameservers. 382*7c478bd9Sstevel@tonic-gate * Note that RES_BLAST overrides RES_ROTATE. 383*7c478bd9Sstevel@tonic-gate */ 384*7c478bd9Sstevel@tonic-gate if ((statp->options & RES_ROTATE) != 0 && 385*7c478bd9Sstevel@tonic-gate (statp->options & RES_BLAST) == 0) { 386*7c478bd9Sstevel@tonic-gate union res_sockaddr_union inu; 387*7c478bd9Sstevel@tonic-gate struct sockaddr_in ina; 388*7c478bd9Sstevel@tonic-gate int lastns = statp->nscount - 1; 389*7c478bd9Sstevel@tonic-gate int fd; 390*7c478bd9Sstevel@tonic-gate u_int16_t nstime; 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate if (EXT(statp).ext != NULL) 393*7c478bd9Sstevel@tonic-gate inu = EXT(statp).ext->nsaddrs[0]; 394*7c478bd9Sstevel@tonic-gate ina = statp->nsaddr_list[0]; 395*7c478bd9Sstevel@tonic-gate fd = EXT(statp).nssocks[0]; 396*7c478bd9Sstevel@tonic-gate nstime = EXT(statp).nstimes[0]; 397*7c478bd9Sstevel@tonic-gate for (ns = 0; ns < lastns; ns++) { 398*7c478bd9Sstevel@tonic-gate if (EXT(statp).ext != NULL) 399*7c478bd9Sstevel@tonic-gate EXT(statp).ext->nsaddrs[ns] = 400*7c478bd9Sstevel@tonic-gate EXT(statp).ext->nsaddrs[ns + 1]; 401*7c478bd9Sstevel@tonic-gate statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; 402*7c478bd9Sstevel@tonic-gate EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; 403*7c478bd9Sstevel@tonic-gate EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate if (EXT(statp).ext != NULL) 406*7c478bd9Sstevel@tonic-gate EXT(statp).ext->nsaddrs[lastns] = inu; 407*7c478bd9Sstevel@tonic-gate statp->nsaddr_list[lastns] = ina; 408*7c478bd9Sstevel@tonic-gate EXT(statp).nssocks[lastns] = fd; 409*7c478bd9Sstevel@tonic-gate EXT(statp).nstimes[lastns] = nstime; 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate /* 413*7c478bd9Sstevel@tonic-gate * Send request, RETRY times, or until successful. 414*7c478bd9Sstevel@tonic-gate */ 415*7c478bd9Sstevel@tonic-gate for (try = 0; try < statp->retry; try++) { 416*7c478bd9Sstevel@tonic-gate for (ns = 0; ns < statp->nscount; ns++) { 417*7c478bd9Sstevel@tonic-gate struct sockaddr *nsap; 418*7c478bd9Sstevel@tonic-gate int nsaplen; 419*7c478bd9Sstevel@tonic-gate nsap = get_nsaddr(statp, ns); 420*7c478bd9Sstevel@tonic-gate nsaplen = get_salen(nsap); 421*7c478bd9Sstevel@tonic-gate statp->_flags &= ~RES_F_LASTMASK; 422*7c478bd9Sstevel@tonic-gate statp->_flags |= (ns << RES_F_LASTSHIFT); 423*7c478bd9Sstevel@tonic-gate same_ns: 424*7c478bd9Sstevel@tonic-gate if (statp->qhook) { 425*7c478bd9Sstevel@tonic-gate int done = 0, loops = 0; 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate do { 428*7c478bd9Sstevel@tonic-gate res_sendhookact act; 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate act = (*statp->qhook)(&nsap, &buf, &buflen, 431*7c478bd9Sstevel@tonic-gate ans, anssiz, &resplen); 432*7c478bd9Sstevel@tonic-gate switch (act) { 433*7c478bd9Sstevel@tonic-gate case res_goahead: 434*7c478bd9Sstevel@tonic-gate done = 1; 435*7c478bd9Sstevel@tonic-gate break; 436*7c478bd9Sstevel@tonic-gate case res_nextns: 437*7c478bd9Sstevel@tonic-gate res_nclose(statp); 438*7c478bd9Sstevel@tonic-gate goto next_ns; 439*7c478bd9Sstevel@tonic-gate case res_done: 440*7c478bd9Sstevel@tonic-gate return (resplen); 441*7c478bd9Sstevel@tonic-gate case res_modified: 442*7c478bd9Sstevel@tonic-gate /* give the hook another try */ 443*7c478bd9Sstevel@tonic-gate if (++loops < 42) /*doug adams*/ 444*7c478bd9Sstevel@tonic-gate break; 445*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 446*7c478bd9Sstevel@tonic-gate case res_error: 447*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 448*7c478bd9Sstevel@tonic-gate default: 449*7c478bd9Sstevel@tonic-gate goto fail; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate } while (!done); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate Dprint(((statp->options & RES_DEBUG) && 455*7c478bd9Sstevel@tonic-gate getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), 456*7c478bd9Sstevel@tonic-gate NULL, 0, niflags) == 0), 457*7c478bd9Sstevel@tonic-gate (stdout, ";; Querying server (# %d) address = %s\n", 458*7c478bd9Sstevel@tonic-gate ns + 1, abuf)); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate if (v_circuit) { 462*7c478bd9Sstevel@tonic-gate /* Use VC; at most one attempt per server. */ 463*7c478bd9Sstevel@tonic-gate try = statp->retry; 464*7c478bd9Sstevel@tonic-gate n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, 465*7c478bd9Sstevel@tonic-gate ns); 466*7c478bd9Sstevel@tonic-gate if (n < 0) 467*7c478bd9Sstevel@tonic-gate goto fail; 468*7c478bd9Sstevel@tonic-gate if (n == 0) 469*7c478bd9Sstevel@tonic-gate goto next_ns; 470*7c478bd9Sstevel@tonic-gate resplen = n; 471*7c478bd9Sstevel@tonic-gate } else { 472*7c478bd9Sstevel@tonic-gate /* Use datagrams. */ 473*7c478bd9Sstevel@tonic-gate n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, 474*7c478bd9Sstevel@tonic-gate ns, &v_circuit, &gotsomewhere); 475*7c478bd9Sstevel@tonic-gate if (n < 0) 476*7c478bd9Sstevel@tonic-gate goto fail; 477*7c478bd9Sstevel@tonic-gate if (n == 0) 478*7c478bd9Sstevel@tonic-gate goto next_ns; 479*7c478bd9Sstevel@tonic-gate if (v_circuit) 480*7c478bd9Sstevel@tonic-gate goto same_ns; 481*7c478bd9Sstevel@tonic-gate resplen = n; 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate Dprint((statp->options & RES_DEBUG) || 485*7c478bd9Sstevel@tonic-gate ((statp->pfcode & RES_PRF_REPLY) && 486*7c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_HEAD1)), 487*7c478bd9Sstevel@tonic-gate (stdout, ";; got answer:\n")); 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 490*7c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 491*7c478bd9Sstevel@tonic-gate (stdout, "%s", ""), 492*7c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate /* 495*7c478bd9Sstevel@tonic-gate * If we have temporarily opened a virtual circuit, 496*7c478bd9Sstevel@tonic-gate * or if we haven't been asked to keep a socket open, 497*7c478bd9Sstevel@tonic-gate * close the socket. 498*7c478bd9Sstevel@tonic-gate */ 499*7c478bd9Sstevel@tonic-gate if ((v_circuit && (statp->options & RES_USEVC) == 0) || 500*7c478bd9Sstevel@tonic-gate (statp->options & RES_STAYOPEN) == 0) { 501*7c478bd9Sstevel@tonic-gate res_nclose(statp); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate if (statp->rhook) { 504*7c478bd9Sstevel@tonic-gate int done = 0, loops = 0; 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate do { 507*7c478bd9Sstevel@tonic-gate res_sendhookact act; 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate act = (*statp->rhook)(nsap, buf, buflen, 510*7c478bd9Sstevel@tonic-gate ans, anssiz, &resplen); 511*7c478bd9Sstevel@tonic-gate switch (act) { 512*7c478bd9Sstevel@tonic-gate case res_goahead: 513*7c478bd9Sstevel@tonic-gate case res_done: 514*7c478bd9Sstevel@tonic-gate done = 1; 515*7c478bd9Sstevel@tonic-gate break; 516*7c478bd9Sstevel@tonic-gate case res_nextns: 517*7c478bd9Sstevel@tonic-gate res_nclose(statp); 518*7c478bd9Sstevel@tonic-gate goto next_ns; 519*7c478bd9Sstevel@tonic-gate case res_modified: 520*7c478bd9Sstevel@tonic-gate /* give the hook another try */ 521*7c478bd9Sstevel@tonic-gate if (++loops < 42) /*doug adams*/ 522*7c478bd9Sstevel@tonic-gate break; 523*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 524*7c478bd9Sstevel@tonic-gate case res_error: 525*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 526*7c478bd9Sstevel@tonic-gate default: 527*7c478bd9Sstevel@tonic-gate goto fail; 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate } while (!done); 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate return (resplen); 533*7c478bd9Sstevel@tonic-gate next_ns: ; 534*7c478bd9Sstevel@tonic-gate } /*foreach ns*/ 535*7c478bd9Sstevel@tonic-gate } /*foreach retry*/ 536*7c478bd9Sstevel@tonic-gate res_nclose(statp); 537*7c478bd9Sstevel@tonic-gate if (!v_circuit) { 538*7c478bd9Sstevel@tonic-gate if (!gotsomewhere) 539*7c478bd9Sstevel@tonic-gate errno = ECONNREFUSED; /* no nameservers found */ 540*7c478bd9Sstevel@tonic-gate else 541*7c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; /* no answer obtained */ 542*7c478bd9Sstevel@tonic-gate } else 543*7c478bd9Sstevel@tonic-gate errno = terrno; 544*7c478bd9Sstevel@tonic-gate return (-1); 545*7c478bd9Sstevel@tonic-gate fail: 546*7c478bd9Sstevel@tonic-gate res_nclose(statp); 547*7c478bd9Sstevel@tonic-gate return (-1); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate /* Private */ 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate static int 553*7c478bd9Sstevel@tonic-gate get_salen(sa) 554*7c478bd9Sstevel@tonic-gate const struct sockaddr *sa; 555*7c478bd9Sstevel@tonic-gate { 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SA_LEN 558*7c478bd9Sstevel@tonic-gate /* There are people do not set sa_len. Be forgiving to them. */ 559*7c478bd9Sstevel@tonic-gate if (sa->sa_len) 560*7c478bd9Sstevel@tonic-gate return (sa->sa_len); 561*7c478bd9Sstevel@tonic-gate #endif 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate if (sa->sa_family == AF_INET) 564*7c478bd9Sstevel@tonic-gate return (sizeof(struct sockaddr_in)); 565*7c478bd9Sstevel@tonic-gate else if (sa->sa_family == AF_INET6) 566*7c478bd9Sstevel@tonic-gate return (sizeof(struct sockaddr_in6)); 567*7c478bd9Sstevel@tonic-gate else 568*7c478bd9Sstevel@tonic-gate return (0); /* unknown, die on connect */ 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate /* 572*7c478bd9Sstevel@tonic-gate * pick appropriate nsaddr_list for use. see res_init() for initialization. 573*7c478bd9Sstevel@tonic-gate */ 574*7c478bd9Sstevel@tonic-gate static struct sockaddr * 575*7c478bd9Sstevel@tonic-gate get_nsaddr(statp, n) 576*7c478bd9Sstevel@tonic-gate res_state statp; 577*7c478bd9Sstevel@tonic-gate size_t n; 578*7c478bd9Sstevel@tonic-gate { 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { 581*7c478bd9Sstevel@tonic-gate /* 582*7c478bd9Sstevel@tonic-gate * - EXT(statp).ext->nsaddrs[n] holds an address that is larger 583*7c478bd9Sstevel@tonic-gate * than struct sockaddr, and 584*7c478bd9Sstevel@tonic-gate * - user code did not update statp->nsaddr_list[n]. 585*7c478bd9Sstevel@tonic-gate */ 586*7c478bd9Sstevel@tonic-gate return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; 587*7c478bd9Sstevel@tonic-gate } else { 588*7c478bd9Sstevel@tonic-gate /* 589*7c478bd9Sstevel@tonic-gate * - user code updated statp->nsaddr_list[n], or 590*7c478bd9Sstevel@tonic-gate * - statp->nsaddr_list[n] has the same content as 591*7c478bd9Sstevel@tonic-gate * EXT(statp).ext->nsaddrs[n]. 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate static int 598*7c478bd9Sstevel@tonic-gate send_vc(res_state statp, 599*7c478bd9Sstevel@tonic-gate const u_char *buf, int buflen, u_char *ans, int anssiz, 600*7c478bd9Sstevel@tonic-gate int *terrno, int ns) 601*7c478bd9Sstevel@tonic-gate { 602*7c478bd9Sstevel@tonic-gate const HEADER *hp = (const HEADER *) buf; 603*7c478bd9Sstevel@tonic-gate HEADER *anhp = (HEADER *) ans; 604*7c478bd9Sstevel@tonic-gate struct sockaddr *nsap; 605*7c478bd9Sstevel@tonic-gate int nsaplen; 606*7c478bd9Sstevel@tonic-gate int truncating, connreset, resplen, n; 607*7c478bd9Sstevel@tonic-gate struct iovec iov[2]; 608*7c478bd9Sstevel@tonic-gate u_short len; 609*7c478bd9Sstevel@tonic-gate u_char *cp; 610*7c478bd9Sstevel@tonic-gate void *tmp; 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate nsap = get_nsaddr(statp, ns); 613*7c478bd9Sstevel@tonic-gate nsaplen = get_salen(nsap); 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate connreset = 0; 616*7c478bd9Sstevel@tonic-gate same_ns: 617*7c478bd9Sstevel@tonic-gate truncating = 0; 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate /* Are we still talking to whom we want to talk to? */ 620*7c478bd9Sstevel@tonic-gate if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { 621*7c478bd9Sstevel@tonic-gate struct sockaddr_storage peer; 622*7c478bd9Sstevel@tonic-gate ISC_SOCKLEN_T size = sizeof peer; 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate if (getpeername(statp->_vcsock, 625*7c478bd9Sstevel@tonic-gate (struct sockaddr *)&peer, &size) < 0 || 626*7c478bd9Sstevel@tonic-gate !sock_eq((struct sockaddr *)&peer, nsap)) { 627*7c478bd9Sstevel@tonic-gate res_nclose(statp); 628*7c478bd9Sstevel@tonic-gate statp->_flags &= ~RES_F_VC; 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { 633*7c478bd9Sstevel@tonic-gate if (statp->_vcsock >= 0) 634*7c478bd9Sstevel@tonic-gate res_nclose(statp); 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); 637*7c478bd9Sstevel@tonic-gate if (statp->_vcsock > highestFD) { 638*7c478bd9Sstevel@tonic-gate res_nclose(statp); 639*7c478bd9Sstevel@tonic-gate errno = ENOTSOCK; 640*7c478bd9Sstevel@tonic-gate } 641*7c478bd9Sstevel@tonic-gate if (statp->_vcsock < 0) { 642*7c478bd9Sstevel@tonic-gate *terrno = errno; 643*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "socket(vc)", errno); 644*7c478bd9Sstevel@tonic-gate return (-1); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate errno = 0; 647*7c478bd9Sstevel@tonic-gate if (connect(statp->_vcsock, nsap, nsaplen) < 0) { 648*7c478bd9Sstevel@tonic-gate *terrno = errno; 649*7c478bd9Sstevel@tonic-gate Aerror(statp, stderr, "connect/vc", errno, nsap, 650*7c478bd9Sstevel@tonic-gate nsaplen); 651*7c478bd9Sstevel@tonic-gate res_nclose(statp); 652*7c478bd9Sstevel@tonic-gate return (0); 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate statp->_flags |= RES_F_VC; 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate /* 658*7c478bd9Sstevel@tonic-gate * Send length & message 659*7c478bd9Sstevel@tonic-gate */ 660*7c478bd9Sstevel@tonic-gate ns_put16((u_short)buflen, (u_char*)&len); 661*7c478bd9Sstevel@tonic-gate iov[0] = evConsIovec(&len, INT16SZ); 662*7c478bd9Sstevel@tonic-gate DE_CONST(buf, tmp); 663*7c478bd9Sstevel@tonic-gate iov[1] = evConsIovec(tmp, buflen); 664*7c478bd9Sstevel@tonic-gate if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { 665*7c478bd9Sstevel@tonic-gate *terrno = errno; 666*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "write failed", errno); 667*7c478bd9Sstevel@tonic-gate res_nclose(statp); 668*7c478bd9Sstevel@tonic-gate return (0); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate /* 671*7c478bd9Sstevel@tonic-gate * Receive length & response 672*7c478bd9Sstevel@tonic-gate */ 673*7c478bd9Sstevel@tonic-gate read_len: 674*7c478bd9Sstevel@tonic-gate cp = ans; 675*7c478bd9Sstevel@tonic-gate len = INT16SZ; 676*7c478bd9Sstevel@tonic-gate while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) { 677*7c478bd9Sstevel@tonic-gate cp += n; 678*7c478bd9Sstevel@tonic-gate if ((len -= n) <= 0) 679*7c478bd9Sstevel@tonic-gate break; 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate if (n <= 0) { 682*7c478bd9Sstevel@tonic-gate *terrno = errno; 683*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "read failed", errno); 684*7c478bd9Sstevel@tonic-gate res_nclose(statp); 685*7c478bd9Sstevel@tonic-gate /* 686*7c478bd9Sstevel@tonic-gate * A long running process might get its TCP 687*7c478bd9Sstevel@tonic-gate * connection reset if the remote server was 688*7c478bd9Sstevel@tonic-gate * restarted. Requery the server instead of 689*7c478bd9Sstevel@tonic-gate * trying a new one. When there is only one 690*7c478bd9Sstevel@tonic-gate * server, this means that a query might work 691*7c478bd9Sstevel@tonic-gate * instead of failing. We only allow one reset 692*7c478bd9Sstevel@tonic-gate * per query to prevent looping. 693*7c478bd9Sstevel@tonic-gate */ 694*7c478bd9Sstevel@tonic-gate if (*terrno == ECONNRESET && !connreset) { 695*7c478bd9Sstevel@tonic-gate connreset = 1; 696*7c478bd9Sstevel@tonic-gate res_nclose(statp); 697*7c478bd9Sstevel@tonic-gate goto same_ns; 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate res_nclose(statp); 700*7c478bd9Sstevel@tonic-gate return (0); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate resplen = ns_get16(ans); 703*7c478bd9Sstevel@tonic-gate if (resplen > anssiz) { 704*7c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 705*7c478bd9Sstevel@tonic-gate (stdout, ";; response truncated\n") 706*7c478bd9Sstevel@tonic-gate ); 707*7c478bd9Sstevel@tonic-gate truncating = 1; 708*7c478bd9Sstevel@tonic-gate len = anssiz; 709*7c478bd9Sstevel@tonic-gate } else 710*7c478bd9Sstevel@tonic-gate len = resplen; 711*7c478bd9Sstevel@tonic-gate if (len < HFIXEDSZ) { 712*7c478bd9Sstevel@tonic-gate /* 713*7c478bd9Sstevel@tonic-gate * Undersized message. 714*7c478bd9Sstevel@tonic-gate */ 715*7c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 716*7c478bd9Sstevel@tonic-gate (stdout, ";; undersized: %d\n", len)); 717*7c478bd9Sstevel@tonic-gate *terrno = EMSGSIZE; 718*7c478bd9Sstevel@tonic-gate res_nclose(statp); 719*7c478bd9Sstevel@tonic-gate return (0); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate cp = ans; 722*7c478bd9Sstevel@tonic-gate while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ 723*7c478bd9Sstevel@tonic-gate cp += n; 724*7c478bd9Sstevel@tonic-gate len -= n; 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate if (n <= 0) { 727*7c478bd9Sstevel@tonic-gate *terrno = errno; 728*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "read(vc)", errno); 729*7c478bd9Sstevel@tonic-gate res_nclose(statp); 730*7c478bd9Sstevel@tonic-gate return (0); 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate if (truncating) { 733*7c478bd9Sstevel@tonic-gate /* 734*7c478bd9Sstevel@tonic-gate * Flush rest of answer so connection stays in synch. 735*7c478bd9Sstevel@tonic-gate */ 736*7c478bd9Sstevel@tonic-gate anhp->tc = 1; 737*7c478bd9Sstevel@tonic-gate len = resplen - anssiz; 738*7c478bd9Sstevel@tonic-gate /* 739*7c478bd9Sstevel@tonic-gate * Reset the value of resplen to anssiz, 740*7c478bd9Sstevel@tonic-gate * this is done because the caller assumes 741*7c478bd9Sstevel@tonic-gate * resplen contains the size of message read 742*7c478bd9Sstevel@tonic-gate * into the "ans" buffer passed in. 743*7c478bd9Sstevel@tonic-gate */ 744*7c478bd9Sstevel@tonic-gate resplen = anssiz; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate while (len != 0) { 747*7c478bd9Sstevel@tonic-gate char junk[PACKETSZ]; 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate n = read(statp->_vcsock, junk, 750*7c478bd9Sstevel@tonic-gate (len > sizeof junk) ? sizeof junk : len); 751*7c478bd9Sstevel@tonic-gate if (n > 0) 752*7c478bd9Sstevel@tonic-gate len -= n; 753*7c478bd9Sstevel@tonic-gate else 754*7c478bd9Sstevel@tonic-gate break; 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate /* 758*7c478bd9Sstevel@tonic-gate * If the calling applicating has bailed out of 759*7c478bd9Sstevel@tonic-gate * a previous call and failed to arrange to have 760*7c478bd9Sstevel@tonic-gate * the circuit closed or the server has got 761*7c478bd9Sstevel@tonic-gate * itself confused, then drop the packet and 762*7c478bd9Sstevel@tonic-gate * wait for the correct one. 763*7c478bd9Sstevel@tonic-gate */ 764*7c478bd9Sstevel@tonic-gate if (hp->id != anhp->id) { 765*7c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 766*7c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 767*7c478bd9Sstevel@tonic-gate (stdout, ";; old answer (unexpected):\n"), 768*7c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz: resplen); 769*7c478bd9Sstevel@tonic-gate goto read_len; 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate /* 773*7c478bd9Sstevel@tonic-gate * All is well, or the error is fatal. Signal that the 774*7c478bd9Sstevel@tonic-gate * next nameserver ought not be tried. 775*7c478bd9Sstevel@tonic-gate */ 776*7c478bd9Sstevel@tonic-gate return (resplen); 777*7c478bd9Sstevel@tonic-gate } 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate static int 780*7c478bd9Sstevel@tonic-gate send_dg(res_state statp, 781*7c478bd9Sstevel@tonic-gate const u_char *buf, int buflen, u_char *ans, int anssiz, 782*7c478bd9Sstevel@tonic-gate int *terrno, int ns, int *v_circuit, int *gotsomewhere) 783*7c478bd9Sstevel@tonic-gate { 784*7c478bd9Sstevel@tonic-gate const HEADER *hp = (const HEADER *) buf; 785*7c478bd9Sstevel@tonic-gate HEADER *anhp = (HEADER *) ans; 786*7c478bd9Sstevel@tonic-gate const struct sockaddr *nsap; 787*7c478bd9Sstevel@tonic-gate int nsaplen; 788*7c478bd9Sstevel@tonic-gate struct timespec now, timeout, finish; 789*7c478bd9Sstevel@tonic-gate fd_set dsmask; 790*7c478bd9Sstevel@tonic-gate struct sockaddr_storage from; 791*7c478bd9Sstevel@tonic-gate ISC_SOCKLEN_T fromlen; 792*7c478bd9Sstevel@tonic-gate int resplen, seconds, n, s; 793*7c478bd9Sstevel@tonic-gate #ifdef SUNW_POLL 794*7c478bd9Sstevel@tonic-gate int polltimeout; 795*7c478bd9Sstevel@tonic-gate struct pollfd pollfd; 796*7c478bd9Sstevel@tonic-gate #endif 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate nsap = get_nsaddr(statp, ns); 799*7c478bd9Sstevel@tonic-gate nsaplen = get_salen(nsap); 800*7c478bd9Sstevel@tonic-gate if (EXT(statp).nssocks[ns] == -1) { 801*7c478bd9Sstevel@tonic-gate EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); 802*7c478bd9Sstevel@tonic-gate if (EXT(statp).nssocks[ns] > highestFD) { 803*7c478bd9Sstevel@tonic-gate res_nclose(statp); 804*7c478bd9Sstevel@tonic-gate errno = ENOTSOCK; 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate if (EXT(statp).nssocks[ns] < 0) { 807*7c478bd9Sstevel@tonic-gate *terrno = errno; 808*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "socket(dg)", errno); 809*7c478bd9Sstevel@tonic-gate return (-1); 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate #ifndef CANNOT_CONNECT_DGRAM 812*7c478bd9Sstevel@tonic-gate /* 813*7c478bd9Sstevel@tonic-gate * On a 4.3BSD+ machine (client and server, 814*7c478bd9Sstevel@tonic-gate * actually), sending to a nameserver datagram 815*7c478bd9Sstevel@tonic-gate * port with no nameserver will cause an 816*7c478bd9Sstevel@tonic-gate * ICMP port unreachable message to be returned. 817*7c478bd9Sstevel@tonic-gate * If our datagram socket is "connected" to the 818*7c478bd9Sstevel@tonic-gate * server, we get an ECONNREFUSED error on the next 819*7c478bd9Sstevel@tonic-gate * socket operation, and select returns if the 820*7c478bd9Sstevel@tonic-gate * error message is received. We can thus detect 821*7c478bd9Sstevel@tonic-gate * the absence of a nameserver without timing out. 822*7c478bd9Sstevel@tonic-gate */ 823*7c478bd9Sstevel@tonic-gate if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { 824*7c478bd9Sstevel@tonic-gate Aerror(statp, stderr, "connect(dg)", errno, nsap, 825*7c478bd9Sstevel@tonic-gate nsaplen); 826*7c478bd9Sstevel@tonic-gate res_nclose(statp); 827*7c478bd9Sstevel@tonic-gate return (0); 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate #endif /* !CANNOT_CONNECT_DGRAM */ 830*7c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 831*7c478bd9Sstevel@tonic-gate (stdout, ";; new DG socket\n")) 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate s = EXT(statp).nssocks[ns]; 834*7c478bd9Sstevel@tonic-gate #ifndef CANNOT_CONNECT_DGRAM 835*7c478bd9Sstevel@tonic-gate if (send(s, (const char*)buf, buflen, 0) != buflen) { 836*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "send", errno); 837*7c478bd9Sstevel@tonic-gate res_nclose(statp); 838*7c478bd9Sstevel@tonic-gate return (0); 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate #else /* !CANNOT_CONNECT_DGRAM */ 841*7c478bd9Sstevel@tonic-gate if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) 842*7c478bd9Sstevel@tonic-gate { 843*7c478bd9Sstevel@tonic-gate Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 844*7c478bd9Sstevel@tonic-gate res_nclose(statp); 845*7c478bd9Sstevel@tonic-gate return (0); 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate #endif /* !CANNOT_CONNECT_DGRAM */ 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate /* 850*7c478bd9Sstevel@tonic-gate * Wait for reply. 851*7c478bd9Sstevel@tonic-gate */ 852*7c478bd9Sstevel@tonic-gate seconds = (statp->retrans << ns); 853*7c478bd9Sstevel@tonic-gate if (ns > 0) 854*7c478bd9Sstevel@tonic-gate seconds /= statp->nscount; 855*7c478bd9Sstevel@tonic-gate if (seconds <= 0) 856*7c478bd9Sstevel@tonic-gate seconds = 1; 857*7c478bd9Sstevel@tonic-gate now = evNowTime(); 858*7c478bd9Sstevel@tonic-gate timeout = evConsTime(seconds, 0); 859*7c478bd9Sstevel@tonic-gate finish = evAddTime(now, timeout); 860*7c478bd9Sstevel@tonic-gate goto nonow; 861*7c478bd9Sstevel@tonic-gate wait: 862*7c478bd9Sstevel@tonic-gate now = evNowTime(); 863*7c478bd9Sstevel@tonic-gate nonow: 864*7c478bd9Sstevel@tonic-gate #ifdef SUNW_POLL 865*7c478bd9Sstevel@tonic-gate timeout = evSubTime(finish, now); 866*7c478bd9Sstevel@tonic-gate if (timeout.tv_sec < 0) 867*7c478bd9Sstevel@tonic-gate timeout = evConsTime(0, 0); 868*7c478bd9Sstevel@tonic-gate polltimeout = 1000*timeout.tv_sec + 869*7c478bd9Sstevel@tonic-gate timeout.tv_nsec/1000000; 870*7c478bd9Sstevel@tonic-gate pollfd.fd = s; 871*7c478bd9Sstevel@tonic-gate pollfd.events = POLLRDNORM; 872*7c478bd9Sstevel@tonic-gate n = poll(&pollfd, 1, polltimeout); 873*7c478bd9Sstevel@tonic-gate #else 874*7c478bd9Sstevel@tonic-gate FD_ZERO(&dsmask); 875*7c478bd9Sstevel@tonic-gate FD_SET(s, &dsmask); 876*7c478bd9Sstevel@tonic-gate if (evCmpTime(finish, now) > 0) 877*7c478bd9Sstevel@tonic-gate timeout = evSubTime(finish, now); 878*7c478bd9Sstevel@tonic-gate else 879*7c478bd9Sstevel@tonic-gate timeout = evConsTime(0, 0); 880*7c478bd9Sstevel@tonic-gate n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); 881*7c478bd9Sstevel@tonic-gate #endif 882*7c478bd9Sstevel@tonic-gate if (n == 0) { 883*7c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); 884*7c478bd9Sstevel@tonic-gate *gotsomewhere = 1; 885*7c478bd9Sstevel@tonic-gate return (0); 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate if (n < 0) { 888*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 889*7c478bd9Sstevel@tonic-gate goto wait; 890*7c478bd9Sstevel@tonic-gate #ifdef SUNW_POLL 891*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "poll", errno); 892*7c478bd9Sstevel@tonic-gate #else 893*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "select", errno); 894*7c478bd9Sstevel@tonic-gate #endif 895*7c478bd9Sstevel@tonic-gate res_nclose(statp); 896*7c478bd9Sstevel@tonic-gate return (0); 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate errno = 0; 899*7c478bd9Sstevel@tonic-gate fromlen = sizeof(from); 900*7c478bd9Sstevel@tonic-gate resplen = recvfrom(s, (char*)ans, anssiz,0, 901*7c478bd9Sstevel@tonic-gate (struct sockaddr *)&from, &fromlen); 902*7c478bd9Sstevel@tonic-gate if (resplen <= 0) { 903*7c478bd9Sstevel@tonic-gate Perror(statp, stderr, "recvfrom", errno); 904*7c478bd9Sstevel@tonic-gate res_nclose(statp); 905*7c478bd9Sstevel@tonic-gate return (0); 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate *gotsomewhere = 1; 908*7c478bd9Sstevel@tonic-gate if (resplen < HFIXEDSZ) { 909*7c478bd9Sstevel@tonic-gate /* 910*7c478bd9Sstevel@tonic-gate * Undersized message. 911*7c478bd9Sstevel@tonic-gate */ 912*7c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 913*7c478bd9Sstevel@tonic-gate (stdout, ";; undersized: %d\n", 914*7c478bd9Sstevel@tonic-gate resplen)); 915*7c478bd9Sstevel@tonic-gate *terrno = EMSGSIZE; 916*7c478bd9Sstevel@tonic-gate res_nclose(statp); 917*7c478bd9Sstevel@tonic-gate return (0); 918*7c478bd9Sstevel@tonic-gate } 919*7c478bd9Sstevel@tonic-gate if (hp->id != anhp->id) { 920*7c478bd9Sstevel@tonic-gate /* 921*7c478bd9Sstevel@tonic-gate * response from old query, ignore it. 922*7c478bd9Sstevel@tonic-gate * XXX - potential security hazard could 923*7c478bd9Sstevel@tonic-gate * be detected here. 924*7c478bd9Sstevel@tonic-gate */ 925*7c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 926*7c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 927*7c478bd9Sstevel@tonic-gate (stdout, ";; old answer:\n"), 928*7c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 929*7c478bd9Sstevel@tonic-gate goto wait; 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate if (!(statp->options & RES_INSECURE1) && 932*7c478bd9Sstevel@tonic-gate !res_ourserver_p(statp, (struct sockaddr *)&from)) { 933*7c478bd9Sstevel@tonic-gate /* 934*7c478bd9Sstevel@tonic-gate * response from wrong server? ignore it. 935*7c478bd9Sstevel@tonic-gate * XXX - potential security hazard could 936*7c478bd9Sstevel@tonic-gate * be detected here. 937*7c478bd9Sstevel@tonic-gate */ 938*7c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 939*7c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 940*7c478bd9Sstevel@tonic-gate (stdout, ";; not our server:\n"), 941*7c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 942*7c478bd9Sstevel@tonic-gate goto wait; 943*7c478bd9Sstevel@tonic-gate } 944*7c478bd9Sstevel@tonic-gate #ifdef RES_USE_EDNS0 945*7c478bd9Sstevel@tonic-gate if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0) { 946*7c478bd9Sstevel@tonic-gate /* 947*7c478bd9Sstevel@tonic-gate * Do not retry if the server do not understand EDNS0. 948*7c478bd9Sstevel@tonic-gate * The case has to be captured here, as FORMERR packet do not 949*7c478bd9Sstevel@tonic-gate * carry query section, hence res_queriesmatch() returns 0. 950*7c478bd9Sstevel@tonic-gate */ 951*7c478bd9Sstevel@tonic-gate DprintQ(statp->options & RES_DEBUG, 952*7c478bd9Sstevel@tonic-gate (stdout, "server rejected query with EDNS0:\n"), 953*7c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 954*7c478bd9Sstevel@tonic-gate /* record the error */ 955*7c478bd9Sstevel@tonic-gate statp->_flags |= RES_F_EDNS0ERR; 956*7c478bd9Sstevel@tonic-gate res_nclose(statp); 957*7c478bd9Sstevel@tonic-gate return (0); 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate #endif 960*7c478bd9Sstevel@tonic-gate if (!(statp->options & RES_INSECURE2) && 961*7c478bd9Sstevel@tonic-gate !res_queriesmatch(buf, buf + buflen, 962*7c478bd9Sstevel@tonic-gate ans, ans + anssiz)) { 963*7c478bd9Sstevel@tonic-gate /* 964*7c478bd9Sstevel@tonic-gate * response contains wrong query? ignore it. 965*7c478bd9Sstevel@tonic-gate * XXX - potential security hazard could 966*7c478bd9Sstevel@tonic-gate * be detected here. 967*7c478bd9Sstevel@tonic-gate */ 968*7c478bd9Sstevel@tonic-gate DprintQ((statp->options & RES_DEBUG) || 969*7c478bd9Sstevel@tonic-gate (statp->pfcode & RES_PRF_REPLY), 970*7c478bd9Sstevel@tonic-gate (stdout, ";; wrong query name:\n"), 971*7c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 972*7c478bd9Sstevel@tonic-gate goto wait; 973*7c478bd9Sstevel@tonic-gate } 974*7c478bd9Sstevel@tonic-gate if (anhp->rcode == SERVFAIL || 975*7c478bd9Sstevel@tonic-gate anhp->rcode == NOTIMP || 976*7c478bd9Sstevel@tonic-gate anhp->rcode == REFUSED) { 977*7c478bd9Sstevel@tonic-gate DprintQ(statp->options & RES_DEBUG, 978*7c478bd9Sstevel@tonic-gate (stdout, "server rejected query:\n"), 979*7c478bd9Sstevel@tonic-gate ans, (resplen > anssiz) ? anssiz : resplen); 980*7c478bd9Sstevel@tonic-gate res_nclose(statp); 981*7c478bd9Sstevel@tonic-gate /* don't retry if called from dig */ 982*7c478bd9Sstevel@tonic-gate if (!statp->pfcode) 983*7c478bd9Sstevel@tonic-gate return (0); 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate if (!(statp->options & RES_IGNTC) && anhp->tc) { 986*7c478bd9Sstevel@tonic-gate /* 987*7c478bd9Sstevel@tonic-gate * To get the rest of answer, 988*7c478bd9Sstevel@tonic-gate * use TCP with same server. 989*7c478bd9Sstevel@tonic-gate */ 990*7c478bd9Sstevel@tonic-gate Dprint(statp->options & RES_DEBUG, 991*7c478bd9Sstevel@tonic-gate (stdout, ";; truncated answer\n")); 992*7c478bd9Sstevel@tonic-gate *v_circuit = 1; 993*7c478bd9Sstevel@tonic-gate res_nclose(statp); 994*7c478bd9Sstevel@tonic-gate return (1); 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate /* 997*7c478bd9Sstevel@tonic-gate * All is well, or the error is fatal. Signal that the 998*7c478bd9Sstevel@tonic-gate * next nameserver ought not be tried. 999*7c478bd9Sstevel@tonic-gate */ 1000*7c478bd9Sstevel@tonic-gate return (resplen); 1001*7c478bd9Sstevel@tonic-gate } 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate static void 1004*7c478bd9Sstevel@tonic-gate Aerror(const res_state statp, FILE *file, const char *string, int error, 1005*7c478bd9Sstevel@tonic-gate const struct sockaddr *address, int alen) 1006*7c478bd9Sstevel@tonic-gate { 1007*7c478bd9Sstevel@tonic-gate int save = errno; 1008*7c478bd9Sstevel@tonic-gate char hbuf[NI_MAXHOST]; 1009*7c478bd9Sstevel@tonic-gate char sbuf[NI_MAXSERV]; 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate alen = alen; 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate if ((statp->options & RES_DEBUG) != 0) { 1014*7c478bd9Sstevel@tonic-gate if (getnameinfo(address, alen, hbuf, sizeof(hbuf), 1015*7c478bd9Sstevel@tonic-gate sbuf, sizeof(sbuf), niflags)) { 1016*7c478bd9Sstevel@tonic-gate strncpy(hbuf, "?", sizeof(hbuf) - 1); 1017*7c478bd9Sstevel@tonic-gate hbuf[sizeof(hbuf) - 1] = '\0'; 1018*7c478bd9Sstevel@tonic-gate strncpy(sbuf, "?", sizeof(sbuf) - 1); 1019*7c478bd9Sstevel@tonic-gate sbuf[sizeof(sbuf) - 1] = '\0'; 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate fprintf(file, "res_send: %s ([%s].%s): %s\n", 1022*7c478bd9Sstevel@tonic-gate string, hbuf, sbuf, strerror(error)); 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate errno = save; 1025*7c478bd9Sstevel@tonic-gate } 1026*7c478bd9Sstevel@tonic-gate 1027*7c478bd9Sstevel@tonic-gate static void 1028*7c478bd9Sstevel@tonic-gate Perror(const res_state statp, FILE *file, const char *string, int error) { 1029*7c478bd9Sstevel@tonic-gate int save = errno; 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate if ((statp->options & RES_DEBUG) != 0) 1032*7c478bd9Sstevel@tonic-gate fprintf(file, "res_send: %s: %s\n", 1033*7c478bd9Sstevel@tonic-gate string, strerror(error)); 1034*7c478bd9Sstevel@tonic-gate errno = save; 1035*7c478bd9Sstevel@tonic-gate } 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate static int 1038*7c478bd9Sstevel@tonic-gate sock_eq(struct sockaddr *a, struct sockaddr *b) { 1039*7c478bd9Sstevel@tonic-gate struct sockaddr_in *a4, *b4; 1040*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 *a6, *b6; 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate if (a->sa_family != b->sa_family) 1043*7c478bd9Sstevel@tonic-gate return 0; 1044*7c478bd9Sstevel@tonic-gate switch (a->sa_family) { 1045*7c478bd9Sstevel@tonic-gate case AF_INET: 1046*7c478bd9Sstevel@tonic-gate a4 = (struct sockaddr_in *)a; 1047*7c478bd9Sstevel@tonic-gate b4 = (struct sockaddr_in *)b; 1048*7c478bd9Sstevel@tonic-gate return a4->sin_port == b4->sin_port && 1049*7c478bd9Sstevel@tonic-gate a4->sin_addr.s_addr == b4->sin_addr.s_addr; 1050*7c478bd9Sstevel@tonic-gate case AF_INET6: 1051*7c478bd9Sstevel@tonic-gate a6 = (struct sockaddr_in6 *)a; 1052*7c478bd9Sstevel@tonic-gate b6 = (struct sockaddr_in6 *)b; 1053*7c478bd9Sstevel@tonic-gate return a6->sin6_port == b6->sin6_port && 1054*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SIN6_SCOPE_ID 1055*7c478bd9Sstevel@tonic-gate a6->sin6_scope_id == b6->sin6_scope_id && 1056*7c478bd9Sstevel@tonic-gate #endif 1057*7c478bd9Sstevel@tonic-gate IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); 1058*7c478bd9Sstevel@tonic-gate default: 1059*7c478bd9Sstevel@tonic-gate return 0; 1060*7c478bd9Sstevel@tonic-gate } 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate #ifdef NEED_PSELECT 1064*7c478bd9Sstevel@tonic-gate /* XXX needs to move to the porting library. */ 1065*7c478bd9Sstevel@tonic-gate static int 1066*7c478bd9Sstevel@tonic-gate pselect(int nfds, void *rfds, void *wfds, void *efds, 1067*7c478bd9Sstevel@tonic-gate struct timespec *tsp, const sigset_t *sigmask) 1068*7c478bd9Sstevel@tonic-gate { 1069*7c478bd9Sstevel@tonic-gate struct timeval tv, *tvp; 1070*7c478bd9Sstevel@tonic-gate sigset_t sigs; 1071*7c478bd9Sstevel@tonic-gate int n; 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate if (tsp) { 1074*7c478bd9Sstevel@tonic-gate tvp = &tv; 1075*7c478bd9Sstevel@tonic-gate tv = evTimeVal(*tsp); 1076*7c478bd9Sstevel@tonic-gate } else 1077*7c478bd9Sstevel@tonic-gate tvp = NULL; 1078*7c478bd9Sstevel@tonic-gate if (sigmask) 1079*7c478bd9Sstevel@tonic-gate sigprocmask(SIG_SETMASK, sigmask, &sigs); 1080*7c478bd9Sstevel@tonic-gate n = select(nfds, rfds, wfds, efds, tvp); 1081*7c478bd9Sstevel@tonic-gate if (sigmask) 1082*7c478bd9Sstevel@tonic-gate sigprocmask(SIG_SETMASK, &sigs, NULL); 1083*7c478bd9Sstevel@tonic-gate if (tsp) 1084*7c478bd9Sstevel@tonic-gate *tsp = evTimeSpec(tv); 1085*7c478bd9Sstevel@tonic-gate return (n); 1086*7c478bd9Sstevel@tonic-gate } 1087*7c478bd9Sstevel@tonic-gate #endif 1088