Remove gnu_unique_object configure test.
[glibc.git] / resolv / res_send.c
blob6137e4d7889574a5c231cb763cf480e3a98a89d4
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
107 /* From ev_streams.c. */
109 static inline void
110 __attribute ((always_inline))
111 evConsIovec(void *buf, size_t cnt, struct iovec *vec) {
112 memset(vec, 0xf5, sizeof (*vec));
113 vec->iov_base = buf;
114 vec->iov_len = cnt;
117 /* From ev_timers.c. */
119 #define BILLION 1000000000
121 static inline void
122 evConsTime(struct timespec *res, time_t sec, long nsec) {
123 res->tv_sec = sec;
124 res->tv_nsec = nsec;
127 static inline void
128 evAddTime(struct timespec *res, const struct timespec *addend1,
129 const struct timespec *addend2) {
130 res->tv_sec = addend1->tv_sec + addend2->tv_sec;
131 res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec;
132 if (res->tv_nsec >= BILLION) {
133 res->tv_sec++;
134 res->tv_nsec -= BILLION;
138 static inline void
139 evSubTime(struct timespec *res, const struct timespec *minuend,
140 const struct timespec *subtrahend) {
141 res->tv_sec = minuend->tv_sec - subtrahend->tv_sec;
142 if (minuend->tv_nsec >= subtrahend->tv_nsec)
143 res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec;
144 else {
145 res->tv_nsec = (BILLION
146 - subtrahend->tv_nsec + minuend->tv_nsec);
147 res->tv_sec--;
151 static int
152 evCmpTime(struct timespec a, struct timespec b) {
153 long x = a.tv_sec - b.tv_sec;
155 if (x == 0L)
156 x = a.tv_nsec - b.tv_nsec;
157 return (x < 0L ? (-1) : x > 0L ? (1) : (0));
160 static void
161 evNowTime(struct timespec *res) {
162 struct timeval now;
164 if (gettimeofday(&now, NULL) < 0)
165 evConsTime(res, 0, 0);
166 else
167 TIMEVAL_TO_TIMESPEC (&now, res);
171 /* Options. Leave them on. */
172 /* #undef DEBUG */
173 #include "res_debug.h"
175 #define EXT(res) ((res)->_u._ext)
177 /* Forward. */
179 static struct sockaddr *get_nsaddr (res_state, int);
180 static int send_vc(res_state, const u_char *, int,
181 const u_char *, int,
182 u_char **, int *, int *, int, u_char **,
183 u_char **, int *, int *, int *);
184 static int send_dg(res_state, const u_char *, int,
185 const u_char *, int,
186 u_char **, int *, int *, int,
187 int *, int *, u_char **,
188 u_char **, int *, int *, int *);
189 #ifdef DEBUG
190 static void Aerror(const res_state, FILE *, const char *, int,
191 const struct sockaddr *);
192 static void Perror(const res_state, FILE *, const char *, int);
193 #endif
194 static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
196 /* Public. */
198 /* int
199 * res_isourserver(ina)
200 * looks up "ina" in _res.ns_addr_list[]
201 * returns:
202 * 0 : not found
203 * >0 : found
204 * author:
205 * paul vixie, 29may94
208 res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
210 int ns;
212 if (inp->sin6_family == AF_INET) {
213 struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
214 in_port_t port = in4p->sin_port;
215 in_addr_t addr = in4p->sin_addr.s_addr;
217 for (ns = 0; ns < statp->nscount; ns++) {
218 const struct sockaddr_in *srv =
219 (struct sockaddr_in *) get_nsaddr (statp, ns);
221 if ((srv->sin_family == AF_INET) &&
222 (srv->sin_port == port) &&
223 (srv->sin_addr.s_addr == INADDR_ANY ||
224 srv->sin_addr.s_addr == addr))
225 return (1);
227 } else if (inp->sin6_family == AF_INET6) {
228 for (ns = 0; ns < statp->nscount; ns++) {
229 const struct sockaddr_in6 *srv
230 = (struct sockaddr_in6 *) get_nsaddr (statp, ns);
231 if ((srv->sin6_family == AF_INET6) &&
232 (srv->sin6_port == inp->sin6_port) &&
233 !(memcmp(&srv->sin6_addr, &in6addr_any,
234 sizeof (struct in6_addr)) &&
235 memcmp(&srv->sin6_addr, &inp->sin6_addr,
236 sizeof (struct in6_addr))))
237 return (1);
240 return (0);
243 /* int
244 * res_nameinquery(name, type, class, buf, eom)
245 * look for (name,type,class) in the query section of packet (buf,eom)
246 * requires:
247 * buf + HFIXEDSZ <= eom
248 * returns:
249 * -1 : format error
250 * 0 : not found
251 * >0 : found
252 * author:
253 * paul vixie, 29may94
256 res_nameinquery(const char *name, int type, int class,
257 const u_char *buf, const u_char *eom)
259 const u_char *cp = buf + HFIXEDSZ;
260 int qdcount = ntohs(((HEADER*)buf)->qdcount);
262 while (qdcount-- > 0) {
263 char tname[MAXDNAME+1];
264 int n, ttype, tclass;
266 n = dn_expand(buf, eom, cp, tname, sizeof tname);
267 if (n < 0)
268 return (-1);
269 cp += n;
270 if (cp + 2 * INT16SZ > eom)
271 return (-1);
272 NS_GET16(ttype, cp);
273 NS_GET16(tclass, cp);
274 if (ttype == type && tclass == class &&
275 ns_samename(tname, name) == 1)
276 return (1);
278 return (0);
280 libresolv_hidden_def (res_nameinquery)
282 /* int
283 * res_queriesmatch(buf1, eom1, buf2, eom2)
284 * is there a 1:1 mapping of (name,type,class)
285 * in (buf1,eom1) and (buf2,eom2)?
286 * returns:
287 * -1 : format error
288 * 0 : not a 1:1 mapping
289 * >0 : is a 1:1 mapping
290 * author:
291 * paul vixie, 29may94
294 res_queriesmatch(const u_char *buf1, const u_char *eom1,
295 const u_char *buf2, const u_char *eom2)
297 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
298 return (-1);
301 * Only header section present in replies to
302 * dynamic update packets.
304 if ((((HEADER *)buf1)->opcode == ns_o_update) &&
305 (((HEADER *)buf2)->opcode == ns_o_update))
306 return (1);
308 /* Note that we initially do not convert QDCOUNT to the host byte
309 order. We can compare it with the second buffer's QDCOUNT
310 value without doing this. */
311 int qdcount = ((HEADER*)buf1)->qdcount;
312 if (qdcount != ((HEADER*)buf2)->qdcount)
313 return (0);
315 qdcount = htons (qdcount);
316 const u_char *cp = buf1 + HFIXEDSZ;
318 while (qdcount-- > 0) {
319 char tname[MAXDNAME+1];
320 int n, ttype, tclass;
322 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
323 if (n < 0)
324 return (-1);
325 cp += n;
326 if (cp + 2 * INT16SZ > eom1)
327 return (-1);
328 NS_GET16(ttype, cp);
329 NS_GET16(tclass, cp);
330 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
331 return (0);
333 return (1);
335 libresolv_hidden_def (res_queriesmatch)
338 __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
339 const u_char *buf2, int buflen2,
340 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
341 int *nansp2, int *resplen2, int *ansp2_malloced)
343 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
345 if (statp->nscount == 0) {
346 __set_errno (ESRCH);
347 return (-1);
350 if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) {
351 __set_errno (EINVAL);
352 return (-1);
355 #ifdef USE_HOOKS
356 if (__glibc_unlikely (statp->qhook || statp->rhook)) {
357 if (anssiz < MAXPACKET && ansp) {
358 u_char *buf = malloc (MAXPACKET);
359 if (buf == NULL)
360 return (-1);
361 memcpy (buf, ans, HFIXEDSZ);
362 *ansp = buf;
363 ans = buf;
364 anssiz = MAXPACKET;
367 #endif
369 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
370 (stdout, ";; res_send()\n"), buf, buflen);
371 v_circuit = ((statp->options & RES_USEVC)
372 || buflen > PACKETSZ
373 || buflen2 > PACKETSZ);
374 gotsomewhere = 0;
375 terrno = ETIMEDOUT;
378 * If the ns_addr_list in the resolver context has changed, then
379 * invalidate our cached copy and the associated timing data.
381 if (EXT(statp).nscount != 0) {
382 int needclose = 0;
384 if (EXT(statp).nscount != statp->nscount)
385 needclose++;
386 else
387 for (ns = 0; ns < statp->nscount; ns++) {
388 if (statp->nsaddr_list[ns].sin_family != 0
389 && !sock_eq((struct sockaddr_in6 *)
390 &statp->nsaddr_list[ns],
391 EXT(statp).nsaddrs[ns]))
393 needclose++;
394 break;
397 if (needclose) {
398 __res_iclose(statp, false);
399 EXT(statp).nscount = 0;
404 * Maybe initialize our private copy of the ns_addr_list.
406 if (EXT(statp).nscount == 0) {
407 for (ns = 0; ns < statp->nscount; ns++) {
408 EXT(statp).nssocks[ns] = -1;
409 if (statp->nsaddr_list[ns].sin_family == 0)
410 continue;
411 if (EXT(statp).nsaddrs[ns] == NULL)
412 EXT(statp).nsaddrs[ns] =
413 malloc(sizeof (struct sockaddr_in6));
414 if (EXT(statp).nsaddrs[ns] != NULL)
415 memset (mempcpy(EXT(statp).nsaddrs[ns],
416 &statp->nsaddr_list[ns],
417 sizeof (struct sockaddr_in)),
418 '\0',
419 sizeof (struct sockaddr_in6)
420 - sizeof (struct sockaddr_in));
422 EXT(statp).nscount = statp->nscount;
426 * Some resolvers want to even out the load on their nameservers.
427 * Note that RES_BLAST overrides RES_ROTATE.
429 if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
430 (statp->options & RES_BLAST) == 0) {
431 struct sockaddr_in ina;
432 struct sockaddr_in6 *inp;
433 int lastns = statp->nscount - 1;
434 int fd;
436 inp = EXT(statp).nsaddrs[0];
437 ina = statp->nsaddr_list[0];
438 fd = EXT(statp).nssocks[0];
439 for (ns = 0; ns < lastns; ns++) {
440 EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1];
441 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
442 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
444 EXT(statp).nsaddrs[lastns] = inp;
445 statp->nsaddr_list[lastns] = ina;
446 EXT(statp).nssocks[lastns] = fd;
450 * Send request, RETRY times, or until successful.
452 for (try = 0; try < statp->retry; try++) {
453 for (ns = 0; ns < statp->nscount; ns++)
455 #ifdef DEBUG
456 char tmpbuf[40];
457 #endif
458 #if defined USE_HOOKS || defined DEBUG
459 struct sockaddr *nsap = get_nsaddr (statp, ns);
460 #endif
462 same_ns:
463 #ifdef USE_HOOKS
464 if (__glibc_unlikely (statp->qhook != NULL)) {
465 int done = 0, loops = 0;
467 do {
468 res_sendhookact act;
470 struct sockaddr_in *nsap4;
471 nsap4 = (struct sockaddr_in *) nsap;
472 act = (*statp->qhook)(&nsap4, &buf, &buflen,
473 ans, anssiz, &resplen);
474 nsap = (struct sockaddr_in6 *) nsap4;
475 switch (act) {
476 case res_goahead:
477 done = 1;
478 break;
479 case res_nextns:
480 __res_iclose(statp, false);
481 goto next_ns;
482 case res_done:
483 return (resplen);
484 case res_modified:
485 /* give the hook another try */
486 if (++loops < 42) /*doug adams*/
487 break;
488 /*FALLTHROUGH*/
489 case res_error:
490 /*FALLTHROUGH*/
491 default:
492 return (-1);
494 } while (!done);
496 #endif
498 Dprint(statp->options & RES_DEBUG,
499 (stdout, ";; Querying server (# %d) address = %s\n",
500 ns + 1, inet_ntop(nsap->sa_family,
501 (nsap->sa_family == AF_INET6
502 ? &((struct sockaddr_in6 *) nsap)->sin6_addr
503 : &((struct sockaddr_in *) nsap)->sin_addr),
504 tmpbuf, sizeof (tmpbuf))));
506 if (__glibc_unlikely (v_circuit)) {
507 /* Use VC; at most one attempt per server. */
508 try = statp->retry;
509 n = send_vc(statp, buf, buflen, buf2, buflen2,
510 &ans, &anssiz, &terrno,
511 ns, ansp, ansp2, nansp2, resplen2,
512 ansp2_malloced);
513 if (n < 0)
514 return (-1);
515 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
516 goto next_ns;
517 } else {
518 /* Use datagrams. */
519 n = send_dg(statp, buf, buflen, buf2, buflen2,
520 &ans, &anssiz, &terrno,
521 ns, &v_circuit, &gotsomewhere, ansp,
522 ansp2, nansp2, resplen2, ansp2_malloced);
523 if (n < 0)
524 return (-1);
525 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
526 goto next_ns;
527 if (v_circuit)
528 // XXX Check whether both requests failed or
529 // XXX whether one has been answered successfully
530 goto same_ns;
533 resplen = n;
535 Dprint((statp->options & RES_DEBUG) ||
536 ((statp->pfcode & RES_PRF_REPLY) &&
537 (statp->pfcode & RES_PRF_HEAD1)),
538 (stdout, ";; got answer:\n"));
540 DprintQ((statp->options & RES_DEBUG) ||
541 (statp->pfcode & RES_PRF_REPLY),
542 (stdout, "%s", ""),
543 ans, (resplen > anssiz) ? anssiz : resplen);
544 if (buf2 != NULL) {
545 DprintQ((statp->options & RES_DEBUG) ||
546 (statp->pfcode & RES_PRF_REPLY),
547 (stdout, "%s", ""),
548 *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
552 * If we have temporarily opened a virtual circuit,
553 * or if we haven't been asked to keep a socket open,
554 * close the socket.
556 if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
557 (statp->options & RES_STAYOPEN) == 0) {
558 __res_iclose(statp, false);
560 #ifdef USE_HOOKS
561 if (__glibc_unlikely (statp->rhook)) {
562 int done = 0, loops = 0;
564 do {
565 res_sendhookact act;
567 act = (*statp->rhook)((struct sockaddr_in *)
568 nsap, buf, buflen,
569 ans, anssiz, &resplen);
570 switch (act) {
571 case res_goahead:
572 case res_done:
573 done = 1;
574 break;
575 case res_nextns:
576 __res_iclose(statp, false);
577 goto next_ns;
578 case res_modified:
579 /* give the hook another try */
580 if (++loops < 42) /*doug adams*/
581 break;
582 /*FALLTHROUGH*/
583 case res_error:
584 /*FALLTHROUGH*/
585 default:
586 return (-1);
588 } while (!done);
591 #endif
592 return (resplen);
593 next_ns: ;
594 } /*foreach ns*/
595 } /*foreach retry*/
596 __res_iclose(statp, false);
597 if (!v_circuit) {
598 if (!gotsomewhere)
599 __set_errno (ECONNREFUSED); /* no nameservers found */
600 else
601 __set_errno (ETIMEDOUT); /* no answer obtained */
602 } else
603 __set_errno (terrno);
604 return (-1);
608 res_nsend(res_state statp,
609 const u_char *buf, int buflen, u_char *ans, int anssiz)
611 return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
612 NULL, NULL, NULL, NULL, NULL);
614 libresolv_hidden_def (res_nsend)
616 /* Private */
618 static struct sockaddr *
619 get_nsaddr (res_state statp, int n)
622 if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL)
623 /* EXT(statp).nsaddrs[n] holds an address that is larger than
624 struct sockaddr, and user code did not update
625 statp->nsaddr_list[n]. */
626 return (struct sockaddr *) EXT(statp).nsaddrs[n];
627 else
628 /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n]
629 has the same content as EXT(statp).nsaddrs[n]. */
630 return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
633 static int
634 send_vc(res_state statp,
635 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
636 u_char **ansp, int *anssizp,
637 int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
638 int *resplen2, int *ansp2_malloced)
640 const HEADER *hp = (HEADER *) buf;
641 const HEADER *hp2 = (HEADER *) buf2;
642 u_char *ans = *ansp;
643 int orig_anssizp = *anssizp;
644 // XXX REMOVE
645 // int anssiz = *anssizp;
646 HEADER *anhp = (HEADER *) ans;
647 struct sockaddr *nsap = get_nsaddr (statp, ns);
648 int truncating, connreset, n;
649 /* On some architectures compiler might emit a warning indicating
650 'resplen' may be used uninitialized. However if buf2 == NULL
651 then this code won't be executed; if buf2 != NULL, then first
652 time round the loop recvresp1 and recvresp2 will be 0 so this
653 code won't be executed but "thisresplenp = &resplen;" followed
654 by "*thisresplenp = rlen;" will be executed so that subsequent
655 times round the loop resplen has been initialized. So this is
656 a false-positive.
658 #if __GNUC_PREREQ (4, 7)
659 DIAG_PUSH_NEEDS_COMMENT;
660 DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
661 #endif
662 int resplen;
663 #if __GNUC_PREREQ (4, 7)
664 DIAG_POP_NEEDS_COMMENT;
665 #endif
666 struct iovec iov[4];
667 u_short len;
668 u_short len2;
669 u_char *cp;
671 if (resplen2 != NULL)
672 *resplen2 = 0;
673 connreset = 0;
674 same_ns:
675 truncating = 0;
677 /* Are we still talking to whom we want to talk to? */
678 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
679 struct sockaddr_in6 peer;
680 socklen_t size = sizeof peer;
682 if (getpeername(statp->_vcsock,
683 (struct sockaddr *)&peer, &size) < 0 ||
684 !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) {
685 __res_iclose(statp, false);
686 statp->_flags &= ~RES_F_VC;
690 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
691 if (statp->_vcsock >= 0)
692 __res_iclose(statp, false);
694 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
695 if (statp->_vcsock < 0) {
696 *terrno = errno;
697 Perror(statp, stderr, "socket(vc)", errno);
698 return (-1);
700 __set_errno (0);
701 if (connect(statp->_vcsock, nsap,
702 nsap->sa_family == AF_INET
703 ? sizeof (struct sockaddr_in)
704 : sizeof (struct sockaddr_in6)) < 0) {
705 *terrno = errno;
706 Aerror(statp, stderr, "connect/vc", errno, nsap);
707 __res_iclose(statp, false);
708 return (0);
710 statp->_flags |= RES_F_VC;
714 * Send length & message
716 len = htons ((u_short) buflen);
717 evConsIovec(&len, INT16SZ, &iov[0]);
718 evConsIovec((void*)buf, buflen, &iov[1]);
719 int niov = 2;
720 ssize_t explen = INT16SZ + buflen;
721 if (buf2 != NULL) {
722 len2 = htons ((u_short) buflen2);
723 evConsIovec(&len2, INT16SZ, &iov[2]);
724 evConsIovec((void*)buf2, buflen2, &iov[3]);
725 niov = 4;
726 explen += INT16SZ + buflen2;
728 if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
729 *terrno = errno;
730 Perror(statp, stderr, "write failed", errno);
731 __res_iclose(statp, false);
732 return (0);
735 * Receive length & response
737 int recvresp1 = 0;
738 int recvresp2 = buf2 == NULL;
739 uint16_t rlen16;
740 read_len:
741 cp = (u_char *)&rlen16;
742 len = sizeof(rlen16);
743 while ((n = TEMP_FAILURE_RETRY (read(statp->_vcsock, cp,
744 (int)len))) > 0) {
745 cp += n;
746 if ((len -= n) <= 0)
747 break;
749 if (n <= 0) {
750 *terrno = errno;
751 Perror(statp, stderr, "read failed", errno);
752 __res_iclose(statp, false);
754 * A long running process might get its TCP
755 * connection reset if the remote server was
756 * restarted. Requery the server instead of
757 * trying a new one. When there is only one
758 * server, this means that a query might work
759 * instead of failing. We only allow one reset
760 * per query to prevent looping.
762 if (*terrno == ECONNRESET && !connreset) {
763 connreset = 1;
764 goto same_ns;
766 return (0);
768 int rlen = ntohs (rlen16);
770 int *thisanssizp;
771 u_char **thisansp;
772 int *thisresplenp;
773 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
774 thisanssizp = anssizp;
775 thisansp = anscp ?: ansp;
776 assert (anscp != NULL || ansp2 == NULL);
777 thisresplenp = &resplen;
778 } else {
779 if (*anssizp != MAXPACKET) {
780 /* No buffer allocated for the first
781 reply. We can try to use the rest
782 of the user-provided buffer. */
783 #if __GNUC_PREREQ (4, 7)
784 DIAG_PUSH_NEEDS_COMMENT;
785 DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
786 #endif
787 #if _STRING_ARCH_unaligned
788 *anssizp2 = orig_anssizp - resplen;
789 *ansp2 = *ansp + resplen;
790 #else
791 int aligned_resplen
792 = ((resplen + __alignof__ (HEADER) - 1)
793 & ~(__alignof__ (HEADER) - 1));
794 *anssizp2 = orig_anssizp - aligned_resplen;
795 *ansp2 = *ansp + aligned_resplen;
796 #endif
797 #if __GNUC_PREREQ (4, 7)
798 DIAG_POP_NEEDS_COMMENT;
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 = get_nsaddr (statp, ns);
918 socklen_t slen;
920 /* only try IPv6 if IPv6 NS and if not failed before */
921 if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
922 EXT(statp).nssocks[ns]
923 = socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, 0);
924 if (EXT(statp).nssocks[ns] < 0)
925 statp->ipv6_unavail = errno == EAFNOSUPPORT;
926 slen = sizeof (struct sockaddr_in6);
927 } else if (nsap->sa_family == AF_INET) {
928 EXT(statp).nssocks[ns]
929 = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, 0);
930 slen = sizeof (struct sockaddr_in);
932 if (EXT(statp).nssocks[ns] < 0) {
933 *terrno = errno;
934 Perror(statp, stderr, "socket(dg)", errno);
935 return (-1);
939 * On a 4.3BSD+ machine (client and server,
940 * actually), sending to a nameserver datagram
941 * port with no nameserver will cause an
942 * ICMP port unreachable message to be returned.
943 * If our datagram socket is "connected" to the
944 * server, we get an ECONNREFUSED error on the next
945 * socket operation, and select returns if the
946 * error message is received. We can thus detect
947 * the absence of a nameserver without timing out.
949 if (connect(EXT(statp).nssocks[ns], nsap, slen) < 0) {
950 Aerror(statp, stderr, "connect(dg)", errno, nsap);
951 __res_iclose(statp, false);
952 return (0);
956 return 1;
959 static int
960 send_dg(res_state statp,
961 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
962 u_char **ansp, int *anssizp,
963 int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
964 u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
966 const HEADER *hp = (HEADER *) buf;
967 const HEADER *hp2 = (HEADER *) buf2;
968 u_char *ans = *ansp;
969 int orig_anssizp = *anssizp;
970 struct timespec now, timeout, finish;
971 struct pollfd pfd[1];
972 int ptimeout;
973 struct sockaddr_in6 from;
974 int resplen = 0;
975 int n;
978 * Compute time for the total operation.
980 int seconds = (statp->retrans << ns);
981 if (ns > 0)
982 seconds /= statp->nscount;
983 if (seconds <= 0)
984 seconds = 1;
985 bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
986 bool single_request = (((statp->options & RES_SNGLKUP) != 0)
987 | single_request_reopen);
988 int save_gotsomewhere = *gotsomewhere;
990 int retval;
991 retry_reopen:
992 retval = reopen (statp, terrno, ns);
993 if (retval <= 0)
994 return retval;
995 retry:
996 evNowTime(&now);
997 evConsTime(&timeout, seconds, 0);
998 evAddTime(&finish, &now, &timeout);
999 int need_recompute = 0;
1000 int nwritten = 0;
1001 int recvresp1 = 0;
1002 int recvresp2 = buf2 == NULL;
1003 pfd[0].fd = EXT(statp).nssocks[ns];
1004 pfd[0].events = POLLOUT;
1005 if (resplen2 != NULL)
1006 *resplen2 = 0;
1007 wait:
1008 if (need_recompute) {
1009 recompute_resend:
1010 evNowTime(&now);
1011 if (evCmpTime(finish, now) <= 0) {
1012 poll_err_out:
1013 Perror(statp, stderr, "poll", errno);
1014 err_out:
1015 __res_iclose(statp, false);
1016 return (0);
1018 evSubTime(&timeout, &finish, &now);
1019 need_recompute = 0;
1021 /* Convert struct timespec in milliseconds. */
1022 ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
1024 n = 0;
1025 if (nwritten == 0)
1026 n = __poll (pfd, 1, 0);
1027 if (__glibc_unlikely (n == 0)) {
1028 n = __poll (pfd, 1, ptimeout);
1029 need_recompute = 1;
1031 if (n == 0) {
1032 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1033 if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
1035 /* There are quite a few broken name servers out
1036 there which don't handle two outstanding
1037 requests from the same source. There are also
1038 broken firewall settings. If we time out after
1039 having received one answer switch to the mode
1040 where we send the second request only once we
1041 have received the first answer. */
1042 if (!single_request)
1044 statp->options |= RES_SNGLKUP;
1045 single_request = true;
1046 *gotsomewhere = save_gotsomewhere;
1047 goto retry;
1049 else if (!single_request_reopen)
1051 statp->options |= RES_SNGLKUPREOP;
1052 single_request_reopen = true;
1053 *gotsomewhere = save_gotsomewhere;
1054 __res_iclose (statp, false);
1055 goto retry_reopen;
1058 *resplen2 = 1;
1059 return resplen;
1062 *gotsomewhere = 1;
1063 return (0);
1065 if (n < 0) {
1066 if (errno == EINTR)
1067 goto recompute_resend;
1069 goto poll_err_out;
1071 __set_errno (0);
1072 if (pfd[0].revents & POLLOUT) {
1073 #ifndef __ASSUME_SENDMMSG
1074 static int have_sendmmsg;
1075 #else
1076 # define have_sendmmsg 1
1077 #endif
1078 if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL
1079 && !single_request)
1081 struct iovec iov[2];
1082 struct mmsghdr reqs[2];
1083 reqs[0].msg_hdr.msg_name = NULL;
1084 reqs[0].msg_hdr.msg_namelen = 0;
1085 reqs[0].msg_hdr.msg_iov = &iov[0];
1086 reqs[0].msg_hdr.msg_iovlen = 1;
1087 iov[0].iov_base = (void *) buf;
1088 iov[0].iov_len = buflen;
1089 reqs[0].msg_hdr.msg_control = NULL;
1090 reqs[0].msg_hdr.msg_controllen = 0;
1092 reqs[1].msg_hdr.msg_name = NULL;
1093 reqs[1].msg_hdr.msg_namelen = 0;
1094 reqs[1].msg_hdr.msg_iov = &iov[1];
1095 reqs[1].msg_hdr.msg_iovlen = 1;
1096 iov[1].iov_base = (void *) buf2;
1097 iov[1].iov_len = buflen2;
1098 reqs[1].msg_hdr.msg_control = NULL;
1099 reqs[1].msg_hdr.msg_controllen = 0;
1101 int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL);
1102 if (__glibc_likely (ndg == 2))
1104 if (reqs[0].msg_len != buflen
1105 || reqs[1].msg_len != buflen2)
1106 goto fail_sendmmsg;
1108 pfd[0].events = POLLIN;
1109 nwritten += 2;
1111 else if (ndg == 1 && reqs[0].msg_len == buflen)
1112 goto just_one;
1113 else if (ndg < 0 && (errno == EINTR || errno == EAGAIN))
1114 goto recompute_resend;
1115 else
1117 #ifndef __ASSUME_SENDMMSG
1118 if (__glibc_unlikely (have_sendmmsg == 0))
1120 if (ndg < 0 && errno == ENOSYS)
1122 have_sendmmsg = -1;
1123 goto try_send;
1125 have_sendmmsg = 1;
1127 #endif
1129 fail_sendmmsg:
1130 Perror(statp, stderr, "sendmmsg", errno);
1131 goto err_out;
1134 else
1136 ssize_t sr;
1137 #ifndef __ASSUME_SENDMMSG
1138 try_send:
1139 #endif
1140 if (nwritten != 0)
1141 sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
1142 else
1143 sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
1145 if (sr != (nwritten != 0 ? buflen2 : buflen)) {
1146 if (errno == EINTR || errno == EAGAIN)
1147 goto recompute_resend;
1148 Perror(statp, stderr, "send", errno);
1149 goto err_out;
1151 just_one:
1152 if (nwritten != 0 || buf2 == NULL || single_request)
1153 pfd[0].events = POLLIN;
1154 else
1155 pfd[0].events = POLLIN | POLLOUT;
1156 ++nwritten;
1158 goto wait;
1159 } else if (pfd[0].revents & POLLIN) {
1160 int *thisanssizp;
1161 u_char **thisansp;
1162 int *thisresplenp;
1164 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1165 thisanssizp = anssizp;
1166 thisansp = anscp ?: ansp;
1167 assert (anscp != NULL || ansp2 == NULL);
1168 thisresplenp = &resplen;
1169 } else {
1170 if (*anssizp != MAXPACKET) {
1171 /* No buffer allocated for the first
1172 reply. We can try to use the rest
1173 of the user-provided buffer. */
1174 #if _STRING_ARCH_unaligned
1175 *anssizp2 = orig_anssizp - resplen;
1176 *ansp2 = *ansp + resplen;
1177 #else
1178 int aligned_resplen
1179 = ((resplen + __alignof__ (HEADER) - 1)
1180 & ~(__alignof__ (HEADER) - 1));
1181 *anssizp2 = orig_anssizp - aligned_resplen;
1182 *ansp2 = *ansp + aligned_resplen;
1183 #endif
1184 } else {
1185 /* The first reply did not fit into the
1186 user-provided buffer. Maybe the second
1187 answer will. */
1188 *anssizp2 = orig_anssizp;
1189 *ansp2 = *ansp;
1192 thisanssizp = anssizp2;
1193 thisansp = ansp2;
1194 thisresplenp = resplen2;
1197 if (*thisanssizp < MAXPACKET
1198 /* Yes, we test ANSCP here. If we have two buffers
1199 both will be allocatable. */
1200 && anscp
1201 #ifdef FIONREAD
1202 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
1203 || *thisanssizp < *thisresplenp)
1204 #endif
1206 u_char *newp = malloc (MAXPACKET);
1207 if (newp != NULL) {
1208 *anssizp = MAXPACKET;
1209 *thisansp = ans = newp;
1210 if (thisansp == ansp2)
1211 *ansp2_malloced = 1;
1214 HEADER *anhp = (HEADER *) *thisansp;
1215 socklen_t fromlen = sizeof(struct sockaddr_in6);
1216 assert (sizeof(from) <= fromlen);
1217 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1218 *thisanssizp, 0,
1219 (struct sockaddr *)&from, &fromlen);
1220 if (__glibc_unlikely (*thisresplenp <= 0)) {
1221 if (errno == EINTR || errno == EAGAIN) {
1222 need_recompute = 1;
1223 goto wait;
1225 Perror(statp, stderr, "recvfrom", errno);
1226 goto err_out;
1228 *gotsomewhere = 1;
1229 if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
1231 * Undersized message.
1233 Dprint(statp->options & RES_DEBUG,
1234 (stdout, ";; undersized: %d\n",
1235 *thisresplenp));
1236 *terrno = EMSGSIZE;
1237 goto err_out;
1239 if ((recvresp1 || hp->id != anhp->id)
1240 && (recvresp2 || hp2->id != anhp->id)) {
1242 * response from old query, ignore it.
1243 * XXX - potential security hazard could
1244 * be detected here.
1246 DprintQ((statp->options & RES_DEBUG) ||
1247 (statp->pfcode & RES_PRF_REPLY),
1248 (stdout, ";; old answer:\n"),
1249 *thisansp,
1250 (*thisresplenp > *thisanssizp)
1251 ? *thisanssizp : *thisresplenp);
1252 goto wait;
1254 if (!(statp->options & RES_INSECURE1) &&
1255 !res_ourserver_p(statp, &from)) {
1257 * response from wrong server? ignore it.
1258 * XXX - potential security hazard could
1259 * be detected here.
1261 DprintQ((statp->options & RES_DEBUG) ||
1262 (statp->pfcode & RES_PRF_REPLY),
1263 (stdout, ";; not our server:\n"),
1264 *thisansp,
1265 (*thisresplenp > *thisanssizp)
1266 ? *thisanssizp : *thisresplenp);
1267 goto wait;
1269 #ifdef RES_USE_EDNS0
1270 if (anhp->rcode == FORMERR
1271 && (statp->options & RES_USE_EDNS0) != 0U) {
1273 * Do not retry if the server does not understand
1274 * EDNS0. The case has to be captured here, as
1275 * FORMERR packet do not carry query section, hence
1276 * res_queriesmatch() returns 0.
1278 DprintQ(statp->options & RES_DEBUG,
1279 (stdout,
1280 "server rejected query with EDNS0:\n"),
1281 *thisansp,
1282 (*thisresplenp > *thisanssizp)
1283 ? *thisanssizp : *thisresplenp);
1284 /* record the error */
1285 statp->_flags |= RES_F_EDNS0ERR;
1286 goto err_out;
1288 #endif
1289 if (!(statp->options & RES_INSECURE2)
1290 && (recvresp1 || !res_queriesmatch(buf, buf + buflen,
1291 *thisansp,
1292 *thisansp
1293 + *thisanssizp))
1294 && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
1295 *thisansp,
1296 *thisansp
1297 + *thisanssizp))) {
1299 * response contains wrong query? ignore it.
1300 * XXX - potential security hazard could
1301 * be detected here.
1303 DprintQ((statp->options & RES_DEBUG) ||
1304 (statp->pfcode & RES_PRF_REPLY),
1305 (stdout, ";; wrong query name:\n"),
1306 *thisansp,
1307 (*thisresplenp > *thisanssizp)
1308 ? *thisanssizp : *thisresplenp);
1309 goto wait;
1311 if (anhp->rcode == SERVFAIL ||
1312 anhp->rcode == NOTIMP ||
1313 anhp->rcode == REFUSED) {
1314 DprintQ(statp->options & RES_DEBUG,
1315 (stdout, "server rejected query:\n"),
1316 *thisansp,
1317 (*thisresplenp > *thisanssizp)
1318 ? *thisanssizp : *thisresplenp);
1320 next_ns:
1321 if (recvresp1 || (buf2 != NULL && recvresp2)) {
1322 *resplen2 = 0;
1323 return resplen;
1325 if (buf2 != NULL)
1327 /* No data from the first reply. */
1328 resplen = 0;
1329 /* We are waiting for a possible second reply. */
1330 if (hp->id == anhp->id)
1331 recvresp1 = 1;
1332 else
1333 recvresp2 = 1;
1335 goto wait;
1338 __res_iclose(statp, false);
1339 /* don't retry if called from dig */
1340 if (!statp->pfcode)
1341 return (0);
1343 if (anhp->rcode == NOERROR && anhp->ancount == 0
1344 && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
1345 DprintQ(statp->options & RES_DEBUG,
1346 (stdout, "referred query:\n"),
1347 *thisansp,
1348 (*thisresplenp > *thisanssizp)
1349 ? *thisanssizp : *thisresplenp);
1350 goto next_ns;
1352 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1354 * To get the rest of answer,
1355 * use TCP with same server.
1357 Dprint(statp->options & RES_DEBUG,
1358 (stdout, ";; truncated answer\n"));
1359 *v_circuit = 1;
1360 __res_iclose(statp, false);
1361 // XXX if we have received one reply we could
1362 // XXX use it and not repeat it over TCP...
1363 return (1);
1365 /* Mark which reply we received. */
1366 if (recvresp1 == 0 && hp->id == anhp->id)
1367 recvresp1 = 1;
1368 else
1369 recvresp2 = 1;
1370 /* Repeat waiting if we have a second answer to arrive. */
1371 if ((recvresp1 & recvresp2) == 0) {
1372 if (single_request) {
1373 pfd[0].events = POLLOUT;
1374 if (single_request_reopen) {
1375 __res_iclose (statp, false);
1376 retval = reopen (statp, terrno, ns);
1377 if (retval <= 0)
1378 return retval;
1379 pfd[0].fd = EXT(statp).nssocks[ns];
1382 goto wait;
1385 * All is well, or the error is fatal. Signal that the
1386 * next nameserver ought not be tried.
1388 return (resplen);
1389 } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
1390 /* Something went wrong. We can stop trying. */
1391 goto err_out;
1393 else {
1394 /* poll should not have returned > 0 in this case. */
1395 abort ();
1399 #ifdef DEBUG
1400 static void
1401 Aerror(const res_state statp, FILE *file, const char *string, int error,
1402 const struct sockaddr *address)
1404 int save = errno;
1406 if ((statp->options & RES_DEBUG) != 0) {
1407 char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
1409 fprintf(file, "res_send: %s ([%s].%u): %s\n",
1410 string,
1411 (address->sa_family == AF_INET
1412 ? inet_ntop(address->sa_family,
1413 &((const struct sockaddr_in *) address)->sin_addr,
1414 tmp, sizeof tmp)
1415 : inet_ntop(address->sa_family,
1416 &((const struct sockaddr_in6 *) address)->sin6_addr,
1417 tmp, sizeof tmp)),
1418 (address->sa_family == AF_INET
1419 ? ntohs(((struct sockaddr_in *) address)->sin_port)
1420 : address->sa_family == AF_INET6
1421 ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
1422 : 0),
1423 strerror(error));
1425 __set_errno (save);
1428 static void
1429 Perror(const res_state statp, FILE *file, const char *string, int error) {
1430 int save = errno;
1432 if ((statp->options & RES_DEBUG) != 0)
1433 fprintf(file, "res_send: %s: %s\n",
1434 string, strerror(error));
1435 __set_errno (save);
1437 #endif
1439 static int
1440 sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
1441 if (a1->sin6_family == a2->sin6_family) {
1442 if (a1->sin6_family == AF_INET)
1443 return ((((struct sockaddr_in *)a1)->sin_port ==
1444 ((struct sockaddr_in *)a2)->sin_port) &&
1445 (((struct sockaddr_in *)a1)->sin_addr.s_addr ==
1446 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1447 else
1448 return ((a1->sin6_port == a2->sin6_port) &&
1449 !memcmp(&a1->sin6_addr, &a2->sin6_addr,
1450 sizeof (struct in6_addr)));
1452 if (a1->sin6_family == AF_INET) {
1453 struct sockaddr_in6 *sap = a1;
1454 a1 = a2;
1455 a2 = sap;
1456 } /* assumes that AF_INET and AF_INET6 are the only possibilities */
1457 return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) &&
1458 IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) &&
1459 (a1->sin6_addr.s6_addr32[3] ==
1460 ((struct sockaddr_in *)a2)->sin_addr.s_addr));