Fix MIPS _ABIO64 -Werror=undef build.
[glibc.git] / resolv / res_send.c
blobc35fb66bda166ca02d92bd60ed224eb62782f1f9
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 int send_vc(res_state, const u_char *, int,
188 const u_char *, int,
189 u_char **, int *, int *, int, u_char **,
190 u_char **, int *, int *, int *);
191 static int send_dg(res_state, const u_char *, int,
192 const u_char *, int,
193 u_char **, int *, int *, int,
194 int *, int *, u_char **,
195 u_char **, int *, int *, int *);
196 #ifdef DEBUG
197 static void Aerror(const res_state, FILE *, const char *, int,
198 const struct sockaddr *);
199 static void Perror(const res_state, FILE *, const char *, int);
200 #endif
201 static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
203 /* Public. */
205 /* int
206 * res_isourserver(ina)
207 * looks up "ina" in _res.ns_addr_list[]
208 * returns:
209 * 0 : not found
210 * >0 : found
211 * author:
212 * paul vixie, 29may94
215 res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
217 int ns;
219 if (inp->sin6_family == AF_INET) {
220 struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
221 in_port_t port = in4p->sin_port;
222 in_addr_t addr = in4p->sin_addr.s_addr;
224 for (ns = 0; ns < MAXNS; ns++) {
225 const struct sockaddr_in *srv =
226 (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
228 if ((srv != NULL) && (srv->sin_family == AF_INET) &&
229 (srv->sin_port == port) &&
230 (srv->sin_addr.s_addr == INADDR_ANY ||
231 srv->sin_addr.s_addr == addr))
232 return (1);
234 } else if (inp->sin6_family == AF_INET6) {
235 for (ns = 0; ns < MAXNS; ns++) {
236 const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
237 if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
238 (srv->sin6_port == inp->sin6_port) &&
239 !(memcmp(&srv->sin6_addr, &in6addr_any,
240 sizeof (struct in6_addr)) &&
241 memcmp(&srv->sin6_addr, &inp->sin6_addr,
242 sizeof (struct in6_addr))))
243 return (1);
246 return (0);
249 /* int
250 * res_nameinquery(name, type, class, buf, eom)
251 * look for (name,type,class) in the query section of packet (buf,eom)
252 * requires:
253 * buf + HFIXEDSZ <= eom
254 * returns:
255 * -1 : format error
256 * 0 : not found
257 * >0 : found
258 * author:
259 * paul vixie, 29may94
262 res_nameinquery(const char *name, int type, int class,
263 const u_char *buf, const u_char *eom)
265 const u_char *cp = buf + HFIXEDSZ;
266 int qdcount = ntohs(((HEADER*)buf)->qdcount);
268 while (qdcount-- > 0) {
269 char tname[MAXDNAME+1];
270 int n, ttype, tclass;
272 n = dn_expand(buf, eom, cp, tname, sizeof tname);
273 if (n < 0)
274 return (-1);
275 cp += n;
276 if (cp + 2 * INT16SZ > eom)
277 return (-1);
278 NS_GET16(ttype, cp);
279 NS_GET16(tclass, cp);
280 if (ttype == type && tclass == class &&
281 ns_samename(tname, name) == 1)
282 return (1);
284 return (0);
286 libresolv_hidden_def (res_nameinquery)
288 /* int
289 * res_queriesmatch(buf1, eom1, buf2, eom2)
290 * is there a 1:1 mapping of (name,type,class)
291 * in (buf1,eom1) and (buf2,eom2)?
292 * returns:
293 * -1 : format error
294 * 0 : not a 1:1 mapping
295 * >0 : is a 1:1 mapping
296 * author:
297 * paul vixie, 29may94
300 res_queriesmatch(const u_char *buf1, const u_char *eom1,
301 const u_char *buf2, const u_char *eom2)
303 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
304 return (-1);
307 * Only header section present in replies to
308 * dynamic update packets.
310 if ((((HEADER *)buf1)->opcode == ns_o_update) &&
311 (((HEADER *)buf2)->opcode == ns_o_update))
312 return (1);
314 /* Note that we initially do not convert QDCOUNT to the host byte
315 order. We can compare it with the second buffer's QDCOUNT
316 value without doing this. */
317 int qdcount = ((HEADER*)buf1)->qdcount;
318 if (qdcount != ((HEADER*)buf2)->qdcount)
319 return (0);
321 qdcount = htons (qdcount);
322 const u_char *cp = buf1 + HFIXEDSZ;
324 while (qdcount-- > 0) {
325 char tname[MAXDNAME+1];
326 int n, ttype, tclass;
328 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
329 if (n < 0)
330 return (-1);
331 cp += n;
332 if (cp + 2 * INT16SZ > eom1)
333 return (-1);
334 NS_GET16(ttype, cp);
335 NS_GET16(tclass, cp);
336 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
337 return (0);
339 return (1);
341 libresolv_hidden_def (res_queriesmatch)
344 __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
345 const u_char *buf2, int buflen2,
346 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
347 int *nansp2, int *resplen2, int *ansp2_malloced)
349 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
351 if (statp->nscount == 0) {
352 __set_errno (ESRCH);
353 return (-1);
356 if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) {
357 __set_errno (EINVAL);
358 return (-1);
361 #ifdef USE_HOOKS
362 if (__glibc_unlikely (statp->qhook || statp->rhook)) {
363 if (anssiz < MAXPACKET && ansp) {
364 u_char *buf = malloc (MAXPACKET);
365 if (buf == NULL)
366 return (-1);
367 memcpy (buf, ans, HFIXEDSZ);
368 *ansp = buf;
369 ans = buf;
370 anssiz = MAXPACKET;
373 #endif
375 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
376 (stdout, ";; res_send()\n"), buf, buflen);
377 v_circuit = ((statp->options & RES_USEVC)
378 || buflen > PACKETSZ
379 || buflen2 > PACKETSZ);
380 gotsomewhere = 0;
381 terrno = ETIMEDOUT;
384 * If the ns_addr_list in the resolver context has changed, then
385 * invalidate our cached copy and the associated timing data.
387 if (EXT(statp).nsinit) {
388 int needclose = 0;
390 if (EXT(statp).nscount != statp->nscount)
391 needclose++;
392 else
393 for (ns = 0; ns < MAXNS; ns++) {
394 unsigned int map = EXT(statp).nsmap[ns];
395 if (map < MAXNS
396 && !sock_eq((struct sockaddr_in6 *)
397 &statp->nsaddr_list[map],
398 EXT(statp).nsaddrs[ns]))
400 needclose++;
401 break;
404 if (needclose)
405 __res_iclose(statp, false);
409 * Maybe initialize our private copy of the ns_addr_list.
411 if (EXT(statp).nsinit == 0) {
412 unsigned char map[MAXNS];
414 memset (map, MAXNS, sizeof (map));
415 for (n = 0; n < MAXNS; n++) {
416 ns = EXT(statp).nsmap[n];
417 if (ns < statp->nscount)
418 map[ns] = n;
419 else if (ns < MAXNS) {
420 free(EXT(statp).nsaddrs[n]);
421 EXT(statp).nsaddrs[n] = NULL;
422 EXT(statp).nsmap[n] = MAXNS;
425 n = statp->nscount;
426 if (statp->nscount > EXT(statp).nscount)
427 for (n = EXT(statp).nscount, ns = 0;
428 n < statp->nscount; n++) {
429 while (ns < MAXNS
430 && EXT(statp).nsmap[ns] != MAXNS)
431 ns++;
432 if (ns == MAXNS)
433 break;
434 /* NS never exceeds MAXNS, but gcc 4.9 somehow
435 does not see this. */
436 DIAG_PUSH_NEEDS_COMMENT;
437 DIAG_IGNORE_NEEDS_COMMENT (4.9,
438 "-Warray-bounds");
439 EXT(statp).nsmap[ns] = n;
440 DIAG_POP_NEEDS_COMMENT;
441 map[n] = ns++;
443 EXT(statp).nscount = n;
444 for (ns = 0; ns < EXT(statp).nscount; ns++) {
445 n = map[ns];
446 if (EXT(statp).nsaddrs[n] == NULL)
447 EXT(statp).nsaddrs[n] =
448 malloc(sizeof (struct sockaddr_in6));
449 if (EXT(statp).nsaddrs[n] != NULL) {
450 memset (mempcpy(EXT(statp).nsaddrs[n],
451 &statp->nsaddr_list[ns],
452 sizeof (struct sockaddr_in)),
453 '\0',
454 sizeof (struct sockaddr_in6)
455 - sizeof (struct sockaddr_in));
456 EXT(statp).nssocks[n] = -1;
457 n++;
460 EXT(statp).nsinit = 1;
464 * Some resolvers want to even out the load on their nameservers.
465 * Note that RES_BLAST overrides RES_ROTATE.
467 if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
468 (statp->options & RES_BLAST) == 0) {
469 struct sockaddr_in6 *ina;
470 unsigned int map;
472 n = 0;
473 while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
474 n++;
475 if (n < MAXNS) {
476 ina = EXT(statp).nsaddrs[n];
477 map = EXT(statp).nsmap[n];
478 for (;;) {
479 ns = n + 1;
480 while (ns < MAXNS
481 && EXT(statp).nsmap[ns] == MAXNS)
482 ns++;
483 if (ns == MAXNS)
484 break;
485 EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
486 EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
487 n = ns;
489 EXT(statp).nsaddrs[n] = ina;
490 EXT(statp).nsmap[n] = map;
495 * Send request, RETRY times, or until successful.
497 for (try = 0; try < statp->retry; try++) {
498 for (ns = 0; ns < MAXNS; ns++)
500 #ifdef DEBUG
501 char tmpbuf[40];
502 #endif
503 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
505 if (nsap == NULL)
506 goto next_ns;
507 same_ns:
508 #ifdef USE_HOOKS
509 if (__glibc_unlikely (statp->qhook != NULL)) {
510 int done = 0, loops = 0;
512 do {
513 res_sendhookact act;
515 struct sockaddr_in *nsap4;
516 nsap4 = (struct sockaddr_in *) nsap;
517 act = (*statp->qhook)(&nsap4, &buf, &buflen,
518 ans, anssiz, &resplen);
519 nsap = (struct sockaddr_in6 *) nsap4;
520 switch (act) {
521 case res_goahead:
522 done = 1;
523 break;
524 case res_nextns:
525 __res_iclose(statp, false);
526 goto next_ns;
527 case res_done:
528 return (resplen);
529 case res_modified:
530 /* give the hook another try */
531 if (++loops < 42) /*doug adams*/
532 break;
533 /*FALLTHROUGH*/
534 case res_error:
535 /*FALLTHROUGH*/
536 default:
537 return (-1);
539 } while (!done);
541 #endif
543 Dprint(statp->options & RES_DEBUG,
544 (stdout, ";; Querying server (# %d) address = %s\n",
545 ns + 1, inet_ntop(nsap->sin6_family,
546 (nsap->sin6_family == AF_INET6
547 ? &nsap->sin6_addr
548 : &((struct sockaddr_in *) nsap)->sin_addr),
549 tmpbuf, sizeof (tmpbuf))));
551 if (__glibc_unlikely (v_circuit)) {
552 /* Use VC; at most one attempt per server. */
553 try = statp->retry;
554 n = send_vc(statp, buf, buflen, buf2, buflen2,
555 &ans, &anssiz, &terrno,
556 ns, ansp, ansp2, nansp2, resplen2,
557 ansp2_malloced);
558 if (n < 0)
559 return (-1);
560 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
561 goto next_ns;
562 } else {
563 /* Use datagrams. */
564 n = send_dg(statp, buf, buflen, buf2, buflen2,
565 &ans, &anssiz, &terrno,
566 ns, &v_circuit, &gotsomewhere, ansp,
567 ansp2, nansp2, resplen2, ansp2_malloced);
568 if (n < 0)
569 return (-1);
570 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
571 goto next_ns;
572 if (v_circuit)
573 // XXX Check whether both requests failed or
574 // XXX whether one has been answered successfully
575 goto same_ns;
578 resplen = n;
580 Dprint((statp->options & RES_DEBUG) ||
581 ((statp->pfcode & RES_PRF_REPLY) &&
582 (statp->pfcode & RES_PRF_HEAD1)),
583 (stdout, ";; got answer:\n"));
585 DprintQ((statp->options & RES_DEBUG) ||
586 (statp->pfcode & RES_PRF_REPLY),
587 (stdout, "%s", ""),
588 ans, (resplen > anssiz) ? anssiz : resplen);
589 if (buf2 != NULL) {
590 DprintQ((statp->options & RES_DEBUG) ||
591 (statp->pfcode & RES_PRF_REPLY),
592 (stdout, "%s", ""),
593 *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
597 * If we have temporarily opened a virtual circuit,
598 * or if we haven't been asked to keep a socket open,
599 * close the socket.
601 if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
602 (statp->options & RES_STAYOPEN) == 0) {
603 __res_iclose(statp, false);
605 #ifdef USE_HOOKS
606 if (__glibc_unlikely (statp->rhook)) {
607 int done = 0, loops = 0;
609 do {
610 res_sendhookact act;
612 act = (*statp->rhook)((struct sockaddr_in *)
613 nsap, buf, buflen,
614 ans, anssiz, &resplen);
615 switch (act) {
616 case res_goahead:
617 case res_done:
618 done = 1;
619 break;
620 case res_nextns:
621 __res_iclose(statp, false);
622 goto next_ns;
623 case res_modified:
624 /* give the hook another try */
625 if (++loops < 42) /*doug adams*/
626 break;
627 /*FALLTHROUGH*/
628 case res_error:
629 /*FALLTHROUGH*/
630 default:
631 return (-1);
633 } while (!done);
636 #endif
637 return (resplen);
638 next_ns: ;
639 } /*foreach ns*/
640 } /*foreach retry*/
641 __res_iclose(statp, false);
642 if (!v_circuit) {
643 if (!gotsomewhere)
644 __set_errno (ECONNREFUSED); /* no nameservers found */
645 else
646 __set_errno (ETIMEDOUT); /* no answer obtained */
647 } else
648 __set_errno (terrno);
649 return (-1);
653 res_nsend(res_state statp,
654 const u_char *buf, int buflen, u_char *ans, int anssiz)
656 return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
657 NULL, NULL, NULL, NULL, NULL);
659 libresolv_hidden_def (res_nsend)
661 /* Private */
663 static int
664 send_vc(res_state statp,
665 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
666 u_char **ansp, int *anssizp,
667 int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
668 int *resplen2, int *ansp2_malloced)
670 const HEADER *hp = (HEADER *) buf;
671 const HEADER *hp2 = (HEADER *) buf2;
672 u_char *ans = *ansp;
673 int orig_anssizp = *anssizp;
674 // XXX REMOVE
675 // int anssiz = *anssizp;
676 HEADER *anhp = (HEADER *) ans;
677 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
678 int truncating, connreset, n;
679 /* On some architectures compiler might emit a warning indicating
680 'resplen' may be used uninitialized. However if buf2 == NULL
681 then this code won't be executed; if buf2 != NULL, then first
682 time round the loop recvresp1 and recvresp2 will be 0 so this
683 code won't be executed but "thisresplenp = &resplen;" followed
684 by "*thisresplenp = rlen;" will be executed so that subsequent
685 times round the loop resplen has been initialized. So this is
686 a false-positive.
688 #if __GNUC_PREREQ (4, 7)
689 DIAG_PUSH_NEEDS_COMMENT;
690 DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
691 #endif
692 int resplen;
693 #if __GNUC_PREREQ (4, 7)
694 DIAG_POP_NEEDS_COMMENT;
695 #endif
696 struct iovec iov[4];
697 u_short len;
698 u_short len2;
699 u_char *cp;
701 if (resplen2 != NULL)
702 *resplen2 = 0;
703 connreset = 0;
704 same_ns:
705 truncating = 0;
707 /* Are we still talking to whom we want to talk to? */
708 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
709 struct sockaddr_in6 peer;
710 socklen_t size = sizeof peer;
712 if (getpeername(statp->_vcsock,
713 (struct sockaddr *)&peer, &size) < 0 ||
714 !sock_eq(&peer, nsap)) {
715 __res_iclose(statp, false);
716 statp->_flags &= ~RES_F_VC;
720 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
721 if (statp->_vcsock >= 0)
722 __res_iclose(statp, false);
724 statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0);
725 if (statp->_vcsock < 0) {
726 *terrno = errno;
727 Perror(statp, stderr, "socket(vc)", errno);
728 return (-1);
730 __set_errno (0);
731 if (connect(statp->_vcsock, (struct sockaddr *)nsap,
732 nsap->sin6_family == AF_INET
733 ? sizeof (struct sockaddr_in)
734 : sizeof (struct sockaddr_in6)) < 0) {
735 *terrno = errno;
736 Aerror(statp, stderr, "connect/vc", errno,
737 (struct sockaddr *) nsap);
738 __res_iclose(statp, false);
739 return (0);
741 statp->_flags |= RES_F_VC;
745 * Send length & message
747 len = htons ((u_short) buflen);
748 evConsIovec(&len, INT16SZ, &iov[0]);
749 evConsIovec((void*)buf, buflen, &iov[1]);
750 int niov = 2;
751 ssize_t explen = INT16SZ + buflen;
752 if (buf2 != NULL) {
753 len2 = htons ((u_short) buflen2);
754 evConsIovec(&len2, INT16SZ, &iov[2]);
755 evConsIovec((void*)buf2, buflen2, &iov[3]);
756 niov = 4;
757 explen += INT16SZ + buflen2;
759 if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
760 *terrno = errno;
761 Perror(statp, stderr, "write failed", errno);
762 __res_iclose(statp, false);
763 return (0);
766 * Receive length & response
768 int recvresp1 = 0;
769 int recvresp2 = buf2 == NULL;
770 uint16_t rlen16;
771 read_len:
772 cp = (u_char *)&rlen16;
773 len = sizeof(rlen16);
774 while ((n = TEMP_FAILURE_RETRY (read(statp->_vcsock, cp,
775 (int)len))) > 0) {
776 cp += n;
777 if ((len -= n) <= 0)
778 break;
780 if (n <= 0) {
781 *terrno = errno;
782 Perror(statp, stderr, "read failed", errno);
783 __res_iclose(statp, false);
785 * A long running process might get its TCP
786 * connection reset if the remote server was
787 * restarted. Requery the server instead of
788 * trying a new one. When there is only one
789 * server, this means that a query might work
790 * instead of failing. We only allow one reset
791 * per query to prevent looping.
793 if (*terrno == ECONNRESET && !connreset) {
794 connreset = 1;
795 goto same_ns;
797 return (0);
799 int rlen = ntohs (rlen16);
801 int *thisanssizp;
802 u_char **thisansp;
803 int *thisresplenp;
804 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
805 thisanssizp = anssizp;
806 thisansp = anscp ?: ansp;
807 assert (anscp != NULL || ansp2 == NULL);
808 thisresplenp = &resplen;
809 } else {
810 if (*anssizp != MAXPACKET) {
811 /* No buffer allocated for the first
812 reply. We can try to use the rest
813 of the user-provided buffer. */
814 #if __GNUC_PREREQ (4, 7)
815 DIAG_PUSH_NEEDS_COMMENT;
816 DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
817 #endif
818 #if _STRING_ARCH_unaligned
819 *anssizp2 = orig_anssizp - resplen;
820 *ansp2 = *ansp + resplen;
821 #else
822 int aligned_resplen
823 = ((resplen + __alignof__ (HEADER) - 1)
824 & ~(__alignof__ (HEADER) - 1));
825 *anssizp2 = orig_anssizp - aligned_resplen;
826 *ansp2 = *ansp + aligned_resplen;
827 #endif
828 #if __GNUC_PREREQ (4, 7)
829 DIAG_POP_NEEDS_COMMENT;
830 #endif
831 } else {
832 /* The first reply did not fit into the
833 user-provided buffer. Maybe the second
834 answer will. */
835 *anssizp2 = orig_anssizp;
836 *ansp2 = *ansp;
839 thisanssizp = anssizp2;
840 thisansp = ansp2;
841 thisresplenp = resplen2;
843 anhp = (HEADER *) *thisansp;
845 *thisresplenp = rlen;
846 if (rlen > *thisanssizp) {
847 /* Yes, we test ANSCP here. If we have two buffers
848 both will be allocatable. */
849 if (__glibc_likely (anscp != NULL)) {
850 u_char *newp = malloc (MAXPACKET);
851 if (newp == NULL) {
852 *terrno = ENOMEM;
853 __res_iclose(statp, false);
854 return (0);
856 *thisanssizp = MAXPACKET;
857 *thisansp = newp;
858 if (thisansp == ansp2)
859 *ansp2_malloced = 1;
860 anhp = (HEADER *) newp;
861 len = rlen;
862 } else {
863 Dprint(statp->options & RES_DEBUG,
864 (stdout, ";; response truncated\n")
866 truncating = 1;
867 len = *thisanssizp;
869 } else
870 len = rlen;
872 if (__glibc_unlikely (len < HFIXEDSZ)) {
874 * Undersized message.
876 Dprint(statp->options & RES_DEBUG,
877 (stdout, ";; undersized: %d\n", len));
878 *terrno = EMSGSIZE;
879 __res_iclose(statp, false);
880 return (0);
883 cp = *thisansp;
884 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
885 cp += n;
886 len -= n;
888 if (__glibc_unlikely (n <= 0)) {
889 *terrno = errno;
890 Perror(statp, stderr, "read(vc)", errno);
891 __res_iclose(statp, false);
892 return (0);
894 if (__glibc_unlikely (truncating)) {
896 * Flush rest of answer so connection stays in synch.
898 anhp->tc = 1;
899 len = rlen - *thisanssizp;
900 while (len != 0) {
901 char junk[PACKETSZ];
903 n = read(statp->_vcsock, junk,
904 (len > sizeof junk) ? sizeof junk : len);
905 if (n > 0)
906 len -= n;
907 else
908 break;
912 * If the calling application has bailed out of
913 * a previous call and failed to arrange to have
914 * the circuit closed or the server has got
915 * itself confused, then drop the packet and
916 * wait for the correct one.
918 if ((recvresp1 || hp->id != anhp->id)
919 && (recvresp2 || hp2->id != anhp->id)) {
920 DprintQ((statp->options & RES_DEBUG) ||
921 (statp->pfcode & RES_PRF_REPLY),
922 (stdout, ";; old answer (unexpected):\n"),
923 *thisansp,
924 (rlen > *thisanssizp) ? *thisanssizp: rlen);
925 goto read_len;
928 /* Mark which reply we received. */
929 if (recvresp1 == 0 && hp->id == anhp->id)
930 recvresp1 = 1;
931 else
932 recvresp2 = 1;
933 /* Repeat waiting if we have a second answer to arrive. */
934 if ((recvresp1 & recvresp2) == 0)
935 goto read_len;
938 * All is well, or the error is fatal. Signal that the
939 * next nameserver ought not be tried.
941 return resplen;
944 static int
945 reopen (res_state statp, int *terrno, int ns)
947 if (EXT(statp).nssocks[ns] == -1) {
948 struct sockaddr *nsap
949 = (struct sockaddr *) EXT(statp).nsaddrs[ns];
950 socklen_t slen;
952 /* only try IPv6 if IPv6 NS and if not failed before */
953 if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
954 if (__glibc_likely (__have_o_nonblock >= 0)) {
955 EXT(statp).nssocks[ns] =
956 socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK,
958 #ifndef __ASSUME_SOCK_CLOEXEC
959 if (__have_o_nonblock == 0)
960 __have_o_nonblock
961 = (EXT(statp).nssocks[ns] == -1
962 && errno == EINVAL ? -1 : 1);
963 #endif
965 if (__glibc_unlikely (__have_o_nonblock < 0))
966 EXT(statp).nssocks[ns] =
967 socket(PF_INET6, SOCK_DGRAM, 0);
968 if (EXT(statp).nssocks[ns] < 0)
969 statp->ipv6_unavail = errno == EAFNOSUPPORT;
970 slen = sizeof (struct sockaddr_in6);
971 } else if (nsap->sa_family == AF_INET) {
972 if (__glibc_likely (__have_o_nonblock >= 0)) {
973 EXT(statp).nssocks[ns]
974 = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK,
976 #ifndef __ASSUME_SOCK_CLOEXEC
977 if (__have_o_nonblock == 0)
978 __have_o_nonblock
979 = (EXT(statp).nssocks[ns] == -1
980 && errno == EINVAL ? -1 : 1);
981 #endif
983 if (__glibc_unlikely (__have_o_nonblock < 0))
984 EXT(statp).nssocks[ns]
985 = socket(PF_INET, SOCK_DGRAM, 0);
986 slen = sizeof (struct sockaddr_in);
988 if (EXT(statp).nssocks[ns] < 0) {
989 *terrno = errno;
990 Perror(statp, stderr, "socket(dg)", errno);
991 return (-1);
995 * On a 4.3BSD+ machine (client and server,
996 * actually), sending to a nameserver datagram
997 * port with no nameserver will cause an
998 * ICMP port unreachable message to be returned.
999 * If our datagram socket is "connected" to the
1000 * server, we get an ECONNREFUSED error on the next
1001 * socket operation, and select returns if the
1002 * error message is received. We can thus detect
1003 * the absence of a nameserver without timing out.
1005 if (connect(EXT(statp).nssocks[ns], nsap, slen) < 0) {
1006 Aerror(statp, stderr, "connect(dg)", errno, nsap);
1007 __res_iclose(statp, false);
1008 return (0);
1010 if (__glibc_unlikely (__have_o_nonblock < 0)) {
1011 /* Make socket non-blocking. */
1012 int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL);
1013 if (fl != -1)
1014 __fcntl (EXT(statp).nssocks[ns], F_SETFL,
1015 fl | O_NONBLOCK);
1016 Dprint(statp->options & RES_DEBUG,
1017 (stdout, ";; new DG socket\n"))
1021 return 1;
1024 static int
1025 send_dg(res_state statp,
1026 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
1027 u_char **ansp, int *anssizp,
1028 int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
1029 u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
1031 const HEADER *hp = (HEADER *) buf;
1032 const HEADER *hp2 = (HEADER *) buf2;
1033 u_char *ans = *ansp;
1034 int orig_anssizp = *anssizp;
1035 struct timespec now, timeout, finish;
1036 struct pollfd pfd[1];
1037 int ptimeout;
1038 struct sockaddr_in6 from;
1039 int resplen = 0;
1040 int n;
1043 * Compute time for the total operation.
1045 int seconds = (statp->retrans << ns);
1046 if (ns > 0)
1047 seconds /= statp->nscount;
1048 if (seconds <= 0)
1049 seconds = 1;
1050 bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
1051 bool single_request = (((statp->options & RES_SNGLKUP) != 0)
1052 | single_request_reopen);
1053 int save_gotsomewhere = *gotsomewhere;
1055 int retval;
1056 retry_reopen:
1057 retval = reopen (statp, terrno, ns);
1058 if (retval <= 0)
1059 return retval;
1060 retry:
1061 evNowTime(&now);
1062 evConsTime(&timeout, seconds, 0);
1063 evAddTime(&finish, &now, &timeout);
1064 int need_recompute = 0;
1065 int nwritten = 0;
1066 int recvresp1 = 0;
1067 int recvresp2 = buf2 == NULL;
1068 pfd[0].fd = EXT(statp).nssocks[ns];
1069 pfd[0].events = POLLOUT;
1070 if (resplen2 != NULL)
1071 *resplen2 = 0;
1072 wait:
1073 if (need_recompute) {
1074 recompute_resend:
1075 evNowTime(&now);
1076 if (evCmpTime(finish, now) <= 0) {
1077 poll_err_out:
1078 Perror(statp, stderr, "poll", errno);
1079 err_out:
1080 __res_iclose(statp, false);
1081 return (0);
1083 evSubTime(&timeout, &finish, &now);
1084 need_recompute = 0;
1086 /* Convert struct timespec in milliseconds. */
1087 ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
1089 n = 0;
1090 if (nwritten == 0)
1091 n = __poll (pfd, 1, 0);
1092 if (__glibc_unlikely (n == 0)) {
1093 n = __poll (pfd, 1, ptimeout);
1094 need_recompute = 1;
1096 if (n == 0) {
1097 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1098 if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
1100 /* There are quite a few broken name servers out
1101 there which don't handle two outstanding
1102 requests from the same source. There are also
1103 broken firewall settings. If we time out after
1104 having received one answer switch to the mode
1105 where we send the second request only once we
1106 have received the first answer. */
1107 if (!single_request)
1109 statp->options |= RES_SNGLKUP;
1110 single_request = true;
1111 *gotsomewhere = save_gotsomewhere;
1112 goto retry;
1114 else if (!single_request_reopen)
1116 statp->options |= RES_SNGLKUPREOP;
1117 single_request_reopen = true;
1118 *gotsomewhere = save_gotsomewhere;
1119 __res_iclose (statp, false);
1120 goto retry_reopen;
1123 *resplen2 = 1;
1124 return resplen;
1127 *gotsomewhere = 1;
1128 return (0);
1130 if (n < 0) {
1131 if (errno == EINTR)
1132 goto recompute_resend;
1134 goto poll_err_out;
1136 __set_errno (0);
1137 if (pfd[0].revents & POLLOUT) {
1138 #ifndef __ASSUME_SENDMMSG
1139 static int have_sendmmsg;
1140 #else
1141 # define have_sendmmsg 1
1142 #endif
1143 if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL
1144 && !single_request)
1146 struct iovec iov[2];
1147 struct mmsghdr reqs[2];
1148 reqs[0].msg_hdr.msg_name = NULL;
1149 reqs[0].msg_hdr.msg_namelen = 0;
1150 reqs[0].msg_hdr.msg_iov = &iov[0];
1151 reqs[0].msg_hdr.msg_iovlen = 1;
1152 iov[0].iov_base = (void *) buf;
1153 iov[0].iov_len = buflen;
1154 reqs[0].msg_hdr.msg_control = NULL;
1155 reqs[0].msg_hdr.msg_controllen = 0;
1157 reqs[1].msg_hdr.msg_name = NULL;
1158 reqs[1].msg_hdr.msg_namelen = 0;
1159 reqs[1].msg_hdr.msg_iov = &iov[1];
1160 reqs[1].msg_hdr.msg_iovlen = 1;
1161 iov[1].iov_base = (void *) buf2;
1162 iov[1].iov_len = buflen2;
1163 reqs[1].msg_hdr.msg_control = NULL;
1164 reqs[1].msg_hdr.msg_controllen = 0;
1166 int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL);
1167 if (__glibc_likely (ndg == 2))
1169 if (reqs[0].msg_len != buflen
1170 || reqs[1].msg_len != buflen2)
1171 goto fail_sendmmsg;
1173 pfd[0].events = POLLIN;
1174 nwritten += 2;
1176 else if (ndg == 1 && reqs[0].msg_len == buflen)
1177 goto just_one;
1178 else if (ndg < 0 && (errno == EINTR || errno == EAGAIN))
1179 goto recompute_resend;
1180 else
1182 #ifndef __ASSUME_SENDMMSG
1183 if (__glibc_unlikely (have_sendmmsg == 0))
1185 if (ndg < 0 && errno == ENOSYS)
1187 have_sendmmsg = -1;
1188 goto try_send;
1190 have_sendmmsg = 1;
1192 #endif
1194 fail_sendmmsg:
1195 Perror(statp, stderr, "sendmmsg", errno);
1196 goto err_out;
1199 else
1201 ssize_t sr;
1202 #ifndef __ASSUME_SENDMMSG
1203 try_send:
1204 #endif
1205 if (nwritten != 0)
1206 sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
1207 else
1208 sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
1210 if (sr != (nwritten != 0 ? buflen2 : buflen)) {
1211 if (errno == EINTR || errno == EAGAIN)
1212 goto recompute_resend;
1213 Perror(statp, stderr, "send", errno);
1214 goto err_out;
1216 just_one:
1217 if (nwritten != 0 || buf2 == NULL || single_request)
1218 pfd[0].events = POLLIN;
1219 else
1220 pfd[0].events = POLLIN | POLLOUT;
1221 ++nwritten;
1223 goto wait;
1224 } else if (pfd[0].revents & POLLIN) {
1225 int *thisanssizp;
1226 u_char **thisansp;
1227 int *thisresplenp;
1229 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1230 thisanssizp = anssizp;
1231 thisansp = anscp ?: ansp;
1232 assert (anscp != NULL || ansp2 == NULL);
1233 thisresplenp = &resplen;
1234 } else {
1235 if (*anssizp != MAXPACKET) {
1236 /* No buffer allocated for the first
1237 reply. We can try to use the rest
1238 of the user-provided buffer. */
1239 #if _STRING_ARCH_unaligned
1240 *anssizp2 = orig_anssizp - resplen;
1241 *ansp2 = *ansp + resplen;
1242 #else
1243 int aligned_resplen
1244 = ((resplen + __alignof__ (HEADER) - 1)
1245 & ~(__alignof__ (HEADER) - 1));
1246 *anssizp2 = orig_anssizp - aligned_resplen;
1247 *ansp2 = *ansp + aligned_resplen;
1248 #endif
1249 } else {
1250 /* The first reply did not fit into the
1251 user-provided buffer. Maybe the second
1252 answer will. */
1253 *anssizp2 = orig_anssizp;
1254 *ansp2 = *ansp;
1257 thisanssizp = anssizp2;
1258 thisansp = ansp2;
1259 thisresplenp = resplen2;
1262 if (*thisanssizp < MAXPACKET
1263 /* Yes, we test ANSCP here. If we have two buffers
1264 both will be allocatable. */
1265 && anscp
1266 #ifdef FIONREAD
1267 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
1268 || *thisanssizp < *thisresplenp)
1269 #endif
1271 u_char *newp = malloc (MAXPACKET);
1272 if (newp != NULL) {
1273 *anssizp = MAXPACKET;
1274 *thisansp = ans = newp;
1275 if (thisansp == ansp2)
1276 *ansp2_malloced = 1;
1279 HEADER *anhp = (HEADER *) *thisansp;
1280 socklen_t fromlen = sizeof(struct sockaddr_in6);
1281 assert (sizeof(from) <= fromlen);
1282 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1283 *thisanssizp, 0,
1284 (struct sockaddr *)&from, &fromlen);
1285 if (__glibc_unlikely (*thisresplenp <= 0)) {
1286 if (errno == EINTR || errno == EAGAIN) {
1287 need_recompute = 1;
1288 goto wait;
1290 Perror(statp, stderr, "recvfrom", errno);
1291 goto err_out;
1293 *gotsomewhere = 1;
1294 if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
1296 * Undersized message.
1298 Dprint(statp->options & RES_DEBUG,
1299 (stdout, ";; undersized: %d\n",
1300 *thisresplenp));
1301 *terrno = EMSGSIZE;
1302 goto err_out;
1304 if ((recvresp1 || hp->id != anhp->id)
1305 && (recvresp2 || hp2->id != anhp->id)) {
1307 * response from old query, ignore it.
1308 * XXX - potential security hazard could
1309 * be detected here.
1311 DprintQ((statp->options & RES_DEBUG) ||
1312 (statp->pfcode & RES_PRF_REPLY),
1313 (stdout, ";; old answer:\n"),
1314 *thisansp,
1315 (*thisresplenp > *thisanssizp)
1316 ? *thisanssizp : *thisresplenp);
1317 goto wait;
1319 if (!(statp->options & RES_INSECURE1) &&
1320 !res_ourserver_p(statp, &from)) {
1322 * response from wrong server? ignore it.
1323 * XXX - potential security hazard could
1324 * be detected here.
1326 DprintQ((statp->options & RES_DEBUG) ||
1327 (statp->pfcode & RES_PRF_REPLY),
1328 (stdout, ";; not our server:\n"),
1329 *thisansp,
1330 (*thisresplenp > *thisanssizp)
1331 ? *thisanssizp : *thisresplenp);
1332 goto wait;
1334 #ifdef RES_USE_EDNS0
1335 if (anhp->rcode == FORMERR
1336 && (statp->options & RES_USE_EDNS0) != 0U) {
1338 * Do not retry if the server does not understand
1339 * EDNS0. The case has to be captured here, as
1340 * FORMERR packet do not carry query section, hence
1341 * res_queriesmatch() returns 0.
1343 DprintQ(statp->options & RES_DEBUG,
1344 (stdout,
1345 "server rejected query with EDNS0:\n"),
1346 *thisansp,
1347 (*thisresplenp > *thisanssizp)
1348 ? *thisanssizp : *thisresplenp);
1349 /* record the error */
1350 statp->_flags |= RES_F_EDNS0ERR;
1351 goto err_out;
1353 #endif
1354 if (!(statp->options & RES_INSECURE2)
1355 && (recvresp1 || !res_queriesmatch(buf, buf + buflen,
1356 *thisansp,
1357 *thisansp
1358 + *thisanssizp))
1359 && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
1360 *thisansp,
1361 *thisansp
1362 + *thisanssizp))) {
1364 * response contains wrong query? ignore it.
1365 * XXX - potential security hazard could
1366 * be detected here.
1368 DprintQ((statp->options & RES_DEBUG) ||
1369 (statp->pfcode & RES_PRF_REPLY),
1370 (stdout, ";; wrong query name:\n"),
1371 *thisansp,
1372 (*thisresplenp > *thisanssizp)
1373 ? *thisanssizp : *thisresplenp);
1374 goto wait;
1376 if (anhp->rcode == SERVFAIL ||
1377 anhp->rcode == NOTIMP ||
1378 anhp->rcode == REFUSED) {
1379 DprintQ(statp->options & RES_DEBUG,
1380 (stdout, "server rejected query:\n"),
1381 *thisansp,
1382 (*thisresplenp > *thisanssizp)
1383 ? *thisanssizp : *thisresplenp);
1385 next_ns:
1386 if (recvresp1 || (buf2 != NULL && recvresp2)) {
1387 *resplen2 = 0;
1388 return resplen;
1390 if (buf2 != NULL)
1392 /* No data from the first reply. */
1393 resplen = 0;
1394 /* We are waiting for a possible second reply. */
1395 if (hp->id == anhp->id)
1396 recvresp1 = 1;
1397 else
1398 recvresp2 = 1;
1400 goto wait;
1403 __res_iclose(statp, false);
1404 /* don't retry if called from dig */
1405 if (!statp->pfcode)
1406 return (0);
1408 if (anhp->rcode == NOERROR && anhp->ancount == 0
1409 && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
1410 DprintQ(statp->options & RES_DEBUG,
1411 (stdout, "referred query:\n"),
1412 *thisansp,
1413 (*thisresplenp > *thisanssizp)
1414 ? *thisanssizp : *thisresplenp);
1415 goto next_ns;
1417 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1419 * To get the rest of answer,
1420 * use TCP with same server.
1422 Dprint(statp->options & RES_DEBUG,
1423 (stdout, ";; truncated answer\n"));
1424 *v_circuit = 1;
1425 __res_iclose(statp, false);
1426 // XXX if we have received one reply we could
1427 // XXX use it and not repeat it over TCP...
1428 return (1);
1430 /* Mark which reply we received. */
1431 if (recvresp1 == 0 && hp->id == anhp->id)
1432 recvresp1 = 1;
1433 else
1434 recvresp2 = 1;
1435 /* Repeat waiting if we have a second answer to arrive. */
1436 if ((recvresp1 & recvresp2) == 0) {
1437 if (single_request) {
1438 pfd[0].events = POLLOUT;
1439 if (single_request_reopen) {
1440 __res_iclose (statp, false);
1441 retval = reopen (statp, terrno, ns);
1442 if (retval <= 0)
1443 return retval;
1444 pfd[0].fd = EXT(statp).nssocks[ns];
1447 goto wait;
1450 * All is well, or the error is fatal. Signal that the
1451 * next nameserver ought not be tried.
1453 return (resplen);
1454 } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
1455 /* Something went wrong. We can stop trying. */
1456 goto err_out;
1458 else {
1459 /* poll should not have returned > 0 in this case. */
1460 abort ();
1464 #ifdef DEBUG
1465 static void
1466 Aerror(const res_state statp, FILE *file, const char *string, int error,
1467 const struct sockaddr *address)
1469 int save = errno;
1471 if ((statp->options & RES_DEBUG) != 0) {
1472 char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
1474 fprintf(file, "res_send: %s ([%s].%u): %s\n",
1475 string,
1476 (address->sa_family == AF_INET
1477 ? inet_ntop(address->sa_family,
1478 &((const struct sockaddr_in *) address)->sin_addr,
1479 tmp, sizeof tmp)
1480 : inet_ntop(address->sa_family,
1481 &((const struct sockaddr_in6 *) address)->sin6_addr,
1482 tmp, sizeof tmp)),
1483 (address->sa_family == AF_INET
1484 ? ntohs(((struct sockaddr_in *) address)->sin_port)
1485 : address->sa_family == AF_INET6
1486 ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
1487 : 0),
1488 strerror(error));
1490 __set_errno (save);
1493 static void
1494 Perror(const res_state statp, FILE *file, const char *string, int error) {
1495 int save = errno;
1497 if ((statp->options & RES_DEBUG) != 0)
1498 fprintf(file, "res_send: %s: %s\n",
1499 string, strerror(error));
1500 __set_errno (save);
1502 #endif
1504 static int
1505 sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
1506 if (a1->sin6_family == a2->sin6_family) {
1507 if (a1->sin6_family == AF_INET)
1508 return ((((struct sockaddr_in *)a1)->sin_port ==
1509 ((struct sockaddr_in *)a2)->sin_port) &&
1510 (((struct sockaddr_in *)a1)->sin_addr.s_addr ==
1511 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1512 else
1513 return ((a1->sin6_port == a2->sin6_port) &&
1514 !memcmp(&a1->sin6_addr, &a2->sin6_addr,
1515 sizeof (struct in6_addr)));
1517 if (a1->sin6_family == AF_INET) {
1518 struct sockaddr_in6 *sap = a1;
1519 a1 = a2;
1520 a2 = sap;
1521 } /* assumes that AF_INET and AF_INET6 are the only possibilities */
1522 return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) &&
1523 IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) &&
1524 (a1->sin6_addr.s6_addr32[3] ==
1525 ((struct sockaddr_in *)a2)->sin_addr.s_addr));