S390: Ifunc resolver macro for vector instructions.
[glibc.git] / resolv / res_send.c
blob5e53cc2df6a7eb654b5a49b05a8898d25d933d1b
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>
99 #include <libc-internal.h>
101 #if PACKETSZ > 65536
102 #define MAXPACKET PACKETSZ
103 #else
104 #define MAXPACKET 65536
105 #endif
108 #ifndef __ASSUME_SOCK_CLOEXEC
109 static int __have_o_nonblock;
110 #else
111 # define __have_o_nonblock 0
112 #endif
115 /* From ev_streams.c. */
117 static inline void
118 __attribute ((always_inline))
119 evConsIovec(void *buf, size_t cnt, struct iovec *vec) {
120 memset(vec, 0xf5, sizeof (*vec));
121 vec->iov_base = buf;
122 vec->iov_len = cnt;
125 /* From ev_timers.c. */
127 #define BILLION 1000000000
129 static inline void
130 evConsTime(struct timespec *res, time_t sec, long nsec) {
131 res->tv_sec = sec;
132 res->tv_nsec = nsec;
135 static inline void
136 evAddTime(struct timespec *res, const struct timespec *addend1,
137 const struct timespec *addend2) {
138 res->tv_sec = addend1->tv_sec + addend2->tv_sec;
139 res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec;
140 if (res->tv_nsec >= BILLION) {
141 res->tv_sec++;
142 res->tv_nsec -= BILLION;
146 static inline void
147 evSubTime(struct timespec *res, const struct timespec *minuend,
148 const struct timespec *subtrahend) {
149 res->tv_sec = minuend->tv_sec - subtrahend->tv_sec;
150 if (minuend->tv_nsec >= subtrahend->tv_nsec)
151 res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec;
152 else {
153 res->tv_nsec = (BILLION
154 - subtrahend->tv_nsec + minuend->tv_nsec);
155 res->tv_sec--;
159 static int
160 evCmpTime(struct timespec a, struct timespec b) {
161 long x = a.tv_sec - b.tv_sec;
163 if (x == 0L)
164 x = a.tv_nsec - b.tv_nsec;
165 return (x < 0L ? (-1) : x > 0L ? (1) : (0));
168 static void
169 evNowTime(struct timespec *res) {
170 struct timeval now;
172 if (gettimeofday(&now, NULL) < 0)
173 evConsTime(res, 0, 0);
174 else
175 TIMEVAL_TO_TIMESPEC (&now, res);
179 /* Options. Leave them on. */
180 /* #undef DEBUG */
181 #include "res_debug.h"
183 #define EXT(res) ((res)->_u._ext)
185 /* Forward. */
187 static struct sockaddr *get_nsaddr (res_state, int);
188 static int send_vc(res_state, const u_char *, int,
189 const u_char *, int,
190 u_char **, int *, int *, int, u_char **,
191 u_char **, int *, int *, int *);
192 static int send_dg(res_state, const u_char *, int,
193 const u_char *, int,
194 u_char **, int *, int *, int,
195 int *, int *, u_char **,
196 u_char **, int *, int *, int *);
197 #ifdef DEBUG
198 static void Aerror(const res_state, FILE *, const char *, int,
199 const struct sockaddr *);
200 static void Perror(const res_state, FILE *, const char *, int);
201 #endif
202 static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
204 /* Public. */
206 /* int
207 * res_isourserver(ina)
208 * looks up "ina" in _res.ns_addr_list[]
209 * returns:
210 * 0 : not found
211 * >0 : found
212 * author:
213 * paul vixie, 29may94
216 res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
218 int ns;
220 if (inp->sin6_family == AF_INET) {
221 struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
222 in_port_t port = in4p->sin_port;
223 in_addr_t addr = in4p->sin_addr.s_addr;
225 for (ns = 0; ns < statp->nscount; ns++) {
226 const struct sockaddr_in *srv =
227 (struct sockaddr_in *) get_nsaddr (statp, ns);
229 if ((srv->sin_family == AF_INET) &&
230 (srv->sin_port == port) &&
231 (srv->sin_addr.s_addr == INADDR_ANY ||
232 srv->sin_addr.s_addr == addr))
233 return (1);
235 } else if (inp->sin6_family == AF_INET6) {
236 for (ns = 0; ns < statp->nscount; ns++) {
237 const struct sockaddr_in6 *srv
238 = (struct sockaddr_in6 *) get_nsaddr (statp, ns);
239 if ((srv->sin6_family == AF_INET6) &&
240 (srv->sin6_port == inp->sin6_port) &&
241 !(memcmp(&srv->sin6_addr, &in6addr_any,
242 sizeof (struct in6_addr)) &&
243 memcmp(&srv->sin6_addr, &inp->sin6_addr,
244 sizeof (struct in6_addr))))
245 return (1);
248 return (0);
251 /* int
252 * res_nameinquery(name, type, class, buf, eom)
253 * look for (name,type,class) in the query section of packet (buf,eom)
254 * requires:
255 * buf + HFIXEDSZ <= eom
256 * returns:
257 * -1 : format error
258 * 0 : not found
259 * >0 : found
260 * author:
261 * paul vixie, 29may94
264 res_nameinquery(const char *name, int type, int class,
265 const u_char *buf, const u_char *eom)
267 const u_char *cp = buf + HFIXEDSZ;
268 int qdcount = ntohs(((HEADER*)buf)->qdcount);
270 while (qdcount-- > 0) {
271 char tname[MAXDNAME+1];
272 int n, ttype, tclass;
274 n = dn_expand(buf, eom, cp, tname, sizeof tname);
275 if (n < 0)
276 return (-1);
277 cp += n;
278 if (cp + 2 * INT16SZ > eom)
279 return (-1);
280 NS_GET16(ttype, cp);
281 NS_GET16(tclass, cp);
282 if (ttype == type && tclass == class &&
283 ns_samename(tname, name) == 1)
284 return (1);
286 return (0);
288 libresolv_hidden_def (res_nameinquery)
290 /* int
291 * res_queriesmatch(buf1, eom1, buf2, eom2)
292 * is there a 1:1 mapping of (name,type,class)
293 * in (buf1,eom1) and (buf2,eom2)?
294 * returns:
295 * -1 : format error
296 * 0 : not a 1:1 mapping
297 * >0 : is a 1:1 mapping
298 * author:
299 * paul vixie, 29may94
302 res_queriesmatch(const u_char *buf1, const u_char *eom1,
303 const u_char *buf2, const u_char *eom2)
305 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
306 return (-1);
309 * Only header section present in replies to
310 * dynamic update packets.
312 if ((((HEADER *)buf1)->opcode == ns_o_update) &&
313 (((HEADER *)buf2)->opcode == ns_o_update))
314 return (1);
316 /* Note that we initially do not convert QDCOUNT to the host byte
317 order. We can compare it with the second buffer's QDCOUNT
318 value without doing this. */
319 int qdcount = ((HEADER*)buf1)->qdcount;
320 if (qdcount != ((HEADER*)buf2)->qdcount)
321 return (0);
323 qdcount = htons (qdcount);
324 const u_char *cp = buf1 + HFIXEDSZ;
326 while (qdcount-- > 0) {
327 char tname[MAXDNAME+1];
328 int n, ttype, tclass;
330 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
331 if (n < 0)
332 return (-1);
333 cp += n;
334 if (cp + 2 * INT16SZ > eom1)
335 return (-1);
336 NS_GET16(ttype, cp);
337 NS_GET16(tclass, cp);
338 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
339 return (0);
341 return (1);
343 libresolv_hidden_def (res_queriesmatch)
346 __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
347 const u_char *buf2, int buflen2,
348 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
349 int *nansp2, int *resplen2, int *ansp2_malloced)
351 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
353 if (statp->nscount == 0) {
354 __set_errno (ESRCH);
355 return (-1);
358 if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) {
359 __set_errno (EINVAL);
360 return (-1);
363 #ifdef USE_HOOKS
364 if (__glibc_unlikely (statp->qhook || statp->rhook)) {
365 if (anssiz < MAXPACKET && ansp) {
366 u_char *buf = malloc (MAXPACKET);
367 if (buf == NULL)
368 return (-1);
369 memcpy (buf, ans, HFIXEDSZ);
370 *ansp = buf;
371 ans = buf;
372 anssiz = MAXPACKET;
375 #endif
377 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
378 (stdout, ";; res_send()\n"), buf, buflen);
379 v_circuit = ((statp->options & RES_USEVC)
380 || buflen > PACKETSZ
381 || buflen2 > PACKETSZ);
382 gotsomewhere = 0;
383 terrno = ETIMEDOUT;
386 * If the ns_addr_list in the resolver context has changed, then
387 * invalidate our cached copy and the associated timing data.
389 if (EXT(statp).nscount != 0) {
390 int needclose = 0;
392 if (EXT(statp).nscount != statp->nscount)
393 needclose++;
394 else
395 for (ns = 0; ns < statp->nscount; ns++) {
396 if (statp->nsaddr_list[ns].sin_family != 0
397 && !sock_eq((struct sockaddr_in6 *)
398 &statp->nsaddr_list[ns],
399 EXT(statp).nsaddrs[ns]))
401 needclose++;
402 break;
405 if (needclose) {
406 __res_iclose(statp, false);
407 EXT(statp).nscount = 0;
412 * Maybe initialize our private copy of the ns_addr_list.
414 if (EXT(statp).nscount == 0) {
415 for (ns = 0; ns < statp->nscount; ns++) {
416 EXT(statp).nssocks[ns] = -1;
417 if (statp->nsaddr_list[ns].sin_family == 0)
418 continue;
419 if (EXT(statp).nsaddrs[ns] == NULL)
420 EXT(statp).nsaddrs[ns] =
421 malloc(sizeof (struct sockaddr_in6));
422 if (EXT(statp).nsaddrs[ns] != NULL)
423 memset (mempcpy(EXT(statp).nsaddrs[ns],
424 &statp->nsaddr_list[ns],
425 sizeof (struct sockaddr_in)),
426 '\0',
427 sizeof (struct sockaddr_in6)
428 - sizeof (struct sockaddr_in));
430 EXT(statp).nscount = statp->nscount;
434 * Some resolvers want to even out the load on their nameservers.
435 * Note that RES_BLAST overrides RES_ROTATE.
437 if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
438 (statp->options & RES_BLAST) == 0) {
439 struct sockaddr_in ina;
440 struct sockaddr_in6 *inp;
441 int lastns = statp->nscount - 1;
442 int fd;
444 inp = EXT(statp).nsaddrs[0];
445 ina = statp->nsaddr_list[0];
446 fd = EXT(statp).nssocks[0];
447 for (ns = 0; ns < lastns; ns++) {
448 EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1];
449 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
450 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
452 EXT(statp).nsaddrs[lastns] = inp;
453 statp->nsaddr_list[lastns] = ina;
454 EXT(statp).nssocks[lastns] = fd;
458 * Send request, RETRY times, or until successful.
460 for (try = 0; try < statp->retry; try++) {
461 for (ns = 0; ns < statp->nscount; ns++)
463 #ifdef DEBUG
464 char tmpbuf[40];
465 #endif
466 #if defined USE_HOOKS || defined DEBUG
467 struct sockaddr *nsap = get_nsaddr (statp, ns);
468 #endif
470 same_ns:
471 #ifdef USE_HOOKS
472 if (__glibc_unlikely (statp->qhook != NULL)) {
473 int done = 0, loops = 0;
475 do {
476 res_sendhookact act;
478 struct sockaddr_in *nsap4;
479 nsap4 = (struct sockaddr_in *) nsap;
480 act = (*statp->qhook)(&nsap4, &buf, &buflen,
481 ans, anssiz, &resplen);
482 nsap = (struct sockaddr_in6 *) nsap4;
483 switch (act) {
484 case res_goahead:
485 done = 1;
486 break;
487 case res_nextns:
488 __res_iclose(statp, false);
489 goto next_ns;
490 case res_done:
491 return (resplen);
492 case res_modified:
493 /* give the hook another try */
494 if (++loops < 42) /*doug adams*/
495 break;
496 /*FALLTHROUGH*/
497 case res_error:
498 /*FALLTHROUGH*/
499 default:
500 return (-1);
502 } while (!done);
504 #endif
506 Dprint(statp->options & RES_DEBUG,
507 (stdout, ";; Querying server (# %d) address = %s\n",
508 ns + 1, inet_ntop(nsap->sa_family,
509 (nsap->sa_family == AF_INET6
510 ? &((struct sockaddr_in6 *) nsap)->sin6_addr
511 : &((struct sockaddr_in *) nsap)->sin_addr),
512 tmpbuf, sizeof (tmpbuf))));
514 if (__glibc_unlikely (v_circuit)) {
515 /* Use VC; at most one attempt per server. */
516 try = statp->retry;
517 n = send_vc(statp, buf, buflen, buf2, buflen2,
518 &ans, &anssiz, &terrno,
519 ns, ansp, ansp2, nansp2, resplen2,
520 ansp2_malloced);
521 if (n < 0)
522 return (-1);
523 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
524 goto next_ns;
525 } else {
526 /* Use datagrams. */
527 n = send_dg(statp, buf, buflen, buf2, buflen2,
528 &ans, &anssiz, &terrno,
529 ns, &v_circuit, &gotsomewhere, ansp,
530 ansp2, nansp2, resplen2, ansp2_malloced);
531 if (n < 0)
532 return (-1);
533 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
534 goto next_ns;
535 if (v_circuit)
536 // XXX Check whether both requests failed or
537 // XXX whether one has been answered successfully
538 goto same_ns;
541 resplen = n;
543 Dprint((statp->options & RES_DEBUG) ||
544 ((statp->pfcode & RES_PRF_REPLY) &&
545 (statp->pfcode & RES_PRF_HEAD1)),
546 (stdout, ";; got answer:\n"));
548 DprintQ((statp->options & RES_DEBUG) ||
549 (statp->pfcode & RES_PRF_REPLY),
550 (stdout, "%s", ""),
551 ans, (resplen > anssiz) ? anssiz : resplen);
552 if (buf2 != NULL) {
553 DprintQ((statp->options & RES_DEBUG) ||
554 (statp->pfcode & RES_PRF_REPLY),
555 (stdout, "%s", ""),
556 *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
560 * If we have temporarily opened a virtual circuit,
561 * or if we haven't been asked to keep a socket open,
562 * close the socket.
564 if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
565 (statp->options & RES_STAYOPEN) == 0) {
566 __res_iclose(statp, false);
568 #ifdef USE_HOOKS
569 if (__glibc_unlikely (statp->rhook)) {
570 int done = 0, loops = 0;
572 do {
573 res_sendhookact act;
575 act = (*statp->rhook)((struct sockaddr_in *)
576 nsap, buf, buflen,
577 ans, anssiz, &resplen);
578 switch (act) {
579 case res_goahead:
580 case res_done:
581 done = 1;
582 break;
583 case res_nextns:
584 __res_iclose(statp, false);
585 goto next_ns;
586 case res_modified:
587 /* give the hook another try */
588 if (++loops < 42) /*doug adams*/
589 break;
590 /*FALLTHROUGH*/
591 case res_error:
592 /*FALLTHROUGH*/
593 default:
594 return (-1);
596 } while (!done);
599 #endif
600 return (resplen);
601 next_ns: ;
602 } /*foreach ns*/
603 } /*foreach retry*/
604 __res_iclose(statp, false);
605 if (!v_circuit) {
606 if (!gotsomewhere)
607 __set_errno (ECONNREFUSED); /* no nameservers found */
608 else
609 __set_errno (ETIMEDOUT); /* no answer obtained */
610 } else
611 __set_errno (terrno);
612 return (-1);
616 res_nsend(res_state statp,
617 const u_char *buf, int buflen, u_char *ans, int anssiz)
619 return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
620 NULL, NULL, NULL, NULL, NULL);
622 libresolv_hidden_def (res_nsend)
624 /* Private */
626 static struct sockaddr *
627 get_nsaddr (res_state statp, int n)
630 if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL)
631 /* EXT(statp).nsaddrs[n] holds an address that is larger than
632 struct sockaddr, and user code did not update
633 statp->nsaddr_list[n]. */
634 return (struct sockaddr *) EXT(statp).nsaddrs[n];
635 else
636 /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n]
637 has the same content as EXT(statp).nsaddrs[n]. */
638 return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
641 static int
642 send_vc(res_state statp,
643 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
644 u_char **ansp, int *anssizp,
645 int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
646 int *resplen2, int *ansp2_malloced)
648 const HEADER *hp = (HEADER *) buf;
649 const HEADER *hp2 = (HEADER *) buf2;
650 u_char *ans = *ansp;
651 int orig_anssizp = *anssizp;
652 // XXX REMOVE
653 // int anssiz = *anssizp;
654 HEADER *anhp = (HEADER *) ans;
655 struct sockaddr *nsap = get_nsaddr (statp, ns);
656 int truncating, connreset, n;
657 /* On some architectures compiler might emit a warning indicating
658 'resplen' may be used uninitialized. However if buf2 == NULL
659 then this code won't be executed; if buf2 != NULL, then first
660 time round the loop recvresp1 and recvresp2 will be 0 so this
661 code won't be executed but "thisresplenp = &resplen;" followed
662 by "*thisresplenp = rlen;" will be executed so that subsequent
663 times round the loop resplen has been initialized. So this is
664 a false-positive.
666 #if __GNUC_PREREQ (4, 7)
667 DIAG_PUSH_NEEDS_COMMENT;
668 DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
669 #endif
670 int resplen;
671 #if __GNUC_PREREQ (4, 7)
672 DIAG_POP_NEEDS_COMMENT;
673 #endif
674 struct iovec iov[4];
675 u_short len;
676 u_short len2;
677 u_char *cp;
679 if (resplen2 != NULL)
680 *resplen2 = 0;
681 connreset = 0;
682 same_ns:
683 truncating = 0;
685 /* Are we still talking to whom we want to talk to? */
686 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
687 struct sockaddr_in6 peer;
688 socklen_t size = sizeof peer;
690 if (getpeername(statp->_vcsock,
691 (struct sockaddr *)&peer, &size) < 0 ||
692 !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) {
693 __res_iclose(statp, false);
694 statp->_flags &= ~RES_F_VC;
698 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
699 if (statp->_vcsock >= 0)
700 __res_iclose(statp, false);
702 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
703 if (statp->_vcsock < 0) {
704 *terrno = errno;
705 Perror(statp, stderr, "socket(vc)", errno);
706 return (-1);
708 __set_errno (0);
709 if (connect(statp->_vcsock, nsap,
710 nsap->sa_family == AF_INET
711 ? sizeof (struct sockaddr_in)
712 : sizeof (struct sockaddr_in6)) < 0) {
713 *terrno = errno;
714 Aerror(statp, stderr, "connect/vc", errno, nsap);
715 __res_iclose(statp, false);
716 return (0);
718 statp->_flags |= RES_F_VC;
722 * Send length & message
724 len = htons ((u_short) buflen);
725 evConsIovec(&len, INT16SZ, &iov[0]);
726 evConsIovec((void*)buf, buflen, &iov[1]);
727 int niov = 2;
728 ssize_t explen = INT16SZ + buflen;
729 if (buf2 != NULL) {
730 len2 = htons ((u_short) buflen2);
731 evConsIovec(&len2, INT16SZ, &iov[2]);
732 evConsIovec((void*)buf2, buflen2, &iov[3]);
733 niov = 4;
734 explen += INT16SZ + buflen2;
736 if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
737 *terrno = errno;
738 Perror(statp, stderr, "write failed", errno);
739 __res_iclose(statp, false);
740 return (0);
743 * Receive length & response
745 int recvresp1 = 0;
746 int recvresp2 = buf2 == NULL;
747 uint16_t rlen16;
748 read_len:
749 cp = (u_char *)&rlen16;
750 len = sizeof(rlen16);
751 while ((n = TEMP_FAILURE_RETRY (read(statp->_vcsock, cp,
752 (int)len))) > 0) {
753 cp += n;
754 if ((len -= n) <= 0)
755 break;
757 if (n <= 0) {
758 *terrno = errno;
759 Perror(statp, stderr, "read failed", errno);
760 __res_iclose(statp, false);
762 * A long running process might get its TCP
763 * connection reset if the remote server was
764 * restarted. Requery the server instead of
765 * trying a new one. When there is only one
766 * server, this means that a query might work
767 * instead of failing. We only allow one reset
768 * per query to prevent looping.
770 if (*terrno == ECONNRESET && !connreset) {
771 connreset = 1;
772 goto same_ns;
774 return (0);
776 int rlen = ntohs (rlen16);
778 int *thisanssizp;
779 u_char **thisansp;
780 int *thisresplenp;
781 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
782 thisanssizp = anssizp;
783 thisansp = anscp ?: ansp;
784 assert (anscp != NULL || ansp2 == NULL);
785 thisresplenp = &resplen;
786 } else {
787 if (*anssizp != MAXPACKET) {
788 /* No buffer allocated for the first
789 reply. We can try to use the rest
790 of the user-provided buffer. */
791 #if __GNUC_PREREQ (4, 7)
792 DIAG_PUSH_NEEDS_COMMENT;
793 DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
794 #endif
795 #if _STRING_ARCH_unaligned
796 *anssizp2 = orig_anssizp - resplen;
797 *ansp2 = *ansp + resplen;
798 #else
799 int aligned_resplen
800 = ((resplen + __alignof__ (HEADER) - 1)
801 & ~(__alignof__ (HEADER) - 1));
802 *anssizp2 = orig_anssizp - aligned_resplen;
803 *ansp2 = *ansp + aligned_resplen;
804 #endif
805 #if __GNUC_PREREQ (4, 7)
806 DIAG_POP_NEEDS_COMMENT;
807 #endif
808 } else {
809 /* The first reply did not fit into the
810 user-provided buffer. Maybe the second
811 answer will. */
812 *anssizp2 = orig_anssizp;
813 *ansp2 = *ansp;
816 thisanssizp = anssizp2;
817 thisansp = ansp2;
818 thisresplenp = resplen2;
820 anhp = (HEADER *) *thisansp;
822 *thisresplenp = rlen;
823 if (rlen > *thisanssizp) {
824 /* Yes, we test ANSCP here. If we have two buffers
825 both will be allocatable. */
826 if (__glibc_likely (anscp != NULL)) {
827 u_char *newp = malloc (MAXPACKET);
828 if (newp == NULL) {
829 *terrno = ENOMEM;
830 __res_iclose(statp, false);
831 return (0);
833 *thisanssizp = MAXPACKET;
834 *thisansp = newp;
835 if (thisansp == ansp2)
836 *ansp2_malloced = 1;
837 anhp = (HEADER *) newp;
838 len = rlen;
839 } else {
840 Dprint(statp->options & RES_DEBUG,
841 (stdout, ";; response truncated\n")
843 truncating = 1;
844 len = *thisanssizp;
846 } else
847 len = rlen;
849 if (__glibc_unlikely (len < HFIXEDSZ)) {
851 * Undersized message.
853 Dprint(statp->options & RES_DEBUG,
854 (stdout, ";; undersized: %d\n", len));
855 *terrno = EMSGSIZE;
856 __res_iclose(statp, false);
857 return (0);
860 cp = *thisansp;
861 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
862 cp += n;
863 len -= n;
865 if (__glibc_unlikely (n <= 0)) {
866 *terrno = errno;
867 Perror(statp, stderr, "read(vc)", errno);
868 __res_iclose(statp, false);
869 return (0);
871 if (__glibc_unlikely (truncating)) {
873 * Flush rest of answer so connection stays in synch.
875 anhp->tc = 1;
876 len = rlen - *thisanssizp;
877 while (len != 0) {
878 char junk[PACKETSZ];
880 n = read(statp->_vcsock, junk,
881 (len > sizeof junk) ? sizeof junk : len);
882 if (n > 0)
883 len -= n;
884 else
885 break;
889 * If the calling application has bailed out of
890 * a previous call and failed to arrange to have
891 * the circuit closed or the server has got
892 * itself confused, then drop the packet and
893 * wait for the correct one.
895 if ((recvresp1 || hp->id != anhp->id)
896 && (recvresp2 || hp2->id != anhp->id)) {
897 DprintQ((statp->options & RES_DEBUG) ||
898 (statp->pfcode & RES_PRF_REPLY),
899 (stdout, ";; old answer (unexpected):\n"),
900 *thisansp,
901 (rlen > *thisanssizp) ? *thisanssizp: rlen);
902 goto read_len;
905 /* Mark which reply we received. */
906 if (recvresp1 == 0 && hp->id == anhp->id)
907 recvresp1 = 1;
908 else
909 recvresp2 = 1;
910 /* Repeat waiting if we have a second answer to arrive. */
911 if ((recvresp1 & recvresp2) == 0)
912 goto read_len;
915 * All is well, or the error is fatal. Signal that the
916 * next nameserver ought not be tried.
918 return resplen;
921 static int
922 reopen (res_state statp, int *terrno, int ns)
924 if (EXT(statp).nssocks[ns] == -1) {
925 struct sockaddr *nsap = get_nsaddr (statp, ns);
926 socklen_t slen;
928 /* only try IPv6 if IPv6 NS and if not failed before */
929 if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
930 if (__glibc_likely (__have_o_nonblock >= 0)) {
931 EXT(statp).nssocks[ns] =
932 socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK,
934 #ifndef __ASSUME_SOCK_CLOEXEC
935 if (__have_o_nonblock == 0)
936 __have_o_nonblock
937 = (EXT(statp).nssocks[ns] == -1
938 && errno == EINVAL ? -1 : 1);
939 #endif
941 if (__glibc_unlikely (__have_o_nonblock < 0))
942 EXT(statp).nssocks[ns] =
943 socket(PF_INET6, SOCK_DGRAM, 0);
944 if (EXT(statp).nssocks[ns] < 0)
945 statp->ipv6_unavail = errno == EAFNOSUPPORT;
946 slen = sizeof (struct sockaddr_in6);
947 } else if (nsap->sa_family == AF_INET) {
948 if (__glibc_likely (__have_o_nonblock >= 0)) {
949 EXT(statp).nssocks[ns]
950 = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK,
952 #ifndef __ASSUME_SOCK_CLOEXEC
953 if (__have_o_nonblock == 0)
954 __have_o_nonblock
955 = (EXT(statp).nssocks[ns] == -1
956 && errno == EINVAL ? -1 : 1);
957 #endif
959 if (__glibc_unlikely (__have_o_nonblock < 0))
960 EXT(statp).nssocks[ns]
961 = socket(PF_INET, SOCK_DGRAM, 0);
962 slen = sizeof (struct sockaddr_in);
964 if (EXT(statp).nssocks[ns] < 0) {
965 *terrno = errno;
966 Perror(statp, stderr, "socket(dg)", errno);
967 return (-1);
971 * On a 4.3BSD+ machine (client and server,
972 * actually), sending to a nameserver datagram
973 * port with no nameserver will cause an
974 * ICMP port unreachable message to be returned.
975 * If our datagram socket is "connected" to the
976 * server, we get an ECONNREFUSED error on the next
977 * socket operation, and select returns if the
978 * error message is received. We can thus detect
979 * the absence of a nameserver without timing out.
981 if (connect(EXT(statp).nssocks[ns], nsap, slen) < 0) {
982 Aerror(statp, stderr, "connect(dg)", errno, nsap);
983 __res_iclose(statp, false);
984 return (0);
986 if (__glibc_unlikely (__have_o_nonblock < 0)) {
987 /* Make socket non-blocking. */
988 int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL);
989 if (fl != -1)
990 __fcntl (EXT(statp).nssocks[ns], F_SETFL,
991 fl | O_NONBLOCK);
992 Dprint(statp->options & RES_DEBUG,
993 (stdout, ";; new DG socket\n"))
997 return 1;
1000 static int
1001 send_dg(res_state statp,
1002 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
1003 u_char **ansp, int *anssizp,
1004 int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
1005 u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
1007 const HEADER *hp = (HEADER *) buf;
1008 const HEADER *hp2 = (HEADER *) buf2;
1009 u_char *ans = *ansp;
1010 int orig_anssizp = *anssizp;
1011 struct timespec now, timeout, finish;
1012 struct pollfd pfd[1];
1013 int ptimeout;
1014 struct sockaddr_in6 from;
1015 int resplen = 0;
1016 int n;
1019 * Compute time for the total operation.
1021 int seconds = (statp->retrans << ns);
1022 if (ns > 0)
1023 seconds /= statp->nscount;
1024 if (seconds <= 0)
1025 seconds = 1;
1026 bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
1027 bool single_request = (((statp->options & RES_SNGLKUP) != 0)
1028 | single_request_reopen);
1029 int save_gotsomewhere = *gotsomewhere;
1031 int retval;
1032 retry_reopen:
1033 retval = reopen (statp, terrno, ns);
1034 if (retval <= 0)
1035 return retval;
1036 retry:
1037 evNowTime(&now);
1038 evConsTime(&timeout, seconds, 0);
1039 evAddTime(&finish, &now, &timeout);
1040 int need_recompute = 0;
1041 int nwritten = 0;
1042 int recvresp1 = 0;
1043 int recvresp2 = buf2 == NULL;
1044 pfd[0].fd = EXT(statp).nssocks[ns];
1045 pfd[0].events = POLLOUT;
1046 if (resplen2 != NULL)
1047 *resplen2 = 0;
1048 wait:
1049 if (need_recompute) {
1050 recompute_resend:
1051 evNowTime(&now);
1052 if (evCmpTime(finish, now) <= 0) {
1053 poll_err_out:
1054 Perror(statp, stderr, "poll", errno);
1055 err_out:
1056 __res_iclose(statp, false);
1057 return (0);
1059 evSubTime(&timeout, &finish, &now);
1060 need_recompute = 0;
1062 /* Convert struct timespec in milliseconds. */
1063 ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
1065 n = 0;
1066 if (nwritten == 0)
1067 n = __poll (pfd, 1, 0);
1068 if (__glibc_unlikely (n == 0)) {
1069 n = __poll (pfd, 1, ptimeout);
1070 need_recompute = 1;
1072 if (n == 0) {
1073 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1074 if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
1076 /* There are quite a few broken name servers out
1077 there which don't handle two outstanding
1078 requests from the same source. There are also
1079 broken firewall settings. If we time out after
1080 having received one answer switch to the mode
1081 where we send the second request only once we
1082 have received the first answer. */
1083 if (!single_request)
1085 statp->options |= RES_SNGLKUP;
1086 single_request = true;
1087 *gotsomewhere = save_gotsomewhere;
1088 goto retry;
1090 else if (!single_request_reopen)
1092 statp->options |= RES_SNGLKUPREOP;
1093 single_request_reopen = true;
1094 *gotsomewhere = save_gotsomewhere;
1095 __res_iclose (statp, false);
1096 goto retry_reopen;
1099 *resplen2 = 1;
1100 return resplen;
1103 *gotsomewhere = 1;
1104 return (0);
1106 if (n < 0) {
1107 if (errno == EINTR)
1108 goto recompute_resend;
1110 goto poll_err_out;
1112 __set_errno (0);
1113 if (pfd[0].revents & POLLOUT) {
1114 #ifndef __ASSUME_SENDMMSG
1115 static int have_sendmmsg;
1116 #else
1117 # define have_sendmmsg 1
1118 #endif
1119 if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL
1120 && !single_request)
1122 struct iovec iov[2];
1123 struct mmsghdr reqs[2];
1124 reqs[0].msg_hdr.msg_name = NULL;
1125 reqs[0].msg_hdr.msg_namelen = 0;
1126 reqs[0].msg_hdr.msg_iov = &iov[0];
1127 reqs[0].msg_hdr.msg_iovlen = 1;
1128 iov[0].iov_base = (void *) buf;
1129 iov[0].iov_len = buflen;
1130 reqs[0].msg_hdr.msg_control = NULL;
1131 reqs[0].msg_hdr.msg_controllen = 0;
1133 reqs[1].msg_hdr.msg_name = NULL;
1134 reqs[1].msg_hdr.msg_namelen = 0;
1135 reqs[1].msg_hdr.msg_iov = &iov[1];
1136 reqs[1].msg_hdr.msg_iovlen = 1;
1137 iov[1].iov_base = (void *) buf2;
1138 iov[1].iov_len = buflen2;
1139 reqs[1].msg_hdr.msg_control = NULL;
1140 reqs[1].msg_hdr.msg_controllen = 0;
1142 int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL);
1143 if (__glibc_likely (ndg == 2))
1145 if (reqs[0].msg_len != buflen
1146 || reqs[1].msg_len != buflen2)
1147 goto fail_sendmmsg;
1149 pfd[0].events = POLLIN;
1150 nwritten += 2;
1152 else if (ndg == 1 && reqs[0].msg_len == buflen)
1153 goto just_one;
1154 else if (ndg < 0 && (errno == EINTR || errno == EAGAIN))
1155 goto recompute_resend;
1156 else
1158 #ifndef __ASSUME_SENDMMSG
1159 if (__glibc_unlikely (have_sendmmsg == 0))
1161 if (ndg < 0 && errno == ENOSYS)
1163 have_sendmmsg = -1;
1164 goto try_send;
1166 have_sendmmsg = 1;
1168 #endif
1170 fail_sendmmsg:
1171 Perror(statp, stderr, "sendmmsg", errno);
1172 goto err_out;
1175 else
1177 ssize_t sr;
1178 #ifndef __ASSUME_SENDMMSG
1179 try_send:
1180 #endif
1181 if (nwritten != 0)
1182 sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
1183 else
1184 sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
1186 if (sr != (nwritten != 0 ? buflen2 : buflen)) {
1187 if (errno == EINTR || errno == EAGAIN)
1188 goto recompute_resend;
1189 Perror(statp, stderr, "send", errno);
1190 goto err_out;
1192 just_one:
1193 if (nwritten != 0 || buf2 == NULL || single_request)
1194 pfd[0].events = POLLIN;
1195 else
1196 pfd[0].events = POLLIN | POLLOUT;
1197 ++nwritten;
1199 goto wait;
1200 } else if (pfd[0].revents & POLLIN) {
1201 int *thisanssizp;
1202 u_char **thisansp;
1203 int *thisresplenp;
1205 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1206 thisanssizp = anssizp;
1207 thisansp = anscp ?: ansp;
1208 assert (anscp != NULL || ansp2 == NULL);
1209 thisresplenp = &resplen;
1210 } else {
1211 if (*anssizp != MAXPACKET) {
1212 /* No buffer allocated for the first
1213 reply. We can try to use the rest
1214 of the user-provided buffer. */
1215 #if _STRING_ARCH_unaligned
1216 *anssizp2 = orig_anssizp - resplen;
1217 *ansp2 = *ansp + resplen;
1218 #else
1219 int aligned_resplen
1220 = ((resplen + __alignof__ (HEADER) - 1)
1221 & ~(__alignof__ (HEADER) - 1));
1222 *anssizp2 = orig_anssizp - aligned_resplen;
1223 *ansp2 = *ansp + aligned_resplen;
1224 #endif
1225 } else {
1226 /* The first reply did not fit into the
1227 user-provided buffer. Maybe the second
1228 answer will. */
1229 *anssizp2 = orig_anssizp;
1230 *ansp2 = *ansp;
1233 thisanssizp = anssizp2;
1234 thisansp = ansp2;
1235 thisresplenp = resplen2;
1238 if (*thisanssizp < MAXPACKET
1239 /* Yes, we test ANSCP here. If we have two buffers
1240 both will be allocatable. */
1241 && anscp
1242 #ifdef FIONREAD
1243 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
1244 || *thisanssizp < *thisresplenp)
1245 #endif
1247 u_char *newp = malloc (MAXPACKET);
1248 if (newp != NULL) {
1249 *anssizp = MAXPACKET;
1250 *thisansp = ans = newp;
1251 if (thisansp == ansp2)
1252 *ansp2_malloced = 1;
1255 HEADER *anhp = (HEADER *) *thisansp;
1256 socklen_t fromlen = sizeof(struct sockaddr_in6);
1257 assert (sizeof(from) <= fromlen);
1258 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1259 *thisanssizp, 0,
1260 (struct sockaddr *)&from, &fromlen);
1261 if (__glibc_unlikely (*thisresplenp <= 0)) {
1262 if (errno == EINTR || errno == EAGAIN) {
1263 need_recompute = 1;
1264 goto wait;
1266 Perror(statp, stderr, "recvfrom", errno);
1267 goto err_out;
1269 *gotsomewhere = 1;
1270 if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
1272 * Undersized message.
1274 Dprint(statp->options & RES_DEBUG,
1275 (stdout, ";; undersized: %d\n",
1276 *thisresplenp));
1277 *terrno = EMSGSIZE;
1278 goto err_out;
1280 if ((recvresp1 || hp->id != anhp->id)
1281 && (recvresp2 || hp2->id != anhp->id)) {
1283 * response from old query, ignore it.
1284 * XXX - potential security hazard could
1285 * be detected here.
1287 DprintQ((statp->options & RES_DEBUG) ||
1288 (statp->pfcode & RES_PRF_REPLY),
1289 (stdout, ";; old answer:\n"),
1290 *thisansp,
1291 (*thisresplenp > *thisanssizp)
1292 ? *thisanssizp : *thisresplenp);
1293 goto wait;
1295 if (!(statp->options & RES_INSECURE1) &&
1296 !res_ourserver_p(statp, &from)) {
1298 * response from wrong server? ignore it.
1299 * XXX - potential security hazard could
1300 * be detected here.
1302 DprintQ((statp->options & RES_DEBUG) ||
1303 (statp->pfcode & RES_PRF_REPLY),
1304 (stdout, ";; not our server:\n"),
1305 *thisansp,
1306 (*thisresplenp > *thisanssizp)
1307 ? *thisanssizp : *thisresplenp);
1308 goto wait;
1310 #ifdef RES_USE_EDNS0
1311 if (anhp->rcode == FORMERR
1312 && (statp->options & RES_USE_EDNS0) != 0U) {
1314 * Do not retry if the server does not understand
1315 * EDNS0. The case has to be captured here, as
1316 * FORMERR packet do not carry query section, hence
1317 * res_queriesmatch() returns 0.
1319 DprintQ(statp->options & RES_DEBUG,
1320 (stdout,
1321 "server rejected query with EDNS0:\n"),
1322 *thisansp,
1323 (*thisresplenp > *thisanssizp)
1324 ? *thisanssizp : *thisresplenp);
1325 /* record the error */
1326 statp->_flags |= RES_F_EDNS0ERR;
1327 goto err_out;
1329 #endif
1330 if (!(statp->options & RES_INSECURE2)
1331 && (recvresp1 || !res_queriesmatch(buf, buf + buflen,
1332 *thisansp,
1333 *thisansp
1334 + *thisanssizp))
1335 && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
1336 *thisansp,
1337 *thisansp
1338 + *thisanssizp))) {
1340 * response contains wrong query? ignore it.
1341 * XXX - potential security hazard could
1342 * be detected here.
1344 DprintQ((statp->options & RES_DEBUG) ||
1345 (statp->pfcode & RES_PRF_REPLY),
1346 (stdout, ";; wrong query name:\n"),
1347 *thisansp,
1348 (*thisresplenp > *thisanssizp)
1349 ? *thisanssizp : *thisresplenp);
1350 goto wait;
1352 if (anhp->rcode == SERVFAIL ||
1353 anhp->rcode == NOTIMP ||
1354 anhp->rcode == REFUSED) {
1355 DprintQ(statp->options & RES_DEBUG,
1356 (stdout, "server rejected query:\n"),
1357 *thisansp,
1358 (*thisresplenp > *thisanssizp)
1359 ? *thisanssizp : *thisresplenp);
1361 next_ns:
1362 if (recvresp1 || (buf2 != NULL && recvresp2)) {
1363 *resplen2 = 0;
1364 return resplen;
1366 if (buf2 != NULL)
1368 /* No data from the first reply. */
1369 resplen = 0;
1370 /* We are waiting for a possible second reply. */
1371 if (hp->id == anhp->id)
1372 recvresp1 = 1;
1373 else
1374 recvresp2 = 1;
1376 goto wait;
1379 __res_iclose(statp, false);
1380 /* don't retry if called from dig */
1381 if (!statp->pfcode)
1382 return (0);
1384 if (anhp->rcode == NOERROR && anhp->ancount == 0
1385 && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
1386 DprintQ(statp->options & RES_DEBUG,
1387 (stdout, "referred query:\n"),
1388 *thisansp,
1389 (*thisresplenp > *thisanssizp)
1390 ? *thisanssizp : *thisresplenp);
1391 goto next_ns;
1393 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1395 * To get the rest of answer,
1396 * use TCP with same server.
1398 Dprint(statp->options & RES_DEBUG,
1399 (stdout, ";; truncated answer\n"));
1400 *v_circuit = 1;
1401 __res_iclose(statp, false);
1402 // XXX if we have received one reply we could
1403 // XXX use it and not repeat it over TCP...
1404 return (1);
1406 /* Mark which reply we received. */
1407 if (recvresp1 == 0 && hp->id == anhp->id)
1408 recvresp1 = 1;
1409 else
1410 recvresp2 = 1;
1411 /* Repeat waiting if we have a second answer to arrive. */
1412 if ((recvresp1 & recvresp2) == 0) {
1413 if (single_request) {
1414 pfd[0].events = POLLOUT;
1415 if (single_request_reopen) {
1416 __res_iclose (statp, false);
1417 retval = reopen (statp, terrno, ns);
1418 if (retval <= 0)
1419 return retval;
1420 pfd[0].fd = EXT(statp).nssocks[ns];
1423 goto wait;
1426 * All is well, or the error is fatal. Signal that the
1427 * next nameserver ought not be tried.
1429 return (resplen);
1430 } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
1431 /* Something went wrong. We can stop trying. */
1432 goto err_out;
1434 else {
1435 /* poll should not have returned > 0 in this case. */
1436 abort ();
1440 #ifdef DEBUG
1441 static void
1442 Aerror(const res_state statp, FILE *file, const char *string, int error,
1443 const struct sockaddr *address)
1445 int save = errno;
1447 if ((statp->options & RES_DEBUG) != 0) {
1448 char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
1450 fprintf(file, "res_send: %s ([%s].%u): %s\n",
1451 string,
1452 (address->sa_family == AF_INET
1453 ? inet_ntop(address->sa_family,
1454 &((const struct sockaddr_in *) address)->sin_addr,
1455 tmp, sizeof tmp)
1456 : inet_ntop(address->sa_family,
1457 &((const struct sockaddr_in6 *) address)->sin6_addr,
1458 tmp, sizeof tmp)),
1459 (address->sa_family == AF_INET
1460 ? ntohs(((struct sockaddr_in *) address)->sin_port)
1461 : address->sa_family == AF_INET6
1462 ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
1463 : 0),
1464 strerror(error));
1466 __set_errno (save);
1469 static void
1470 Perror(const res_state statp, FILE *file, const char *string, int error) {
1471 int save = errno;
1473 if ((statp->options & RES_DEBUG) != 0)
1474 fprintf(file, "res_send: %s: %s\n",
1475 string, strerror(error));
1476 __set_errno (save);
1478 #endif
1480 static int
1481 sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
1482 if (a1->sin6_family == a2->sin6_family) {
1483 if (a1->sin6_family == AF_INET)
1484 return ((((struct sockaddr_in *)a1)->sin_port ==
1485 ((struct sockaddr_in *)a2)->sin_port) &&
1486 (((struct sockaddr_in *)a1)->sin_addr.s_addr ==
1487 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1488 else
1489 return ((a1->sin6_port == a2->sin6_port) &&
1490 !memcmp(&a1->sin6_addr, &a2->sin6_addr,
1491 sizeof (struct in6_addr)));
1493 if (a1->sin6_family == AF_INET) {
1494 struct sockaddr_in6 *sap = a1;
1495 a1 = a2;
1496 a2 = sap;
1497 } /* assumes that AF_INET and AF_INET6 are the only possibilities */
1498 return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) &&
1499 IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) &&
1500 (a1->sin6_addr.s6_addr32[3] ==
1501 ((struct sockaddr_in *)a2)->sin_addr.s_addr));