Fix SPARC atomic_write_barrier.
[glibc.git] / resolv / res_send.c
blobaf42b8aac216356a5466998df5c47c21357881d3
1 /*
2 * Copyright (c) 1985, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
31 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
33 * Permission to use, copy, modify, and distribute this software for any
34 * purpose with or without fee is hereby granted, provided that the above
35 * copyright notice and this permission notice appear in all copies, and that
36 * the name of Digital Equipment Corporation not be used in advertising or
37 * publicity pertaining to distribution of the document or software without
38 * specific, written prior permission.
40 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
43 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 * SOFTWARE.
51 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
53 * Permission to use, copy, modify, and distribute this software for any
54 * purpose with or without fee is hereby granted, provided that the above
55 * copyright notice and this permission notice appear in all copies.
57 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
58 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
60 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
61 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
62 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
63 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
64 * SOFTWARE.
67 #if defined(LIBC_SCCS) && !defined(lint)
68 static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
69 static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixie Exp $";
70 #endif /* LIBC_SCCS and not lint */
73 * Send query to name server and wait for reply.
76 #include <assert.h>
77 #include <sys/types.h>
78 #include <sys/param.h>
79 #include <sys/time.h>
80 #include <sys/socket.h>
81 #include <sys/uio.h>
82 #include <sys/poll.h>
84 #include <netinet/in.h>
85 #include <arpa/nameser.h>
86 #include <arpa/inet.h>
87 #include <sys/ioctl.h>
89 #include <errno.h>
90 #include <fcntl.h>
91 #include <netdb.h>
92 #include <resolv.h>
93 #include <signal.h>
94 #include <stdio.h>
95 #include <stdlib.h>
96 #include <string.h>
97 #include <unistd.h>
98 #include <kernel-features.h>
100 #if PACKETSZ > 65536
101 #define MAXPACKET PACKETSZ
102 #else
103 #define MAXPACKET 65536
104 #endif
107 #ifndef __ASSUME_SOCK_CLOEXEC
108 static int __have_o_nonblock;
109 #else
110 # define __have_o_nonblock 0
111 #endif
114 /* From ev_streams.c. */
116 static inline void
117 __attribute ((always_inline))
118 evConsIovec(void *buf, size_t cnt, struct iovec *vec) {
119 memset(vec, 0xf5, sizeof (*vec));
120 vec->iov_base = buf;
121 vec->iov_len = cnt;
124 /* From ev_timers.c. */
126 #define BILLION 1000000000
128 static inline void
129 evConsTime(struct timespec *res, time_t sec, long nsec) {
130 res->tv_sec = sec;
131 res->tv_nsec = nsec;
134 static inline void
135 evAddTime(struct timespec *res, const struct timespec *addend1,
136 const struct timespec *addend2) {
137 res->tv_sec = addend1->tv_sec + addend2->tv_sec;
138 res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec;
139 if (res->tv_nsec >= BILLION) {
140 res->tv_sec++;
141 res->tv_nsec -= BILLION;
145 static inline void
146 evSubTime(struct timespec *res, const struct timespec *minuend,
147 const struct timespec *subtrahend) {
148 res->tv_sec = minuend->tv_sec - subtrahend->tv_sec;
149 if (minuend->tv_nsec >= subtrahend->tv_nsec)
150 res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec;
151 else {
152 res->tv_nsec = (BILLION
153 - subtrahend->tv_nsec + minuend->tv_nsec);
154 res->tv_sec--;
158 static int
159 evCmpTime(struct timespec a, struct timespec b) {
160 long x = a.tv_sec - b.tv_sec;
162 if (x == 0L)
163 x = a.tv_nsec - b.tv_nsec;
164 return (x < 0L ? (-1) : x > 0L ? (1) : (0));
167 static void
168 evNowTime(struct timespec *res) {
169 struct timeval now;
171 if (gettimeofday(&now, NULL) < 0)
172 evConsTime(res, 0, 0);
173 else
174 TIMEVAL_TO_TIMESPEC (&now, res);
178 /* Options. Leave them on. */
179 /* #undef DEBUG */
180 #include "res_debug.h"
182 #define EXT(res) ((res)->_u._ext)
184 /* Forward. */
186 static int send_vc(res_state, const u_char *, int,
187 const u_char *, int,
188 u_char **, int *, int *, int, u_char **,
189 u_char **, int *, int *, int *);
190 static int send_dg(res_state, const u_char *, int,
191 const u_char *, int,
192 u_char **, int *, int *, int,
193 int *, int *, u_char **,
194 u_char **, int *, int *, int *);
195 #ifdef DEBUG
196 static void Aerror(const res_state, FILE *, const char *, int,
197 const struct sockaddr *);
198 static void Perror(const res_state, FILE *, const char *, int);
199 #endif
200 static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
202 /* Public. */
204 /* int
205 * res_isourserver(ina)
206 * looks up "ina" in _res.ns_addr_list[]
207 * returns:
208 * 0 : not found
209 * >0 : found
210 * author:
211 * paul vixie, 29may94
214 res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
216 int ns;
218 if (inp->sin6_family == AF_INET) {
219 struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
220 in_port_t port = in4p->sin_port;
221 in_addr_t addr = in4p->sin_addr.s_addr;
223 for (ns = 0; ns < MAXNS; ns++) {
224 const struct sockaddr_in *srv =
225 (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
227 if ((srv != NULL) && (srv->sin_family == AF_INET) &&
228 (srv->sin_port == port) &&
229 (srv->sin_addr.s_addr == INADDR_ANY ||
230 srv->sin_addr.s_addr == addr))
231 return (1);
233 } else if (inp->sin6_family == AF_INET6) {
234 for (ns = 0; ns < MAXNS; ns++) {
235 const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
236 if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
237 (srv->sin6_port == inp->sin6_port) &&
238 !(memcmp(&srv->sin6_addr, &in6addr_any,
239 sizeof (struct in6_addr)) &&
240 memcmp(&srv->sin6_addr, &inp->sin6_addr,
241 sizeof (struct in6_addr))))
242 return (1);
245 return (0);
248 /* int
249 * res_nameinquery(name, type, class, buf, eom)
250 * look for (name,type,class) in the query section of packet (buf,eom)
251 * requires:
252 * buf + HFIXEDSZ <= eom
253 * returns:
254 * -1 : format error
255 * 0 : not found
256 * >0 : found
257 * author:
258 * paul vixie, 29may94
261 res_nameinquery(const char *name, int type, int class,
262 const u_char *buf, const u_char *eom)
264 const u_char *cp = buf + HFIXEDSZ;
265 int qdcount = ntohs(((HEADER*)buf)->qdcount);
267 while (qdcount-- > 0) {
268 char tname[MAXDNAME+1];
269 int n, ttype, tclass;
271 n = dn_expand(buf, eom, cp, tname, sizeof tname);
272 if (n < 0)
273 return (-1);
274 cp += n;
275 if (cp + 2 * INT16SZ > eom)
276 return (-1);
277 NS_GET16(ttype, cp);
278 NS_GET16(tclass, cp);
279 if (ttype == type && tclass == class &&
280 ns_samename(tname, name) == 1)
281 return (1);
283 return (0);
285 libresolv_hidden_def (res_nameinquery)
287 /* int
288 * res_queriesmatch(buf1, eom1, buf2, eom2)
289 * is there a 1:1 mapping of (name,type,class)
290 * in (buf1,eom1) and (buf2,eom2)?
291 * returns:
292 * -1 : format error
293 * 0 : not a 1:1 mapping
294 * >0 : is a 1:1 mapping
295 * author:
296 * paul vixie, 29may94
299 res_queriesmatch(const u_char *buf1, const u_char *eom1,
300 const u_char *buf2, const u_char *eom2)
302 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
303 return (-1);
306 * Only header section present in replies to
307 * dynamic update packets.
309 if ((((HEADER *)buf1)->opcode == ns_o_update) &&
310 (((HEADER *)buf2)->opcode == ns_o_update))
311 return (1);
313 /* Note that we initially do not convert QDCOUNT to the host byte
314 order. We can compare it with the second buffer's QDCOUNT
315 value without doing this. */
316 int qdcount = ((HEADER*)buf1)->qdcount;
317 if (qdcount != ((HEADER*)buf2)->qdcount)
318 return (0);
320 qdcount = htons (qdcount);
321 const u_char *cp = buf1 + HFIXEDSZ;
323 while (qdcount-- > 0) {
324 char tname[MAXDNAME+1];
325 int n, ttype, tclass;
327 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
328 if (n < 0)
329 return (-1);
330 cp += n;
331 if (cp + 2 * INT16SZ > eom1)
332 return (-1);
333 NS_GET16(ttype, cp);
334 NS_GET16(tclass, cp);
335 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
336 return (0);
338 return (1);
340 libresolv_hidden_def (res_queriesmatch)
343 __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
344 const u_char *buf2, int buflen2,
345 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
346 int *nansp2, int *resplen2, int *ansp2_malloced)
348 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
350 if (statp->nscount == 0) {
351 __set_errno (ESRCH);
352 return (-1);
355 if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) {
356 __set_errno (EINVAL);
357 return (-1);
360 #ifdef USE_HOOKS
361 if (__glibc_unlikely (statp->qhook || statp->rhook)) {
362 if (anssiz < MAXPACKET && ansp) {
363 u_char *buf = malloc (MAXPACKET);
364 if (buf == NULL)
365 return (-1);
366 memcpy (buf, ans, HFIXEDSZ);
367 *ansp = buf;
368 ans = buf;
369 anssiz = MAXPACKET;
372 #endif
374 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
375 (stdout, ";; res_send()\n"), buf, buflen);
376 v_circuit = ((statp->options & RES_USEVC)
377 || buflen > PACKETSZ
378 || buflen2 > PACKETSZ);
379 gotsomewhere = 0;
380 terrno = ETIMEDOUT;
383 * If the ns_addr_list in the resolver context has changed, then
384 * invalidate our cached copy and the associated timing data.
386 if (EXT(statp).nsinit) {
387 int needclose = 0;
389 if (EXT(statp).nscount != statp->nscount)
390 needclose++;
391 else
392 for (ns = 0; ns < MAXNS; ns++) {
393 unsigned int map = EXT(statp).nsmap[ns];
394 if (map < MAXNS
395 && !sock_eq((struct sockaddr_in6 *)
396 &statp->nsaddr_list[map],
397 EXT(statp).nsaddrs[ns]))
399 needclose++;
400 break;
403 if (needclose)
404 __res_iclose(statp, false);
408 * Maybe initialize our private copy of the ns_addr_list.
410 if (EXT(statp).nsinit == 0) {
411 unsigned char map[MAXNS];
413 memset (map, MAXNS, sizeof (map));
414 for (n = 0; n < MAXNS; n++) {
415 ns = EXT(statp).nsmap[n];
416 if (ns < statp->nscount)
417 map[ns] = n;
418 else if (ns < MAXNS) {
419 free(EXT(statp).nsaddrs[n]);
420 EXT(statp).nsaddrs[n] = NULL;
421 EXT(statp).nsmap[n] = MAXNS;
424 n = statp->nscount;
425 if (statp->nscount > EXT(statp).nscount)
426 for (n = EXT(statp).nscount, ns = 0;
427 n < statp->nscount; n++) {
428 while (ns < MAXNS
429 && EXT(statp).nsmap[ns] != MAXNS)
430 ns++;
431 if (ns == MAXNS)
432 break;
433 EXT(statp).nsmap[ns] = n;
434 map[n] = ns++;
436 EXT(statp).nscount = n;
437 for (ns = 0; ns < EXT(statp).nscount; ns++) {
438 n = map[ns];
439 if (EXT(statp).nsaddrs[n] == NULL)
440 EXT(statp).nsaddrs[n] =
441 malloc(sizeof (struct sockaddr_in6));
442 if (EXT(statp).nsaddrs[n] != NULL) {
443 memset (mempcpy(EXT(statp).nsaddrs[n],
444 &statp->nsaddr_list[ns],
445 sizeof (struct sockaddr_in)),
446 '\0',
447 sizeof (struct sockaddr_in6)
448 - sizeof (struct sockaddr_in));
449 EXT(statp).nssocks[n] = -1;
450 n++;
453 EXT(statp).nsinit = 1;
457 * Some resolvers want to even out the load on their nameservers.
458 * Note that RES_BLAST overrides RES_ROTATE.
460 if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
461 (statp->options & RES_BLAST) == 0) {
462 struct sockaddr_in6 *ina;
463 unsigned int map;
465 n = 0;
466 while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
467 n++;
468 if (n < MAXNS) {
469 ina = EXT(statp).nsaddrs[n];
470 map = EXT(statp).nsmap[n];
471 for (;;) {
472 ns = n + 1;
473 while (ns < MAXNS
474 && EXT(statp).nsmap[ns] == MAXNS)
475 ns++;
476 if (ns == MAXNS)
477 break;
478 EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
479 EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
480 n = ns;
482 EXT(statp).nsaddrs[n] = ina;
483 EXT(statp).nsmap[n] = map;
488 * Send request, RETRY times, or until successful.
490 for (try = 0; try < statp->retry; try++) {
491 for (ns = 0; ns < MAXNS; ns++)
493 #ifdef DEBUG
494 char tmpbuf[40];
495 #endif
496 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
498 if (nsap == NULL)
499 goto next_ns;
500 same_ns:
501 #ifdef USE_HOOKS
502 if (__glibc_unlikely (statp->qhook != NULL)) {
503 int done = 0, loops = 0;
505 do {
506 res_sendhookact act;
508 struct sockaddr_in *nsap4;
509 nsap4 = (struct sockaddr_in *) nsap;
510 act = (*statp->qhook)(&nsap4, &buf, &buflen,
511 ans, anssiz, &resplen);
512 nsap = (struct sockaddr_in6 *) nsap4;
513 switch (act) {
514 case res_goahead:
515 done = 1;
516 break;
517 case res_nextns:
518 __res_iclose(statp, false);
519 goto next_ns;
520 case res_done:
521 return (resplen);
522 case res_modified:
523 /* give the hook another try */
524 if (++loops < 42) /*doug adams*/
525 break;
526 /*FALLTHROUGH*/
527 case res_error:
528 /*FALLTHROUGH*/
529 default:
530 return (-1);
532 } while (!done);
534 #endif
536 Dprint(statp->options & RES_DEBUG,
537 (stdout, ";; Querying server (# %d) address = %s\n",
538 ns + 1, inet_ntop(nsap->sin6_family,
539 (nsap->sin6_family == AF_INET6
540 ? &nsap->sin6_addr
541 : &((struct sockaddr_in *) nsap)->sin_addr),
542 tmpbuf, sizeof (tmpbuf))));
544 if (__glibc_unlikely (v_circuit)) {
545 /* Use VC; at most one attempt per server. */
546 try = statp->retry;
547 n = send_vc(statp, buf, buflen, buf2, buflen2,
548 &ans, &anssiz, &terrno,
549 ns, ansp, ansp2, nansp2, resplen2,
550 ansp2_malloced);
551 if (n < 0)
552 return (-1);
553 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
554 goto next_ns;
555 } else {
556 /* Use datagrams. */
557 n = send_dg(statp, buf, buflen, buf2, buflen2,
558 &ans, &anssiz, &terrno,
559 ns, &v_circuit, &gotsomewhere, ansp,
560 ansp2, nansp2, resplen2, ansp2_malloced);
561 if (n < 0)
562 return (-1);
563 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
564 goto next_ns;
565 if (v_circuit)
566 // XXX Check whether both requests failed or
567 // XXX whether one has been answered successfully
568 goto same_ns;
571 resplen = n;
573 Dprint((statp->options & RES_DEBUG) ||
574 ((statp->pfcode & RES_PRF_REPLY) &&
575 (statp->pfcode & RES_PRF_HEAD1)),
576 (stdout, ";; got answer:\n"));
578 DprintQ((statp->options & RES_DEBUG) ||
579 (statp->pfcode & RES_PRF_REPLY),
580 (stdout, "%s", ""),
581 ans, (resplen > anssiz) ? anssiz : resplen);
582 if (buf2 != NULL) {
583 DprintQ((statp->options & RES_DEBUG) ||
584 (statp->pfcode & RES_PRF_REPLY),
585 (stdout, "%s", ""),
586 *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
590 * If we have temporarily opened a virtual circuit,
591 * or if we haven't been asked to keep a socket open,
592 * close the socket.
594 if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
595 (statp->options & RES_STAYOPEN) == 0) {
596 __res_iclose(statp, false);
598 #ifdef USE_HOOKS
599 if (__glibc_unlikely (statp->rhook)) {
600 int done = 0, loops = 0;
602 do {
603 res_sendhookact act;
605 act = (*statp->rhook)((struct sockaddr_in *)
606 nsap, buf, buflen,
607 ans, anssiz, &resplen);
608 switch (act) {
609 case res_goahead:
610 case res_done:
611 done = 1;
612 break;
613 case res_nextns:
614 __res_iclose(statp, false);
615 goto next_ns;
616 case res_modified:
617 /* give the hook another try */
618 if (++loops < 42) /*doug adams*/
619 break;
620 /*FALLTHROUGH*/
621 case res_error:
622 /*FALLTHROUGH*/
623 default:
624 return (-1);
626 } while (!done);
629 #endif
630 return (resplen);
631 next_ns: ;
632 } /*foreach ns*/
633 } /*foreach retry*/
634 __res_iclose(statp, false);
635 if (!v_circuit) {
636 if (!gotsomewhere)
637 __set_errno (ECONNREFUSED); /* no nameservers found */
638 else
639 __set_errno (ETIMEDOUT); /* no answer obtained */
640 } else
641 __set_errno (terrno);
642 return (-1);
646 res_nsend(res_state statp,
647 const u_char *buf, int buflen, u_char *ans, int anssiz)
649 return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
650 NULL, NULL, NULL, NULL, NULL);
652 libresolv_hidden_def (res_nsend)
654 /* Private */
656 static int
657 send_vc(res_state statp,
658 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
659 u_char **ansp, int *anssizp,
660 int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
661 int *resplen2, int *ansp2_malloced)
663 const HEADER *hp = (HEADER *) buf;
664 const HEADER *hp2 = (HEADER *) buf2;
665 u_char *ans = *ansp;
666 int orig_anssizp = *anssizp;
667 // XXX REMOVE
668 // int anssiz = *anssizp;
669 HEADER *anhp = (HEADER *) ans;
670 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
671 int truncating, connreset, resplen, n;
672 struct iovec iov[4];
673 u_short len;
674 u_short len2;
675 u_char *cp;
677 if (resplen2 != NULL)
678 *resplen2 = 0;
679 connreset = 0;
680 same_ns:
681 truncating = 0;
683 /* Are we still talking to whom we want to talk to? */
684 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
685 struct sockaddr_in6 peer;
686 socklen_t size = sizeof peer;
688 if (getpeername(statp->_vcsock,
689 (struct sockaddr *)&peer, &size) < 0 ||
690 !sock_eq(&peer, nsap)) {
691 __res_iclose(statp, false);
692 statp->_flags &= ~RES_F_VC;
696 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
697 if (statp->_vcsock >= 0)
698 __res_iclose(statp, false);
700 statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0);
701 if (statp->_vcsock < 0) {
702 *terrno = errno;
703 Perror(statp, stderr, "socket(vc)", errno);
704 return (-1);
706 __set_errno (0);
707 if (connect(statp->_vcsock, (struct sockaddr *)nsap,
708 nsap->sin6_family == AF_INET
709 ? sizeof (struct sockaddr_in)
710 : sizeof (struct sockaddr_in6)) < 0) {
711 *terrno = errno;
712 Aerror(statp, stderr, "connect/vc", errno,
713 (struct sockaddr *) nsap);
714 __res_iclose(statp, false);
715 return (0);
717 statp->_flags |= RES_F_VC;
721 * Send length & message
723 len = htons ((u_short) buflen);
724 evConsIovec(&len, INT16SZ, &iov[0]);
725 evConsIovec((void*)buf, buflen, &iov[1]);
726 int niov = 2;
727 ssize_t explen = INT16SZ + buflen;
728 if (buf2 != NULL) {
729 len2 = htons ((u_short) buflen2);
730 evConsIovec(&len2, INT16SZ, &iov[2]);
731 evConsIovec((void*)buf2, buflen2, &iov[3]);
732 niov = 4;
733 explen += INT16SZ + buflen2;
735 if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
736 *terrno = errno;
737 Perror(statp, stderr, "write failed", errno);
738 __res_iclose(statp, false);
739 return (0);
742 * Receive length & response
744 int recvresp1 = 0;
745 int recvresp2 = buf2 == NULL;
746 uint16_t rlen16;
747 read_len:
748 cp = (u_char *)&rlen16;
749 len = sizeof(rlen16);
750 while ((n = TEMP_FAILURE_RETRY (read(statp->_vcsock, cp,
751 (int)len))) > 0) {
752 cp += n;
753 if ((len -= n) <= 0)
754 break;
756 if (n <= 0) {
757 *terrno = errno;
758 Perror(statp, stderr, "read failed", errno);
759 __res_iclose(statp, false);
761 * A long running process might get its TCP
762 * connection reset if the remote server was
763 * restarted. Requery the server instead of
764 * trying a new one. When there is only one
765 * server, this means that a query might work
766 * instead of failing. We only allow one reset
767 * per query to prevent looping.
769 if (*terrno == ECONNRESET && !connreset) {
770 connreset = 1;
771 goto same_ns;
773 return (0);
775 int rlen = ntohs (rlen16);
777 int *thisanssizp;
778 u_char **thisansp;
779 int *thisresplenp;
780 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
781 thisanssizp = anssizp;
782 thisansp = anscp ?: ansp;
783 assert (anscp != NULL || ansp2 == NULL);
784 thisresplenp = &resplen;
785 } else {
786 if (*anssizp != MAXPACKET) {
787 /* No buffer allocated for the first
788 reply. We can try to use the rest
789 of the user-provided buffer. */
790 #if _STRING_ARCH_unaligned
791 *anssizp2 = orig_anssizp - resplen;
792 *ansp2 = *ansp + resplen;
793 #else
794 int aligned_resplen
795 = ((resplen + __alignof__ (HEADER) - 1)
796 & ~(__alignof__ (HEADER) - 1));
797 *anssizp2 = orig_anssizp - aligned_resplen;
798 *ansp2 = *ansp + aligned_resplen;
799 #endif
800 } else {
801 /* The first reply did not fit into the
802 user-provided buffer. Maybe the second
803 answer will. */
804 *anssizp2 = orig_anssizp;
805 *ansp2 = *ansp;
808 thisanssizp = anssizp2;
809 thisansp = ansp2;
810 thisresplenp = resplen2;
812 anhp = (HEADER *) *thisansp;
814 *thisresplenp = rlen;
815 if (rlen > *thisanssizp) {
816 /* Yes, we test ANSCP here. If we have two buffers
817 both will be allocatable. */
818 if (__glibc_likely (anscp != NULL)) {
819 u_char *newp = malloc (MAXPACKET);
820 if (newp == NULL) {
821 *terrno = ENOMEM;
822 __res_iclose(statp, false);
823 return (0);
825 *thisanssizp = MAXPACKET;
826 *thisansp = newp;
827 if (thisansp == ansp2)
828 *ansp2_malloced = 1;
829 anhp = (HEADER *) newp;
830 len = rlen;
831 } else {
832 Dprint(statp->options & RES_DEBUG,
833 (stdout, ";; response truncated\n")
835 truncating = 1;
836 len = *thisanssizp;
838 } else
839 len = rlen;
841 if (__glibc_unlikely (len < HFIXEDSZ)) {
843 * Undersized message.
845 Dprint(statp->options & RES_DEBUG,
846 (stdout, ";; undersized: %d\n", len));
847 *terrno = EMSGSIZE;
848 __res_iclose(statp, false);
849 return (0);
852 cp = *thisansp;
853 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
854 cp += n;
855 len -= n;
857 if (__glibc_unlikely (n <= 0)) {
858 *terrno = errno;
859 Perror(statp, stderr, "read(vc)", errno);
860 __res_iclose(statp, false);
861 return (0);
863 if (__glibc_unlikely (truncating)) {
865 * Flush rest of answer so connection stays in synch.
867 anhp->tc = 1;
868 len = rlen - *thisanssizp;
869 while (len != 0) {
870 char junk[PACKETSZ];
872 n = read(statp->_vcsock, junk,
873 (len > sizeof junk) ? sizeof junk : len);
874 if (n > 0)
875 len -= n;
876 else
877 break;
881 * If the calling application has bailed out of
882 * a previous call and failed to arrange to have
883 * the circuit closed or the server has got
884 * itself confused, then drop the packet and
885 * wait for the correct one.
887 if ((recvresp1 || hp->id != anhp->id)
888 && (recvresp2 || hp2->id != anhp->id)) {
889 DprintQ((statp->options & RES_DEBUG) ||
890 (statp->pfcode & RES_PRF_REPLY),
891 (stdout, ";; old answer (unexpected):\n"),
892 *thisansp,
893 (rlen > *thisanssizp) ? *thisanssizp: rlen);
894 goto read_len;
897 /* Mark which reply we received. */
898 if (recvresp1 == 0 && hp->id == anhp->id)
899 recvresp1 = 1;
900 else
901 recvresp2 = 1;
902 /* Repeat waiting if we have a second answer to arrive. */
903 if ((recvresp1 & recvresp2) == 0)
904 goto read_len;
907 * All is well, or the error is fatal. Signal that the
908 * next nameserver ought not be tried.
910 return resplen;
913 static int
914 reopen (res_state statp, int *terrno, int ns)
916 if (EXT(statp).nssocks[ns] == -1) {
917 struct sockaddr *nsap
918 = (struct sockaddr *) EXT(statp).nsaddrs[ns];
919 socklen_t slen;
921 /* only try IPv6 if IPv6 NS and if not failed before */
922 if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
923 if (__glibc_likely (__have_o_nonblock >= 0)) {
924 EXT(statp).nssocks[ns] =
925 socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK,
927 #ifndef __ASSUME_SOCK_CLOEXEC
928 if (__have_o_nonblock == 0)
929 __have_o_nonblock
930 = (EXT(statp).nssocks[ns] == -1
931 && errno == EINVAL ? -1 : 1);
932 #endif
934 if (__glibc_unlikely (__have_o_nonblock < 0))
935 EXT(statp).nssocks[ns] =
936 socket(PF_INET6, SOCK_DGRAM, 0);
937 if (EXT(statp).nssocks[ns] < 0)
938 statp->ipv6_unavail = errno == EAFNOSUPPORT;
939 slen = sizeof (struct sockaddr_in6);
940 } else if (nsap->sa_family == AF_INET) {
941 if (__glibc_likely (__have_o_nonblock >= 0)) {
942 EXT(statp).nssocks[ns]
943 = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK,
945 #ifndef __ASSUME_SOCK_CLOEXEC
946 if (__have_o_nonblock == 0)
947 __have_o_nonblock
948 = (EXT(statp).nssocks[ns] == -1
949 && errno == EINVAL ? -1 : 1);
950 #endif
952 if (__glibc_unlikely (__have_o_nonblock < 0))
953 EXT(statp).nssocks[ns]
954 = socket(PF_INET, SOCK_DGRAM, 0);
955 slen = sizeof (struct sockaddr_in);
957 if (EXT(statp).nssocks[ns] < 0) {
958 *terrno = errno;
959 Perror(statp, stderr, "socket(dg)", errno);
960 return (-1);
964 * On a 4.3BSD+ machine (client and server,
965 * actually), sending to a nameserver datagram
966 * port with no nameserver will cause an
967 * ICMP port unreachable message to be returned.
968 * If our datagram socket is "connected" to the
969 * server, we get an ECONNREFUSED error on the next
970 * socket operation, and select returns if the
971 * error message is received. We can thus detect
972 * the absence of a nameserver without timing out.
974 if (connect(EXT(statp).nssocks[ns], nsap, slen) < 0) {
975 Aerror(statp, stderr, "connect(dg)", errno, nsap);
976 __res_iclose(statp, false);
977 return (0);
979 if (__glibc_unlikely (__have_o_nonblock < 0)) {
980 /* Make socket non-blocking. */
981 int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL);
982 if (fl != -1)
983 __fcntl (EXT(statp).nssocks[ns], F_SETFL,
984 fl | O_NONBLOCK);
985 Dprint(statp->options & RES_DEBUG,
986 (stdout, ";; new DG socket\n"))
990 return 1;
993 static int
994 send_dg(res_state statp,
995 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
996 u_char **ansp, int *anssizp,
997 int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
998 u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
1000 const HEADER *hp = (HEADER *) buf;
1001 const HEADER *hp2 = (HEADER *) buf2;
1002 u_char *ans = *ansp;
1003 int orig_anssizp = *anssizp;
1004 struct timespec now, timeout, finish;
1005 struct pollfd pfd[1];
1006 int ptimeout;
1007 struct sockaddr_in6 from;
1008 int resplen = 0;
1009 int n;
1012 * Compute time for the total operation.
1014 int seconds = (statp->retrans << ns);
1015 if (ns > 0)
1016 seconds /= statp->nscount;
1017 if (seconds <= 0)
1018 seconds = 1;
1019 bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
1020 bool single_request = (((statp->options & RES_SNGLKUP) != 0)
1021 | single_request_reopen);
1022 int save_gotsomewhere = *gotsomewhere;
1024 int retval;
1025 retry_reopen:
1026 retval = reopen (statp, terrno, ns);
1027 if (retval <= 0)
1028 return retval;
1029 retry:
1030 evNowTime(&now);
1031 evConsTime(&timeout, seconds, 0);
1032 evAddTime(&finish, &now, &timeout);
1033 int need_recompute = 0;
1034 int nwritten = 0;
1035 int recvresp1 = 0;
1036 int recvresp2 = buf2 == NULL;
1037 pfd[0].fd = EXT(statp).nssocks[ns];
1038 pfd[0].events = POLLOUT;
1039 if (resplen2 != NULL)
1040 *resplen2 = 0;
1041 wait:
1042 if (need_recompute) {
1043 recompute_resend:
1044 evNowTime(&now);
1045 if (evCmpTime(finish, now) <= 0) {
1046 poll_err_out:
1047 Perror(statp, stderr, "poll", errno);
1048 err_out:
1049 __res_iclose(statp, false);
1050 return (0);
1052 evSubTime(&timeout, &finish, &now);
1053 need_recompute = 0;
1055 /* Convert struct timespec in milliseconds. */
1056 ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
1058 n = 0;
1059 if (nwritten == 0)
1060 n = __poll (pfd, 1, 0);
1061 if (__glibc_unlikely (n == 0)) {
1062 n = __poll (pfd, 1, ptimeout);
1063 need_recompute = 1;
1065 if (n == 0) {
1066 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1067 if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
1069 /* There are quite a few broken name servers out
1070 there which don't handle two outstanding
1071 requests from the same source. There are also
1072 broken firewall settings. If we time out after
1073 having received one answer switch to the mode
1074 where we send the second request only once we
1075 have received the first answer. */
1076 if (!single_request)
1078 statp->options |= RES_SNGLKUP;
1079 single_request = true;
1080 *gotsomewhere = save_gotsomewhere;
1081 goto retry;
1083 else if (!single_request_reopen)
1085 statp->options |= RES_SNGLKUPREOP;
1086 single_request_reopen = true;
1087 *gotsomewhere = save_gotsomewhere;
1088 __res_iclose (statp, false);
1089 goto retry_reopen;
1092 *resplen2 = 1;
1093 return resplen;
1096 *gotsomewhere = 1;
1097 return (0);
1099 if (n < 0) {
1100 if (errno == EINTR)
1101 goto recompute_resend;
1103 goto poll_err_out;
1105 __set_errno (0);
1106 if (pfd[0].revents & POLLOUT) {
1107 #ifndef __ASSUME_SENDMMSG
1108 static int have_sendmmsg;
1109 #else
1110 # define have_sendmmsg 1
1111 #endif
1112 if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL
1113 && !single_request)
1115 struct iovec iov[2];
1116 struct mmsghdr reqs[2];
1117 reqs[0].msg_hdr.msg_name = NULL;
1118 reqs[0].msg_hdr.msg_namelen = 0;
1119 reqs[0].msg_hdr.msg_iov = &iov[0];
1120 reqs[0].msg_hdr.msg_iovlen = 1;
1121 iov[0].iov_base = (void *) buf;
1122 iov[0].iov_len = buflen;
1123 reqs[0].msg_hdr.msg_control = NULL;
1124 reqs[0].msg_hdr.msg_controllen = 0;
1126 reqs[1].msg_hdr.msg_name = NULL;
1127 reqs[1].msg_hdr.msg_namelen = 0;
1128 reqs[1].msg_hdr.msg_iov = &iov[1];
1129 reqs[1].msg_hdr.msg_iovlen = 1;
1130 iov[1].iov_base = (void *) buf2;
1131 iov[1].iov_len = buflen2;
1132 reqs[1].msg_hdr.msg_control = NULL;
1133 reqs[1].msg_hdr.msg_controllen = 0;
1135 int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL);
1136 if (__glibc_likely (ndg == 2))
1138 if (reqs[0].msg_len != buflen
1139 || reqs[1].msg_len != buflen2)
1140 goto fail_sendmmsg;
1142 pfd[0].events = POLLIN;
1143 nwritten += 2;
1145 else if (ndg == 1 && reqs[0].msg_len == buflen)
1146 goto just_one;
1147 else if (ndg < 0 && (errno == EINTR || errno == EAGAIN))
1148 goto recompute_resend;
1149 else
1151 #ifndef __ASSUME_SENDMMSG
1152 if (__glibc_unlikely (have_sendmmsg == 0))
1154 if (ndg < 0 && errno == ENOSYS)
1156 have_sendmmsg = -1;
1157 goto try_send;
1159 have_sendmmsg = 1;
1161 #endif
1163 fail_sendmmsg:
1164 Perror(statp, stderr, "sendmmsg", errno);
1165 goto err_out;
1168 else
1170 ssize_t sr;
1171 #ifndef __ASSUME_SENDMMSG
1172 try_send:
1173 #endif
1174 if (nwritten != 0)
1175 sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
1176 else
1177 sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
1179 if (sr != (nwritten != 0 ? buflen2 : buflen)) {
1180 if (errno == EINTR || errno == EAGAIN)
1181 goto recompute_resend;
1182 Perror(statp, stderr, "send", errno);
1183 goto err_out;
1185 just_one:
1186 if (nwritten != 0 || buf2 == NULL || single_request)
1187 pfd[0].events = POLLIN;
1188 else
1189 pfd[0].events = POLLIN | POLLOUT;
1190 ++nwritten;
1192 goto wait;
1193 } else if (pfd[0].revents & POLLIN) {
1194 int *thisanssizp;
1195 u_char **thisansp;
1196 int *thisresplenp;
1198 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1199 thisanssizp = anssizp;
1200 thisansp = anscp ?: ansp;
1201 assert (anscp != NULL || ansp2 == NULL);
1202 thisresplenp = &resplen;
1203 } else {
1204 if (*anssizp != MAXPACKET) {
1205 /* No buffer allocated for the first
1206 reply. We can try to use the rest
1207 of the user-provided buffer. */
1208 #if _STRING_ARCH_unaligned
1209 *anssizp2 = orig_anssizp - resplen;
1210 *ansp2 = *ansp + resplen;
1211 #else
1212 int aligned_resplen
1213 = ((resplen + __alignof__ (HEADER) - 1)
1214 & ~(__alignof__ (HEADER) - 1));
1215 *anssizp2 = orig_anssizp - aligned_resplen;
1216 *ansp2 = *ansp + aligned_resplen;
1217 #endif
1218 } else {
1219 /* The first reply did not fit into the
1220 user-provided buffer. Maybe the second
1221 answer will. */
1222 *anssizp2 = orig_anssizp;
1223 *ansp2 = *ansp;
1226 thisanssizp = anssizp2;
1227 thisansp = ansp2;
1228 thisresplenp = resplen2;
1231 if (*thisanssizp < MAXPACKET
1232 /* Yes, we test ANSCP here. If we have two buffers
1233 both will be allocatable. */
1234 && anscp
1235 #ifdef FIONREAD
1236 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
1237 || *thisanssizp < *thisresplenp)
1238 #endif
1240 u_char *newp = malloc (MAXPACKET);
1241 if (newp != NULL) {
1242 *anssizp = MAXPACKET;
1243 *thisansp = ans = newp;
1244 if (thisansp == ansp2)
1245 *ansp2_malloced = 1;
1248 HEADER *anhp = (HEADER *) *thisansp;
1249 socklen_t fromlen = sizeof(struct sockaddr_in6);
1250 assert (sizeof(from) <= fromlen);
1251 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1252 *thisanssizp, 0,
1253 (struct sockaddr *)&from, &fromlen);
1254 if (__glibc_unlikely (*thisresplenp <= 0)) {
1255 if (errno == EINTR || errno == EAGAIN) {
1256 need_recompute = 1;
1257 goto wait;
1259 Perror(statp, stderr, "recvfrom", errno);
1260 goto err_out;
1262 *gotsomewhere = 1;
1263 if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
1265 * Undersized message.
1267 Dprint(statp->options & RES_DEBUG,
1268 (stdout, ";; undersized: %d\n",
1269 *thisresplenp));
1270 *terrno = EMSGSIZE;
1271 goto err_out;
1273 if ((recvresp1 || hp->id != anhp->id)
1274 && (recvresp2 || hp2->id != anhp->id)) {
1276 * response from old query, ignore it.
1277 * XXX - potential security hazard could
1278 * be detected here.
1280 DprintQ((statp->options & RES_DEBUG) ||
1281 (statp->pfcode & RES_PRF_REPLY),
1282 (stdout, ";; old answer:\n"),
1283 *thisansp,
1284 (*thisresplenp > *thisanssizp)
1285 ? *thisanssizp : *thisresplenp);
1286 goto wait;
1288 if (!(statp->options & RES_INSECURE1) &&
1289 !res_ourserver_p(statp, &from)) {
1291 * response from wrong server? ignore it.
1292 * XXX - potential security hazard could
1293 * be detected here.
1295 DprintQ((statp->options & RES_DEBUG) ||
1296 (statp->pfcode & RES_PRF_REPLY),
1297 (stdout, ";; not our server:\n"),
1298 *thisansp,
1299 (*thisresplenp > *thisanssizp)
1300 ? *thisanssizp : *thisresplenp);
1301 goto wait;
1303 #ifdef RES_USE_EDNS0
1304 if (anhp->rcode == FORMERR
1305 && (statp->options & RES_USE_EDNS0) != 0U) {
1307 * Do not retry if the server does not understand
1308 * EDNS0. The case has to be captured here, as
1309 * FORMERR packet do not carry query section, hence
1310 * res_queriesmatch() returns 0.
1312 DprintQ(statp->options & RES_DEBUG,
1313 (stdout,
1314 "server rejected query with EDNS0:\n"),
1315 *thisansp,
1316 (*thisresplenp > *thisanssizp)
1317 ? *thisanssizp : *thisresplenp);
1318 /* record the error */
1319 statp->_flags |= RES_F_EDNS0ERR;
1320 goto err_out;
1322 #endif
1323 if (!(statp->options & RES_INSECURE2)
1324 && (recvresp1 || !res_queriesmatch(buf, buf + buflen,
1325 *thisansp,
1326 *thisansp
1327 + *thisanssizp))
1328 && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
1329 *thisansp,
1330 *thisansp
1331 + *thisanssizp))) {
1333 * response contains wrong query? ignore it.
1334 * XXX - potential security hazard could
1335 * be detected here.
1337 DprintQ((statp->options & RES_DEBUG) ||
1338 (statp->pfcode & RES_PRF_REPLY),
1339 (stdout, ";; wrong query name:\n"),
1340 *thisansp,
1341 (*thisresplenp > *thisanssizp)
1342 ? *thisanssizp : *thisresplenp);
1343 goto wait;
1345 if (anhp->rcode == SERVFAIL ||
1346 anhp->rcode == NOTIMP ||
1347 anhp->rcode == REFUSED) {
1348 DprintQ(statp->options & RES_DEBUG,
1349 (stdout, "server rejected query:\n"),
1350 *thisansp,
1351 (*thisresplenp > *thisanssizp)
1352 ? *thisanssizp : *thisresplenp);
1354 next_ns:
1355 if (recvresp1 || (buf2 != NULL && recvresp2)) {
1356 *resplen2 = 0;
1357 return resplen;
1359 if (buf2 != NULL)
1361 /* No data from the first reply. */
1362 resplen = 0;
1363 /* We are waiting for a possible second reply. */
1364 if (hp->id == anhp->id)
1365 recvresp1 = 1;
1366 else
1367 recvresp2 = 1;
1369 goto wait;
1372 __res_iclose(statp, false);
1373 /* don't retry if called from dig */
1374 if (!statp->pfcode)
1375 return (0);
1377 if (anhp->rcode == NOERROR && anhp->ancount == 0
1378 && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
1379 DprintQ(statp->options & RES_DEBUG,
1380 (stdout, "referred query:\n"),
1381 *thisansp,
1382 (*thisresplenp > *thisanssizp)
1383 ? *thisanssizp : *thisresplenp);
1384 goto next_ns;
1386 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1388 * To get the rest of answer,
1389 * use TCP with same server.
1391 Dprint(statp->options & RES_DEBUG,
1392 (stdout, ";; truncated answer\n"));
1393 *v_circuit = 1;
1394 __res_iclose(statp, false);
1395 // XXX if we have received one reply we could
1396 // XXX use it and not repeat it over TCP...
1397 return (1);
1399 /* Mark which reply we received. */
1400 if (recvresp1 == 0 && hp->id == anhp->id)
1401 recvresp1 = 1;
1402 else
1403 recvresp2 = 1;
1404 /* Repeat waiting if we have a second answer to arrive. */
1405 if ((recvresp1 & recvresp2) == 0) {
1406 if (single_request) {
1407 pfd[0].events = POLLOUT;
1408 if (single_request_reopen) {
1409 __res_iclose (statp, false);
1410 retval = reopen (statp, terrno, ns);
1411 if (retval <= 0)
1412 return retval;
1413 pfd[0].fd = EXT(statp).nssocks[ns];
1416 goto wait;
1419 * All is well, or the error is fatal. Signal that the
1420 * next nameserver ought not be tried.
1422 return (resplen);
1423 } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
1424 /* Something went wrong. We can stop trying. */
1425 goto err_out;
1427 else {
1428 /* poll should not have returned > 0 in this case. */
1429 abort ();
1433 #ifdef DEBUG
1434 static void
1435 Aerror(const res_state statp, FILE *file, const char *string, int error,
1436 const struct sockaddr *address)
1438 int save = errno;
1440 if ((statp->options & RES_DEBUG) != 0) {
1441 char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
1443 fprintf(file, "res_send: %s ([%s].%u): %s\n",
1444 string,
1445 (address->sa_family == AF_INET
1446 ? inet_ntop(address->sa_family,
1447 &((const struct sockaddr_in *) address)->sin_addr,
1448 tmp, sizeof tmp)
1449 : inet_ntop(address->sa_family,
1450 &((const struct sockaddr_in6 *) address)->sin6_addr,
1451 tmp, sizeof tmp)),
1452 (address->sa_family == AF_INET
1453 ? ntohs(((struct sockaddr_in *) address)->sin_port)
1454 : address->sa_family == AF_INET6
1455 ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
1456 : 0),
1457 strerror(error));
1459 __set_errno (save);
1462 static void
1463 Perror(const res_state statp, FILE *file, const char *string, int error) {
1464 int save = errno;
1466 if ((statp->options & RES_DEBUG) != 0)
1467 fprintf(file, "res_send: %s: %s\n",
1468 string, strerror(error));
1469 __set_errno (save);
1471 #endif
1473 static int
1474 sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
1475 if (a1->sin6_family == a2->sin6_family) {
1476 if (a1->sin6_family == AF_INET)
1477 return ((((struct sockaddr_in *)a1)->sin_port ==
1478 ((struct sockaddr_in *)a2)->sin_port) &&
1479 (((struct sockaddr_in *)a1)->sin_addr.s_addr ==
1480 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1481 else
1482 return ((a1->sin6_port == a2->sin6_port) &&
1483 !memcmp(&a1->sin6_addr, &a2->sin6_addr,
1484 sizeof (struct in6_addr)));
1486 if (a1->sin6_family == AF_INET) {
1487 struct sockaddr_in6 *sap = a1;
1488 a1 = a2;
1489 a2 = sap;
1490 } /* assumes that AF_INET and AF_INET6 are the only possibilities */
1491 return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) &&
1492 IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) &&
1493 (a1->sin6_addr.s6_addr32[3] ==
1494 ((struct sockaddr_in *)a2)->sin_addr.s_addr));