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