res_send.c revision 260652
1156952Sume/* 2156952Sume * Copyright (c) 1985, 1989, 1993 3156952Sume * The Regents of the University of California. All rights reserved. 4156952Sume * 5156952Sume * Redistribution and use in source and binary forms, with or without 6156952Sume * modification, are permitted provided that the following conditions 7156952Sume * are met: 8156952Sume * 1. Redistributions of source code must retain the above copyright 9156952Sume * notice, this list of conditions and the following disclaimer. 10156952Sume * 2. Redistributions in binary form must reproduce the above copyright 11156952Sume * notice, this list of conditions and the following disclaimer in the 12156952Sume * documentation and/or other materials provided with the distribution. 13156952Sume * 4. Neither the name of the University nor the names of its contributors 14156952Sume * may be used to endorse or promote products derived from this software 15156952Sume * without specific prior written permission. 16156952Sume * 17156952Sume * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18156952Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19156952Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20156952Sume * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21156952Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22156952Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23156952Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24156952Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25156952Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26156952Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27156952Sume * SUCH DAMAGE. 28156952Sume */ 29156952Sume 30156952Sume/* 31156952Sume * Portions Copyright (c) 1993 by Digital Equipment Corporation. 32156952Sume * 33156952Sume * Permission to use, copy, modify, and distribute this software for any 34156952Sume * purpose with or without fee is hereby granted, provided that the above 35156952Sume * copyright notice and this permission notice appear in all copies, and that 36156952Sume * the name of Digital Equipment Corporation not be used in advertising or 37156952Sume * publicity pertaining to distribution of the document or software without 38156952Sume * specific, written prior permission. 39156952Sume * 40156952Sume * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 41156952Sume * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 42156952Sume * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 43156952Sume * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 44156952Sume * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 45156952Sume * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46156952Sume * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 47156952Sume * SOFTWARE. 48156952Sume */ 49156952Sume 50156952Sume/* 51156952Sume * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC") 52156952Sume * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 53156952Sume * 54156952Sume * Permission to use, copy, modify, and distribute this software for any 55156952Sume * purpose with or without fee is hereby granted, provided that the above 56156952Sume * copyright notice and this permission notice appear in all copies. 57156952Sume * 58156952Sume * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 59156952Sume * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 60156952Sume * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 61156952Sume * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 62156952Sume * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 63156952Sume * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 64156952Sume * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 65156952Sume */ 66156952Sume 67156952Sume#if defined(LIBC_SCCS) && !defined(lint) 68156952Sumestatic const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 69186090Sumestatic const char rcsid[] = "$Id: res_send.c,v 1.9.18.10 2008/01/27 02:06:26 marka Exp $"; 70156952Sume#endif /* LIBC_SCCS and not lint */ 71156956Sume#include <sys/cdefs.h> 72156956Sume__FBSDID("$FreeBSD: head/lib/libc/resolv/res_send.c 260652 2014-01-14 22:05:33Z jilles $"); 73156952Sume 74170244Sume/*! \file 75170244Sume * \brief 76156952Sume * Send query to name server and wait for reply. 77156952Sume */ 78156952Sume 79156952Sume#include "port_before.h" 80260652Sjilles#if !defined(USE_KQUEUE) && !defined(USE_POLL) 81156952Sume#include "fd_setsize.h" 82156956Sume#endif 83156952Sume 84156956Sume#include "namespace.h" 85156952Sume#include <sys/types.h> 86156952Sume#include <sys/param.h> 87156952Sume#include <sys/time.h> 88156952Sume#include <sys/socket.h> 89156952Sume#include <sys/uio.h> 90156952Sume 91156952Sume#include <netinet/in.h> 92156952Sume#include <arpa/nameser.h> 93156952Sume#include <arpa/inet.h> 94156952Sume 95156952Sume#include <errno.h> 96156952Sume#include <netdb.h> 97156952Sume#include <resolv.h> 98156952Sume#include <signal.h> 99156952Sume#include <stdio.h> 100156952Sume#include <stdlib.h> 101156952Sume#include <string.h> 102156952Sume#include <unistd.h> 103156952Sume 104156952Sume#include <isc/eventlib.h> 105156952Sume 106156952Sume#include "port_after.h" 107156952Sume 108156956Sume#ifdef USE_KQUEUE 109156956Sume#include <sys/event.h> 110156956Sume#else 111156952Sume#ifdef USE_POLL 112156952Sume#ifdef HAVE_STROPTS_H 113156952Sume#include <stropts.h> 114156952Sume#endif 115156952Sume#include <poll.h> 116156952Sume#endif /* USE_POLL */ 117156956Sume#endif 118156952Sume 119156956Sume#include "un-namespace.h" 120156956Sume 121156952Sume/* Options. Leave them on. */ 122156952Sume#define DEBUG 123156952Sume#include "res_debug.h" 124156952Sume#include "res_private.h" 125156952Sume 126156952Sume#define EXT(res) ((res)->_u._ext) 127156952Sume 128167246Sjhb#if !defined(USE_POLL) && !defined(USE_KQUEUE) 129156952Sumestatic const int highestFD = FD_SETSIZE - 1; 130156952Sume#endif 131156952Sume 132156952Sume/* Forward. */ 133156952Sume 134156956Sumestatic int get_salen(const struct sockaddr *); 135156956Sumestatic struct sockaddr * get_nsaddr(res_state, size_t); 136156952Sumestatic int send_vc(res_state, const u_char *, int, 137156952Sume u_char *, int, int *, int); 138156956Sumestatic int send_dg(res_state, 139156956Sume#ifdef USE_KQUEUE 140156956Sume int kq, 141156956Sume#endif 142156956Sume const u_char *, int, 143163661Sume u_char *, int, int *, int, int, 144156952Sume int *, int *); 145156952Sumestatic void Aerror(const res_state, FILE *, const char *, int, 146156952Sume const struct sockaddr *, int); 147156952Sumestatic void Perror(const res_state, FILE *, const char *, int); 148156952Sumestatic int sock_eq(struct sockaddr *, struct sockaddr *); 149156956Sume#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) 150156952Sumestatic int pselect(int, void *, void *, void *, 151156952Sume struct timespec *, 152156952Sume const sigset_t *); 153156952Sume#endif 154156952Sumevoid res_pquery(const res_state, const u_char *, int, FILE *); 155156952Sume 156156952Sumestatic const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 157156952Sume 158156952Sume/* Public. */ 159156952Sume 160170244Sume/*% 161156952Sume * looks up "ina" in _res.ns_addr_list[] 162170244Sume * 163156952Sume * returns: 164170244Sume *\li 0 : not found 165170244Sume *\li >0 : found 166170244Sume * 167156952Sume * author: 168170244Sume *\li paul vixie, 29may94 169156952Sume */ 170156952Sumeint 171156952Sumeres_ourserver_p(const res_state statp, const struct sockaddr *sa) { 172156952Sume const struct sockaddr_in *inp, *srv; 173156952Sume const struct sockaddr_in6 *in6p, *srv6; 174156952Sume int ns; 175156952Sume 176156952Sume switch (sa->sa_family) { 177156952Sume case AF_INET: 178156952Sume inp = (const struct sockaddr_in *)sa; 179156952Sume for (ns = 0; ns < statp->nscount; ns++) { 180156952Sume srv = (struct sockaddr_in *)get_nsaddr(statp, ns); 181156952Sume if (srv->sin_family == inp->sin_family && 182156952Sume srv->sin_port == inp->sin_port && 183156952Sume (srv->sin_addr.s_addr == INADDR_ANY || 184156952Sume srv->sin_addr.s_addr == inp->sin_addr.s_addr)) 185156952Sume return (1); 186156952Sume } 187156952Sume break; 188156952Sume case AF_INET6: 189156952Sume if (EXT(statp).ext == NULL) 190156952Sume break; 191156952Sume in6p = (const struct sockaddr_in6 *)sa; 192156952Sume for (ns = 0; ns < statp->nscount; ns++) { 193156952Sume srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); 194156952Sume if (srv6->sin6_family == in6p->sin6_family && 195156952Sume srv6->sin6_port == in6p->sin6_port && 196156952Sume#ifdef HAVE_SIN6_SCOPE_ID 197156952Sume (srv6->sin6_scope_id == 0 || 198156952Sume srv6->sin6_scope_id == in6p->sin6_scope_id) && 199156952Sume#endif 200156952Sume (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || 201156952Sume IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) 202156952Sume return (1); 203156952Sume } 204156952Sume break; 205156952Sume default: 206156952Sume break; 207156952Sume } 208156952Sume return (0); 209156952Sume} 210156952Sume 211170244Sume/*% 212156952Sume * look for (name,type,class) in the query section of packet (buf,eom) 213170244Sume * 214156952Sume * requires: 215170244Sume *\li buf + HFIXEDSZ <= eom 216170244Sume * 217156952Sume * returns: 218170244Sume *\li -1 : format error 219170244Sume *\li 0 : not found 220170244Sume *\li >0 : found 221170244Sume * 222156952Sume * author: 223170244Sume *\li paul vixie, 29may94 224156952Sume */ 225156952Sumeint 226156952Sumeres_nameinquery(const char *name, int type, int class, 227156952Sume const u_char *buf, const u_char *eom) 228156952Sume{ 229156952Sume const u_char *cp = buf + HFIXEDSZ; 230156952Sume int qdcount = ntohs(((const HEADER*)buf)->qdcount); 231156952Sume 232156952Sume while (qdcount-- > 0) { 233156952Sume char tname[MAXDNAME+1]; 234156952Sume int n, ttype, tclass; 235156952Sume 236156952Sume n = dn_expand(buf, eom, cp, tname, sizeof tname); 237156952Sume if (n < 0) 238156952Sume return (-1); 239156952Sume cp += n; 240156952Sume if (cp + 2 * INT16SZ > eom) 241156952Sume return (-1); 242156952Sume ttype = ns_get16(cp); cp += INT16SZ; 243156952Sume tclass = ns_get16(cp); cp += INT16SZ; 244156952Sume if (ttype == type && tclass == class && 245156952Sume ns_samename(tname, name) == 1) 246156952Sume return (1); 247156952Sume } 248156952Sume return (0); 249156952Sume} 250156952Sume 251170244Sume/*% 252156952Sume * is there a 1:1 mapping of (name,type,class) 253156952Sume * in (buf1,eom1) and (buf2,eom2)? 254170244Sume * 255156952Sume * returns: 256170244Sume *\li -1 : format error 257170244Sume *\li 0 : not a 1:1 mapping 258170244Sume *\li >0 : is a 1:1 mapping 259170244Sume * 260156952Sume * author: 261170244Sume *\li paul vixie, 29may94 262156952Sume */ 263156952Sumeint 264156952Sumeres_queriesmatch(const u_char *buf1, const u_char *eom1, 265156952Sume const u_char *buf2, const u_char *eom2) 266156952Sume{ 267156952Sume const u_char *cp = buf1 + HFIXEDSZ; 268156952Sume int qdcount = ntohs(((const HEADER*)buf1)->qdcount); 269156952Sume 270156952Sume if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) 271156952Sume return (-1); 272156952Sume 273156952Sume /* 274156952Sume * Only header section present in replies to 275156952Sume * dynamic update packets. 276156952Sume */ 277156952Sume if ((((const HEADER *)buf1)->opcode == ns_o_update) && 278156952Sume (((const HEADER *)buf2)->opcode == ns_o_update)) 279156952Sume return (1); 280156952Sume 281156952Sume if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) 282156952Sume return (0); 283156952Sume while (qdcount-- > 0) { 284156952Sume char tname[MAXDNAME+1]; 285156952Sume int n, ttype, tclass; 286156952Sume 287156952Sume n = dn_expand(buf1, eom1, cp, tname, sizeof tname); 288156952Sume if (n < 0) 289156952Sume return (-1); 290156952Sume cp += n; 291156952Sume if (cp + 2 * INT16SZ > eom1) 292156952Sume return (-1); 293156952Sume ttype = ns_get16(cp); cp += INT16SZ; 294156952Sume tclass = ns_get16(cp); cp += INT16SZ; 295156952Sume if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) 296156952Sume return (0); 297156952Sume } 298156952Sume return (1); 299156952Sume} 300156952Sume 301156952Sumeint 302156952Sumeres_nsend(res_state statp, 303156952Sume const u_char *buf, int buflen, u_char *ans, int anssiz) 304156952Sume{ 305186090Sume int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n; 306156956Sume#ifdef USE_KQUEUE 307156956Sume int kq; 308156956Sume#endif 309156952Sume char abuf[NI_MAXHOST]; 310156952Sume 311165258Sume /* No name servers or res_init() failure */ 312165258Sume if (statp->nscount == 0 || EXT(statp).ext == NULL) { 313156952Sume errno = ESRCH; 314156952Sume return (-1); 315156952Sume } 316156952Sume if (anssiz < HFIXEDSZ) { 317156952Sume errno = EINVAL; 318156952Sume return (-1); 319156952Sume } 320156952Sume DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), 321156952Sume (stdout, ";; res_send()\n"), buf, buflen); 322156952Sume v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; 323156952Sume gotsomewhere = 0; 324156952Sume terrno = ETIMEDOUT; 325156952Sume 326156956Sume#ifdef USE_KQUEUE 327156956Sume if ((kq = kqueue()) < 0) { 328156956Sume Perror(statp, stderr, "kqueue", errno); 329156956Sume return (-1); 330156956Sume } 331156956Sume#endif 332156956Sume 333156952Sume /* 334156952Sume * If the ns_addr_list in the resolver context has changed, then 335156952Sume * invalidate our cached copy and the associated timing data. 336156952Sume */ 337156952Sume if (EXT(statp).nscount != 0) { 338156952Sume int needclose = 0; 339156952Sume struct sockaddr_storage peer; 340156952Sume ISC_SOCKLEN_T peerlen; 341156952Sume 342156952Sume if (EXT(statp).nscount != statp->nscount) 343156952Sume needclose++; 344156952Sume else 345156952Sume for (ns = 0; ns < statp->nscount; ns++) { 346156952Sume if (statp->nsaddr_list[ns].sin_family && 347156952Sume !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], 348156952Sume (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { 349156952Sume needclose++; 350156952Sume break; 351156952Sume } 352156952Sume 353156952Sume if (EXT(statp).nssocks[ns] == -1) 354156952Sume continue; 355156952Sume peerlen = sizeof(peer); 356156956Sume if (_getsockname(EXT(statp).nssocks[ns], 357156952Sume (struct sockaddr *)&peer, &peerlen) < 0) { 358156952Sume needclose++; 359156952Sume break; 360156952Sume } 361156952Sume if (!sock_eq((struct sockaddr *)&peer, 362156952Sume get_nsaddr(statp, ns))) { 363156952Sume needclose++; 364156952Sume break; 365156952Sume } 366156952Sume } 367156952Sume if (needclose) { 368156952Sume res_nclose(statp); 369156952Sume EXT(statp).nscount = 0; 370156952Sume } 371156952Sume } 372156952Sume 373156952Sume /* 374156952Sume * Maybe initialize our private copy of the ns_addr_list. 375156952Sume */ 376156952Sume if (EXT(statp).nscount == 0) { 377156952Sume for (ns = 0; ns < statp->nscount; ns++) { 378156952Sume EXT(statp).nstimes[ns] = RES_MAXTIME; 379156952Sume EXT(statp).nssocks[ns] = -1; 380156952Sume if (!statp->nsaddr_list[ns].sin_family) 381156952Sume continue; 382156952Sume EXT(statp).ext->nsaddrs[ns].sin = 383156952Sume statp->nsaddr_list[ns]; 384156952Sume } 385156952Sume EXT(statp).nscount = statp->nscount; 386156952Sume } 387156952Sume 388156952Sume /* 389156952Sume * Some resolvers want to even out the load on their nameservers. 390156952Sume * Note that RES_BLAST overrides RES_ROTATE. 391156952Sume */ 392156952Sume if ((statp->options & RES_ROTATE) != 0U && 393156952Sume (statp->options & RES_BLAST) == 0U) { 394156952Sume union res_sockaddr_union inu; 395156952Sume struct sockaddr_in ina; 396156952Sume int lastns = statp->nscount - 1; 397156952Sume int fd; 398156952Sume u_int16_t nstime; 399156952Sume 400156952Sume if (EXT(statp).ext != NULL) 401156952Sume inu = EXT(statp).ext->nsaddrs[0]; 402156952Sume ina = statp->nsaddr_list[0]; 403156952Sume fd = EXT(statp).nssocks[0]; 404156952Sume nstime = EXT(statp).nstimes[0]; 405156952Sume for (ns = 0; ns < lastns; ns++) { 406156952Sume if (EXT(statp).ext != NULL) 407156952Sume EXT(statp).ext->nsaddrs[ns] = 408156952Sume EXT(statp).ext->nsaddrs[ns + 1]; 409156952Sume statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; 410156952Sume EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; 411156952Sume EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; 412156952Sume } 413156952Sume if (EXT(statp).ext != NULL) 414156952Sume EXT(statp).ext->nsaddrs[lastns] = inu; 415156952Sume statp->nsaddr_list[lastns] = ina; 416156952Sume EXT(statp).nssocks[lastns] = fd; 417156952Sume EXT(statp).nstimes[lastns] = nstime; 418156952Sume } 419156952Sume 420156952Sume /* 421156952Sume * Send request, RETRY times, or until successful. 422156952Sume */ 423186090Sume for (tries = 0; tries < statp->retry; tries++) { 424156952Sume for (ns = 0; ns < statp->nscount; ns++) { 425156952Sume struct sockaddr *nsap; 426156952Sume int nsaplen; 427156952Sume nsap = get_nsaddr(statp, ns); 428156952Sume nsaplen = get_salen(nsap); 429156952Sume statp->_flags &= ~RES_F_LASTMASK; 430156952Sume statp->_flags |= (ns << RES_F_LASTSHIFT); 431156952Sume same_ns: 432156952Sume if (statp->qhook) { 433156952Sume int done = 0, loops = 0; 434156952Sume 435156952Sume do { 436156952Sume res_sendhookact act; 437156952Sume 438156952Sume act = (*statp->qhook)(&nsap, &buf, &buflen, 439156952Sume ans, anssiz, &resplen); 440156952Sume switch (act) { 441156952Sume case res_goahead: 442156952Sume done = 1; 443156952Sume break; 444156952Sume case res_nextns: 445156952Sume res_nclose(statp); 446156952Sume goto next_ns; 447156952Sume case res_done: 448156956Sume#ifdef USE_KQUEUE 449156956Sume _close(kq); 450156956Sume#endif 451156952Sume return (resplen); 452156952Sume case res_modified: 453156952Sume /* give the hook another try */ 454156952Sume if (++loops < 42) /*doug adams*/ 455156952Sume break; 456156952Sume /*FALLTHROUGH*/ 457156952Sume case res_error: 458156952Sume /*FALLTHROUGH*/ 459156952Sume default: 460156952Sume goto fail; 461156952Sume } 462156952Sume } while (!done); 463156952Sume } 464156952Sume 465156952Sume Dprint(((statp->options & RES_DEBUG) && 466156952Sume getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), 467156952Sume NULL, 0, niflags) == 0), 468156952Sume (stdout, ";; Querying server (# %d) address = %s\n", 469156952Sume ns + 1, abuf)); 470156952Sume 471156952Sume 472156952Sume if (v_circuit) { 473156952Sume /* Use VC; at most one attempt per server. */ 474186090Sume tries = statp->retry; 475156952Sume n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, 476156952Sume ns); 477156952Sume if (n < 0) 478156952Sume goto fail; 479156952Sume if (n == 0) 480156952Sume goto next_ns; 481156952Sume resplen = n; 482156952Sume } else { 483156952Sume /* Use datagrams. */ 484156956Sume n = send_dg(statp, 485156956Sume#ifdef USE_KQUEUE 486156956Sume kq, 487156956Sume#endif 488156956Sume buf, buflen, ans, anssiz, &terrno, 489186090Sume ns, tries, &v_circuit, &gotsomewhere); 490156952Sume if (n < 0) 491156952Sume goto fail; 492156952Sume if (n == 0) 493156952Sume goto next_ns; 494156952Sume if (v_circuit) 495156952Sume goto same_ns; 496156952Sume resplen = n; 497156952Sume } 498156952Sume 499156952Sume Dprint((statp->options & RES_DEBUG) || 500156952Sume ((statp->pfcode & RES_PRF_REPLY) && 501156952Sume (statp->pfcode & RES_PRF_HEAD1)), 502156952Sume (stdout, ";; got answer:\n")); 503156952Sume 504156952Sume DprintQ((statp->options & RES_DEBUG) || 505156952Sume (statp->pfcode & RES_PRF_REPLY), 506156952Sume (stdout, "%s", ""), 507156952Sume ans, (resplen > anssiz) ? anssiz : resplen); 508156952Sume 509156952Sume /* 510156952Sume * If we have temporarily opened a virtual circuit, 511156952Sume * or if we haven't been asked to keep a socket open, 512156952Sume * close the socket. 513156952Sume */ 514156952Sume if ((v_circuit && (statp->options & RES_USEVC) == 0U) || 515156952Sume (statp->options & RES_STAYOPEN) == 0U) { 516156952Sume res_nclose(statp); 517156952Sume } 518156952Sume if (statp->rhook) { 519156952Sume int done = 0, loops = 0; 520156952Sume 521156952Sume do { 522156952Sume res_sendhookact act; 523156952Sume 524156952Sume act = (*statp->rhook)(nsap, buf, buflen, 525156952Sume ans, anssiz, &resplen); 526156952Sume switch (act) { 527156952Sume case res_goahead: 528156952Sume case res_done: 529156952Sume done = 1; 530156952Sume break; 531156952Sume case res_nextns: 532156952Sume res_nclose(statp); 533156952Sume goto next_ns; 534156952Sume case res_modified: 535156952Sume /* give the hook another try */ 536156952Sume if (++loops < 42) /*doug adams*/ 537156952Sume break; 538156952Sume /*FALLTHROUGH*/ 539156952Sume case res_error: 540156952Sume /*FALLTHROUGH*/ 541156952Sume default: 542156952Sume goto fail; 543156952Sume } 544156952Sume } while (!done); 545156952Sume 546156952Sume } 547156956Sume#ifdef USE_KQUEUE 548156956Sume _close(kq); 549156956Sume#endif 550156952Sume return (resplen); 551156952Sume next_ns: ; 552156952Sume } /*foreach ns*/ 553156952Sume } /*foreach retry*/ 554156952Sume res_nclose(statp); 555156956Sume#ifdef USE_KQUEUE 556156956Sume _close(kq); 557156956Sume#endif 558156952Sume if (!v_circuit) { 559156952Sume if (!gotsomewhere) 560170244Sume errno = ECONNREFUSED; /*%< no nameservers found */ 561156952Sume else 562170244Sume errno = ETIMEDOUT; /*%< no answer obtained */ 563156952Sume } else 564156952Sume errno = terrno; 565156952Sume return (-1); 566156952Sume fail: 567156952Sume res_nclose(statp); 568156956Sume#ifdef USE_KQUEUE 569156956Sume _close(kq); 570156956Sume#endif 571156952Sume return (-1); 572156952Sume} 573156952Sume 574156952Sume/* Private */ 575156952Sume 576156952Sumestatic int 577156952Sumeget_salen(sa) 578156952Sume const struct sockaddr *sa; 579156952Sume{ 580156952Sume 581156952Sume#ifdef HAVE_SA_LEN 582156952Sume /* There are people do not set sa_len. Be forgiving to them. */ 583156952Sume if (sa->sa_len) 584156952Sume return (sa->sa_len); 585156952Sume#endif 586156952Sume 587156952Sume if (sa->sa_family == AF_INET) 588156952Sume return (sizeof(struct sockaddr_in)); 589156952Sume else if (sa->sa_family == AF_INET6) 590156952Sume return (sizeof(struct sockaddr_in6)); 591156952Sume else 592170244Sume return (0); /*%< unknown, die on connect */ 593156952Sume} 594156952Sume 595170244Sume/*% 596156952Sume * pick appropriate nsaddr_list for use. see res_init() for initialization. 597156952Sume */ 598156952Sumestatic struct sockaddr * 599156952Sumeget_nsaddr(statp, n) 600156952Sume res_state statp; 601156952Sume size_t n; 602156952Sume{ 603156952Sume 604156952Sume if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { 605156952Sume /* 606156952Sume * - EXT(statp).ext->nsaddrs[n] holds an address that is larger 607156952Sume * than struct sockaddr, and 608156952Sume * - user code did not update statp->nsaddr_list[n]. 609156952Sume */ 610156952Sume return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; 611156952Sume } else { 612156952Sume /* 613156952Sume * - user code updated statp->nsaddr_list[n], or 614156952Sume * - statp->nsaddr_list[n] has the same content as 615156952Sume * EXT(statp).ext->nsaddrs[n]. 616156952Sume */ 617156952Sume return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; 618156952Sume } 619156952Sume} 620156952Sume 621156952Sumestatic int 622156952Sumesend_vc(res_state statp, 623156952Sume const u_char *buf, int buflen, u_char *ans, int anssiz, 624156952Sume int *terrno, int ns) 625156952Sume{ 626156952Sume const HEADER *hp = (const HEADER *) buf; 627156952Sume HEADER *anhp = (HEADER *) ans; 628156952Sume struct sockaddr *nsap; 629156952Sume int nsaplen; 630156952Sume int truncating, connreset, resplen, n; 631156952Sume struct iovec iov[2]; 632156952Sume u_short len; 633156952Sume u_char *cp; 634156952Sume void *tmp; 635186090Sume#ifdef SO_NOSIGPIPE 636186090Sume int on = 1; 637186090Sume#endif 638156952Sume 639156952Sume nsap = get_nsaddr(statp, ns); 640156952Sume nsaplen = get_salen(nsap); 641156952Sume 642156952Sume connreset = 0; 643156952Sume same_ns: 644156952Sume truncating = 0; 645156952Sume 646156952Sume /* Are we still talking to whom we want to talk to? */ 647156952Sume if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { 648156952Sume struct sockaddr_storage peer; 649156952Sume ISC_SOCKLEN_T size = sizeof peer; 650156952Sume 651156956Sume if (_getpeername(statp->_vcsock, 652156952Sume (struct sockaddr *)&peer, &size) < 0 || 653156952Sume !sock_eq((struct sockaddr *)&peer, nsap)) { 654156952Sume res_nclose(statp); 655156952Sume statp->_flags &= ~RES_F_VC; 656156952Sume } 657156952Sume } 658156952Sume 659156952Sume if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { 660156952Sume if (statp->_vcsock >= 0) 661156952Sume res_nclose(statp); 662156952Sume 663255336Sjilles statp->_vcsock = _socket(nsap->sa_family, SOCK_STREAM | 664255336Sjilles SOCK_CLOEXEC, 0); 665167246Sjhb#if !defined(USE_POLL) && !defined(USE_KQUEUE) 666156952Sume if (statp->_vcsock > highestFD) { 667156952Sume res_nclose(statp); 668156952Sume errno = ENOTSOCK; 669156952Sume } 670167246Sjhb#endif 671156952Sume if (statp->_vcsock < 0) { 672156952Sume switch (errno) { 673156952Sume case EPROTONOSUPPORT: 674156952Sume#ifdef EPFNOSUPPORT 675156952Sume case EPFNOSUPPORT: 676156952Sume#endif 677156952Sume case EAFNOSUPPORT: 678156952Sume Perror(statp, stderr, "socket(vc)", errno); 679156952Sume return (0); 680156952Sume default: 681156952Sume *terrno = errno; 682156952Sume Perror(statp, stderr, "socket(vc)", errno); 683156952Sume return (-1); 684156952Sume } 685156952Sume } 686186090Sume#ifdef SO_NOSIGPIPE 687186090Sume /* 688186090Sume * Disable generation of SIGPIPE when writing to a closed 689186090Sume * socket. Write should return -1 and set errno to EPIPE 690186090Sume * instead. 691186090Sume * 692186090Sume * Push on even if setsockopt(SO_NOSIGPIPE) fails. 693186090Sume */ 694186090Sume (void)_setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on, 695186090Sume sizeof(on)); 696186090Sume#endif 697156952Sume errno = 0; 698156956Sume if (_connect(statp->_vcsock, nsap, nsaplen) < 0) { 699156952Sume *terrno = errno; 700156952Sume Aerror(statp, stderr, "connect/vc", errno, nsap, 701156952Sume nsaplen); 702156952Sume res_nclose(statp); 703156952Sume return (0); 704156952Sume } 705156952Sume statp->_flags |= RES_F_VC; 706156952Sume } 707156952Sume 708156952Sume /* 709156952Sume * Send length & message 710156952Sume */ 711156952Sume ns_put16((u_short)buflen, (u_char*)&len); 712156952Sume iov[0] = evConsIovec(&len, INT16SZ); 713156952Sume DE_CONST(buf, tmp); 714156952Sume iov[1] = evConsIovec(tmp, buflen); 715156956Sume if (_writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { 716156952Sume *terrno = errno; 717156952Sume Perror(statp, stderr, "write failed", errno); 718156952Sume res_nclose(statp); 719156952Sume return (0); 720156952Sume } 721156952Sume /* 722156952Sume * Receive length & response 723156952Sume */ 724156952Sume read_len: 725156952Sume cp = ans; 726156952Sume len = INT16SZ; 727156956Sume while ((n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) { 728156952Sume cp += n; 729156952Sume if ((len -= n) == 0) 730156952Sume break; 731156952Sume } 732156952Sume if (n <= 0) { 733156952Sume *terrno = errno; 734156952Sume Perror(statp, stderr, "read failed", errno); 735156952Sume res_nclose(statp); 736156952Sume /* 737156952Sume * A long running process might get its TCP 738156952Sume * connection reset if the remote server was 739156952Sume * restarted. Requery the server instead of 740156952Sume * trying a new one. When there is only one 741156952Sume * server, this means that a query might work 742156952Sume * instead of failing. We only allow one reset 743156952Sume * per query to prevent looping. 744156952Sume */ 745156952Sume if (*terrno == ECONNRESET && !connreset) { 746156952Sume connreset = 1; 747156952Sume res_nclose(statp); 748156952Sume goto same_ns; 749156952Sume } 750156952Sume res_nclose(statp); 751156952Sume return (0); 752156952Sume } 753156952Sume resplen = ns_get16(ans); 754156952Sume if (resplen > anssiz) { 755156952Sume Dprint(statp->options & RES_DEBUG, 756156952Sume (stdout, ";; response truncated\n") 757156952Sume ); 758156952Sume truncating = 1; 759156952Sume len = anssiz; 760156952Sume } else 761156952Sume len = resplen; 762156952Sume if (len < HFIXEDSZ) { 763156952Sume /* 764156952Sume * Undersized message. 765156952Sume */ 766156952Sume Dprint(statp->options & RES_DEBUG, 767156952Sume (stdout, ";; undersized: %d\n", len)); 768156952Sume *terrno = EMSGSIZE; 769156952Sume res_nclose(statp); 770156952Sume return (0); 771156952Sume } 772156952Sume cp = ans; 773156956Sume while (len != 0 && 774156956Sume (n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) { 775156952Sume cp += n; 776156952Sume len -= n; 777156952Sume } 778156952Sume if (n <= 0) { 779156952Sume *terrno = errno; 780156952Sume Perror(statp, stderr, "read(vc)", errno); 781156952Sume res_nclose(statp); 782156952Sume return (0); 783156952Sume } 784156952Sume if (truncating) { 785156952Sume /* 786156952Sume * Flush rest of answer so connection stays in synch. 787156952Sume */ 788156952Sume anhp->tc = 1; 789156952Sume len = resplen - anssiz; 790156952Sume while (len != 0) { 791156952Sume char junk[PACKETSZ]; 792156952Sume 793156956Sume n = _read(statp->_vcsock, junk, 794156956Sume (len > sizeof junk) ? sizeof junk : len); 795156952Sume if (n > 0) 796156952Sume len -= n; 797156952Sume else 798156952Sume break; 799156952Sume } 800156952Sume } 801156952Sume /* 802156952Sume * If the calling applicating has bailed out of 803156952Sume * a previous call and failed to arrange to have 804156952Sume * the circuit closed or the server has got 805156952Sume * itself confused, then drop the packet and 806156952Sume * wait for the correct one. 807156952Sume */ 808156952Sume if (hp->id != anhp->id) { 809156952Sume DprintQ((statp->options & RES_DEBUG) || 810156952Sume (statp->pfcode & RES_PRF_REPLY), 811156952Sume (stdout, ";; old answer (unexpected):\n"), 812156952Sume ans, (resplen > anssiz) ? anssiz: resplen); 813156952Sume goto read_len; 814156952Sume } 815156952Sume 816156952Sume /* 817156952Sume * All is well, or the error is fatal. Signal that the 818156952Sume * next nameserver ought not be tried. 819156952Sume */ 820156952Sume return (resplen); 821156952Sume} 822156952Sume 823156952Sumestatic int 824156952Sumesend_dg(res_state statp, 825156956Sume#ifdef USE_KQUEUE 826156956Sume int kq, 827156956Sume#endif 828163661Sume const u_char *buf, int buflen, u_char *ans, 829186090Sume int anssiz, int *terrno, int ns, int tries, int *v_circuit, 830163661Sume int *gotsomewhere) 831156952Sume{ 832156952Sume const HEADER *hp = (const HEADER *) buf; 833156952Sume HEADER *anhp = (HEADER *) ans; 834156952Sume const struct sockaddr *nsap; 835156952Sume int nsaplen; 836156952Sume struct timespec now, timeout, finish; 837156952Sume struct sockaddr_storage from; 838156952Sume ISC_SOCKLEN_T fromlen; 839156952Sume int resplen, seconds, n, s; 840156956Sume#ifdef USE_KQUEUE 841156956Sume struct kevent kv; 842156956Sume#else 843156952Sume#ifdef USE_POLL 844156952Sume int polltimeout; 845156952Sume struct pollfd pollfd; 846156952Sume#else 847156952Sume fd_set dsmask; 848156952Sume#endif 849156956Sume#endif 850156952Sume 851156952Sume nsap = get_nsaddr(statp, ns); 852156952Sume nsaplen = get_salen(nsap); 853156952Sume if (EXT(statp).nssocks[ns] == -1) { 854156956Sume EXT(statp).nssocks[ns] = _socket(nsap->sa_family, 855255336Sjilles SOCK_DGRAM | SOCK_CLOEXEC, 0); 856167246Sjhb#if !defined(USE_POLL) && !defined(USE_KQUEUE) 857156952Sume if (EXT(statp).nssocks[ns] > highestFD) { 858156952Sume res_nclose(statp); 859156952Sume errno = ENOTSOCK; 860156952Sume } 861167246Sjhb#endif 862156952Sume if (EXT(statp).nssocks[ns] < 0) { 863156952Sume switch (errno) { 864156952Sume case EPROTONOSUPPORT: 865156952Sume#ifdef EPFNOSUPPORT 866156952Sume case EPFNOSUPPORT: 867156952Sume#endif 868156952Sume case EAFNOSUPPORT: 869156952Sume Perror(statp, stderr, "socket(dg)", errno); 870156952Sume return (0); 871156952Sume default: 872156952Sume *terrno = errno; 873156952Sume Perror(statp, stderr, "socket(dg)", errno); 874156952Sume return (-1); 875156952Sume } 876156952Sume } 877156952Sume#ifndef CANNOT_CONNECT_DGRAM 878156952Sume /* 879156952Sume * On a 4.3BSD+ machine (client and server, 880156952Sume * actually), sending to a nameserver datagram 881156952Sume * port with no nameserver will cause an 882156952Sume * ICMP port unreachable message to be returned. 883156952Sume * If our datagram socket is "connected" to the 884156952Sume * server, we get an ECONNREFUSED error on the next 885156952Sume * socket operation, and select returns if the 886156952Sume * error message is received. We can thus detect 887156952Sume * the absence of a nameserver without timing out. 888156956Sume * 889156956Sume * When the option "insecure1" is specified, we'd 890156956Sume * rather expect to see responses from an "unknown" 891156956Sume * address. In order to let the kernel accept such 892156956Sume * responses, do not connect the socket here. 893156956Sume * XXX: or do we need an explicit option to disable 894156956Sume * connecting? 895156952Sume */ 896156956Sume if (!(statp->options & RES_INSECURE1) && 897156956Sume _connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { 898156952Sume Aerror(statp, stderr, "connect(dg)", errno, nsap, 899156952Sume nsaplen); 900156952Sume res_nclose(statp); 901156952Sume return (0); 902156952Sume } 903156952Sume#endif /* !CANNOT_CONNECT_DGRAM */ 904156952Sume Dprint(statp->options & RES_DEBUG, 905156952Sume (stdout, ";; new DG socket\n")) 906156952Sume } 907156952Sume s = EXT(statp).nssocks[ns]; 908156952Sume#ifndef CANNOT_CONNECT_DGRAM 909156956Sume if (statp->options & RES_INSECURE1) { 910156956Sume if (_sendto(s, 911156956Sume (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) { 912156956Sume Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 913156956Sume res_nclose(statp); 914156956Sume return (0); 915156956Sume } 916156956Sume } else if (send(s, (const char*)buf, buflen, 0) != buflen) { 917156952Sume Perror(statp, stderr, "send", errno); 918156952Sume res_nclose(statp); 919156952Sume return (0); 920156952Sume } 921156952Sume#else /* !CANNOT_CONNECT_DGRAM */ 922156956Sume if (_sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) 923156952Sume { 924156952Sume Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 925156952Sume res_nclose(statp); 926156952Sume return (0); 927156952Sume } 928156952Sume#endif /* !CANNOT_CONNECT_DGRAM */ 929156952Sume 930156952Sume /* 931156952Sume * Wait for reply. 932156952Sume */ 933186090Sume seconds = (statp->retrans << tries); 934156952Sume if (ns > 0) 935156952Sume seconds /= statp->nscount; 936156952Sume if (seconds <= 0) 937156952Sume seconds = 1; 938156952Sume now = evNowTime(); 939156952Sume timeout = evConsTime(seconds, 0); 940156952Sume finish = evAddTime(now, timeout); 941156952Sume goto nonow; 942156952Sume wait: 943156952Sume now = evNowTime(); 944156952Sume nonow: 945156952Sume#ifndef USE_POLL 946156952Sume if (evCmpTime(finish, now) > 0) 947156952Sume timeout = evSubTime(finish, now); 948156952Sume else 949156952Sume timeout = evConsTime(0, 0); 950156956Sume#ifdef USE_KQUEUE 951156956Sume EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0); 952156956Sume n = _kevent(kq, &kv, 1, &kv, 1, &timeout); 953156956Sume#else 954156956Sume FD_ZERO(&dsmask); 955156956Sume FD_SET(s, &dsmask); 956156952Sume n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); 957156956Sume#endif 958156952Sume#else 959156952Sume timeout = evSubTime(finish, now); 960156952Sume if (timeout.tv_sec < 0) 961156952Sume timeout = evConsTime(0, 0); 962156952Sume polltimeout = 1000*timeout.tv_sec + 963156952Sume timeout.tv_nsec/1000000; 964156952Sume pollfd.fd = s; 965156952Sume pollfd.events = POLLRDNORM; 966260652Sjilles n = _poll(&pollfd, 1, polltimeout); 967156952Sume#endif /* USE_POLL */ 968156952Sume 969156952Sume if (n == 0) { 970156952Sume Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); 971156952Sume *gotsomewhere = 1; 972156952Sume return (0); 973156952Sume } 974156952Sume if (n < 0) { 975156952Sume if (errno == EINTR) 976156952Sume goto wait; 977156956Sume#ifdef USE_KQUEUE 978156956Sume Perror(statp, stderr, "kevent", errno); 979156956Sume#else 980156952Sume#ifndef USE_POLL 981156952Sume Perror(statp, stderr, "select", errno); 982156952Sume#else 983156952Sume Perror(statp, stderr, "poll", errno); 984156952Sume#endif /* USE_POLL */ 985156956Sume#endif 986156952Sume res_nclose(statp); 987156952Sume return (0); 988156952Sume } 989160967Sume#ifdef USE_KQUEUE 990160967Sume if (kv.ident != s) 991160967Sume goto wait; 992160967Sume#endif 993156952Sume errno = 0; 994156952Sume fromlen = sizeof(from); 995156956Sume resplen = _recvfrom(s, (char*)ans, anssiz,0, 996156952Sume (struct sockaddr *)&from, &fromlen); 997156952Sume if (resplen <= 0) { 998156952Sume Perror(statp, stderr, "recvfrom", errno); 999156952Sume res_nclose(statp); 1000156952Sume return (0); 1001156952Sume } 1002156952Sume *gotsomewhere = 1; 1003156952Sume if (resplen < HFIXEDSZ) { 1004156952Sume /* 1005156952Sume * Undersized message. 1006156952Sume */ 1007156952Sume Dprint(statp->options & RES_DEBUG, 1008156952Sume (stdout, ";; undersized: %d\n", 1009156952Sume resplen)); 1010156952Sume *terrno = EMSGSIZE; 1011156952Sume res_nclose(statp); 1012156952Sume return (0); 1013156952Sume } 1014156952Sume if (hp->id != anhp->id) { 1015156952Sume /* 1016156952Sume * response from old query, ignore it. 1017156952Sume * XXX - potential security hazard could 1018156952Sume * be detected here. 1019156952Sume */ 1020156952Sume DprintQ((statp->options & RES_DEBUG) || 1021156952Sume (statp->pfcode & RES_PRF_REPLY), 1022156952Sume (stdout, ";; old answer:\n"), 1023156952Sume ans, (resplen > anssiz) ? anssiz : resplen); 1024156952Sume goto wait; 1025156952Sume } 1026156952Sume if (!(statp->options & RES_INSECURE1) && 1027156952Sume !res_ourserver_p(statp, (struct sockaddr *)&from)) { 1028156952Sume /* 1029156952Sume * response from wrong server? ignore it. 1030156952Sume * XXX - potential security hazard could 1031156952Sume * be detected here. 1032156952Sume */ 1033156952Sume DprintQ((statp->options & RES_DEBUG) || 1034156952Sume (statp->pfcode & RES_PRF_REPLY), 1035156952Sume (stdout, ";; not our server:\n"), 1036156952Sume ans, (resplen > anssiz) ? anssiz : resplen); 1037156952Sume goto wait; 1038156952Sume } 1039156952Sume#ifdef RES_USE_EDNS0 1040156952Sume if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) { 1041156952Sume /* 1042156952Sume * Do not retry if the server do not understand EDNS0. 1043156952Sume * The case has to be captured here, as FORMERR packet do not 1044156952Sume * carry query section, hence res_queriesmatch() returns 0. 1045156952Sume */ 1046156952Sume DprintQ(statp->options & RES_DEBUG, 1047156952Sume (stdout, "server rejected query with EDNS0:\n"), 1048156952Sume ans, (resplen > anssiz) ? anssiz : resplen); 1049156952Sume /* record the error */ 1050156952Sume statp->_flags |= RES_F_EDNS0ERR; 1051156952Sume res_nclose(statp); 1052156952Sume return (0); 1053156952Sume } 1054156952Sume#endif 1055156952Sume if (!(statp->options & RES_INSECURE2) && 1056156952Sume !res_queriesmatch(buf, buf + buflen, 1057156952Sume ans, ans + anssiz)) { 1058156952Sume /* 1059156952Sume * response contains wrong query? ignore it. 1060156952Sume * XXX - potential security hazard could 1061156952Sume * be detected here. 1062156952Sume */ 1063156952Sume DprintQ((statp->options & RES_DEBUG) || 1064156952Sume (statp->pfcode & RES_PRF_REPLY), 1065156952Sume (stdout, ";; wrong query name:\n"), 1066156952Sume ans, (resplen > anssiz) ? anssiz : resplen); 1067156952Sume goto wait; 1068156952Sume } 1069156952Sume if (anhp->rcode == SERVFAIL || 1070156952Sume anhp->rcode == NOTIMP || 1071156952Sume anhp->rcode == REFUSED) { 1072156952Sume DprintQ(statp->options & RES_DEBUG, 1073156952Sume (stdout, "server rejected query:\n"), 1074156952Sume ans, (resplen > anssiz) ? anssiz : resplen); 1075156952Sume res_nclose(statp); 1076156952Sume /* don't retry if called from dig */ 1077156952Sume if (!statp->pfcode) 1078156952Sume return (0); 1079156952Sume } 1080156952Sume if (!(statp->options & RES_IGNTC) && anhp->tc) { 1081156952Sume /* 1082156952Sume * To get the rest of answer, 1083156952Sume * use TCP with same server. 1084156952Sume */ 1085156952Sume Dprint(statp->options & RES_DEBUG, 1086156952Sume (stdout, ";; truncated answer\n")); 1087156952Sume *v_circuit = 1; 1088156952Sume res_nclose(statp); 1089156952Sume return (1); 1090156952Sume } 1091156952Sume /* 1092156952Sume * All is well, or the error is fatal. Signal that the 1093156952Sume * next nameserver ought not be tried. 1094156952Sume */ 1095156952Sume return (resplen); 1096156952Sume} 1097156952Sume 1098156952Sumestatic void 1099156952SumeAerror(const res_state statp, FILE *file, const char *string, int error, 1100156952Sume const struct sockaddr *address, int alen) 1101156952Sume{ 1102156952Sume int save = errno; 1103156952Sume char hbuf[NI_MAXHOST]; 1104156952Sume char sbuf[NI_MAXSERV]; 1105156952Sume 1106156952Sume if ((statp->options & RES_DEBUG) != 0U) { 1107156952Sume if (getnameinfo(address, alen, hbuf, sizeof(hbuf), 1108156952Sume sbuf, sizeof(sbuf), niflags)) { 1109156952Sume strncpy(hbuf, "?", sizeof(hbuf) - 1); 1110156952Sume hbuf[sizeof(hbuf) - 1] = '\0'; 1111156952Sume strncpy(sbuf, "?", sizeof(sbuf) - 1); 1112156952Sume sbuf[sizeof(sbuf) - 1] = '\0'; 1113156952Sume } 1114156952Sume fprintf(file, "res_send: %s ([%s].%s): %s\n", 1115156952Sume string, hbuf, sbuf, strerror(error)); 1116156952Sume } 1117156952Sume errno = save; 1118156952Sume} 1119156952Sume 1120156952Sumestatic void 1121156952SumePerror(const res_state statp, FILE *file, const char *string, int error) { 1122156952Sume int save = errno; 1123156952Sume 1124156952Sume if ((statp->options & RES_DEBUG) != 0U) 1125156952Sume fprintf(file, "res_send: %s: %s\n", 1126156952Sume string, strerror(error)); 1127156952Sume errno = save; 1128156952Sume} 1129156952Sume 1130156952Sumestatic int 1131156952Sumesock_eq(struct sockaddr *a, struct sockaddr *b) { 1132156952Sume struct sockaddr_in *a4, *b4; 1133156952Sume struct sockaddr_in6 *a6, *b6; 1134156952Sume 1135156952Sume if (a->sa_family != b->sa_family) 1136156952Sume return 0; 1137156952Sume switch (a->sa_family) { 1138156952Sume case AF_INET: 1139156952Sume a4 = (struct sockaddr_in *)a; 1140156952Sume b4 = (struct sockaddr_in *)b; 1141156952Sume return a4->sin_port == b4->sin_port && 1142156952Sume a4->sin_addr.s_addr == b4->sin_addr.s_addr; 1143156952Sume case AF_INET6: 1144156952Sume a6 = (struct sockaddr_in6 *)a; 1145156952Sume b6 = (struct sockaddr_in6 *)b; 1146156952Sume return a6->sin6_port == b6->sin6_port && 1147156952Sume#ifdef HAVE_SIN6_SCOPE_ID 1148156952Sume a6->sin6_scope_id == b6->sin6_scope_id && 1149156952Sume#endif 1150156952Sume IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); 1151156952Sume default: 1152156952Sume return 0; 1153156952Sume } 1154156952Sume} 1155156952Sume 1156156956Sume#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) 1157156952Sume/* XXX needs to move to the porting library. */ 1158156952Sumestatic int 1159156952Sumepselect(int nfds, void *rfds, void *wfds, void *efds, 1160156952Sume struct timespec *tsp, const sigset_t *sigmask) 1161156952Sume{ 1162156952Sume struct timeval tv, *tvp; 1163156952Sume sigset_t sigs; 1164156952Sume int n; 1165156952Sume 1166156952Sume if (tsp) { 1167156952Sume tvp = &tv; 1168156952Sume tv = evTimeVal(*tsp); 1169156952Sume } else 1170156952Sume tvp = NULL; 1171156952Sume if (sigmask) 1172156952Sume sigprocmask(SIG_SETMASK, sigmask, &sigs); 1173156952Sume n = select(nfds, rfds, wfds, efds, tvp); 1174156952Sume if (sigmask) 1175156952Sume sigprocmask(SIG_SETMASK, &sigs, NULL); 1176156952Sume if (tsp) 1177156952Sume *tsp = evTimeSpec(tv); 1178156952Sume return (n); 1179156952Sume} 1180156952Sume#endif 1181