2.9
[glibc/nacl-glibc.git] / resolv / res_send.c
blobac5cc0b4fe6af26d414d4fbd6eb926c7c2ceeb83
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>
99 #if PACKETSZ > 65536
100 #define MAXPACKET PACKETSZ
101 #else
102 #define MAXPACKET 65536
103 #endif
106 /* From ev_streams.c. */
108 static inline void
109 __attribute ((always_inline))
110 evConsIovec(void *buf, size_t cnt, struct iovec *vec) {
111 memset(vec, 0xf5, sizeof (*vec));
112 vec->iov_base = buf;
113 vec->iov_len = cnt;
116 /* From ev_timers.c. */
118 #define BILLION 1000000000
120 static inline void
121 evConsTime(struct timespec *res, time_t sec, long nsec) {
122 res->tv_sec = sec;
123 res->tv_nsec = nsec;
126 static inline void
127 evAddTime(struct timespec *res, const struct timespec *addend1,
128 const struct timespec *addend2) {
129 res->tv_sec = addend1->tv_sec + addend2->tv_sec;
130 res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec;
131 if (res->tv_nsec >= BILLION) {
132 res->tv_sec++;
133 res->tv_nsec -= BILLION;
137 static inline void
138 evSubTime(struct timespec *res, const struct timespec *minuend,
139 const struct timespec *subtrahend) {
140 res->tv_sec = minuend->tv_sec - subtrahend->tv_sec;
141 if (minuend->tv_nsec >= subtrahend->tv_nsec)
142 res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec;
143 else {
144 res->tv_nsec = (BILLION
145 - subtrahend->tv_nsec + minuend->tv_nsec);
146 res->tv_sec--;
150 static inline int
151 evCmpTime(struct timespec a, struct timespec b) {
152 long x = a.tv_sec - b.tv_sec;
154 if (x == 0L)
155 x = a.tv_nsec - b.tv_nsec;
156 return (x < 0L ? (-1) : x > 0L ? (1) : (0));
159 static inline void
160 evNowTime(struct timespec *res) {
161 struct timeval now;
163 if (gettimeofday(&now, NULL) < 0)
164 evConsTime(res, 0, 0);
165 else
166 TIMEVAL_TO_TIMESPEC (&now, res);
170 /* Options. Leave them on. */
171 /* #undef DEBUG */
172 #include "res_debug.h"
174 #define EXT(res) ((res)->_u._ext)
176 /* Forward. */
178 static int send_vc(res_state, const u_char *, int,
179 const u_char *, int,
180 u_char **, int *, int *, int, u_char **,
181 u_char **, int *, int *);
182 static int send_dg(res_state, const u_char *, int,
183 const u_char *, int,
184 u_char **, int *, int *, int,
185 int *, int *, u_char **,
186 u_char **, int *, int *);
187 #ifdef DEBUG
188 static void Aerror(const res_state, FILE *, const char *, int,
189 const struct sockaddr *);
190 static void Perror(const res_state, FILE *, const char *, int);
191 #endif
192 static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
194 /* Reachover. */
196 static void convaddr4to6(struct sockaddr_in6 *sa);
198 /* Public. */
200 /* int
201 * res_isourserver(ina)
202 * looks up "ina" in _res.ns_addr_list[]
203 * returns:
204 * 0 : not found
205 * >0 : found
206 * author:
207 * paul vixie, 29may94
210 res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
212 int ns;
214 if (inp->sin6_family == AF_INET) {
215 struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
216 in_port_t port = in4p->sin_port;
217 in_addr_t addr = in4p->sin_addr.s_addr;
219 for (ns = 0; ns < MAXNS; ns++) {
220 const struct sockaddr_in *srv =
221 (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
223 if ((srv != NULL) && (srv->sin_family == AF_INET) &&
224 (srv->sin_port == port) &&
225 (srv->sin_addr.s_addr == INADDR_ANY ||
226 srv->sin_addr.s_addr == addr))
227 return (1);
229 } else if (inp->sin6_family == AF_INET6) {
230 for (ns = 0; ns < MAXNS; ns++) {
231 const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
232 if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
233 (srv->sin6_port == inp->sin6_port) &&
234 !(memcmp(&srv->sin6_addr, &in6addr_any,
235 sizeof (struct in6_addr)) &&
236 memcmp(&srv->sin6_addr, &inp->sin6_addr,
237 sizeof (struct in6_addr))))
238 return (1);
241 return (0);
244 /* int
245 * res_nameinquery(name, type, class, buf, eom)
246 * look for (name,type,class) in the query section of packet (buf,eom)
247 * requires:
248 * buf + HFIXEDSZ <= eom
249 * returns:
250 * -1 : format error
251 * 0 : not found
252 * >0 : found
253 * author:
254 * paul vixie, 29may94
257 res_nameinquery(const char *name, int type, int class,
258 const u_char *buf, const u_char *eom)
260 const u_char *cp = buf + HFIXEDSZ;
261 int qdcount = ntohs(((HEADER*)buf)->qdcount);
263 while (qdcount-- > 0) {
264 char tname[MAXDNAME+1];
265 int n, ttype, tclass;
267 n = dn_expand(buf, eom, cp, tname, sizeof tname);
268 if (n < 0)
269 return (-1);
270 cp += n;
271 if (cp + 2 * INT16SZ > eom)
272 return (-1);
273 NS_GET16(ttype, cp);
274 NS_GET16(tclass, cp);
275 if (ttype == type && tclass == class &&
276 ns_samename(tname, name) == 1)
277 return (1);
279 return (0);
281 libresolv_hidden_def (res_nameinquery)
283 /* int
284 * res_queriesmatch(buf1, eom1, buf2, eom2)
285 * is there a 1:1 mapping of (name,type,class)
286 * in (buf1,eom1) and (buf2,eom2)?
287 * returns:
288 * -1 : format error
289 * 0 : not a 1:1 mapping
290 * >0 : is a 1:1 mapping
291 * author:
292 * paul vixie, 29may94
295 res_queriesmatch(const u_char *buf1, const u_char *eom1,
296 const u_char *buf2, const u_char *eom2)
298 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
299 return (-1);
302 * Only header section present in replies to
303 * dynamic update packets.
305 if ((((HEADER *)buf1)->opcode == ns_o_update) &&
306 (((HEADER *)buf2)->opcode == ns_o_update))
307 return (1);
309 /* Note that we initially do not convert QDCOUNT to the host byte
310 order. We can compare it with the second buffer's QDCOUNT
311 value without doing this. */
312 int qdcount = ((HEADER*)buf1)->qdcount;
313 if (qdcount != ((HEADER*)buf2)->qdcount)
314 return (0);
316 qdcount = htons (qdcount);
317 const u_char *cp = buf1 + HFIXEDSZ;
319 while (qdcount-- > 0) {
320 char tname[MAXDNAME+1];
321 int n, ttype, tclass;
323 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
324 if (n < 0)
325 return (-1);
326 cp += n;
327 if (cp + 2 * INT16SZ > eom1)
328 return (-1);
329 NS_GET16(ttype, cp);
330 NS_GET16(tclass, cp);
331 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
332 return (0);
334 return (1);
336 libresolv_hidden_def (res_queriesmatch)
339 __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
340 const u_char *buf2, int buflen2,
341 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
342 int *nansp2, int *resplen2)
344 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
346 if (statp->nscount == 0) {
347 __set_errno (ESRCH);
348 return (-1);
351 if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) {
352 __set_errno (EINVAL);
353 return (-1);
356 #ifdef USE_HOOKS
357 if (__builtin_expect (statp->qhook || statp->rhook, 0)) {
358 if (anssiz < MAXPACKET && ansp) {
359 u_char *buf = malloc (MAXPACKET);
360 if (buf == NULL)
361 return (-1);
362 memcpy (buf, ans, HFIXEDSZ);
363 *ansp = buf;
364 ans = buf;
365 anssiz = MAXPACKET;
368 #endif
370 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
371 (stdout, ";; res_send()\n"), buf, buflen);
372 v_circuit = ((statp->options & RES_USEVC)
373 || buflen > PACKETSZ
374 || buflen2 > PACKETSZ);
375 gotsomewhere = 0;
376 terrno = ETIMEDOUT;
379 * If the ns_addr_list in the resolver context has changed, then
380 * invalidate our cached copy and the associated timing data.
382 if (EXT(statp).nsinit) {
383 int needclose = 0;
385 if (EXT(statp).nscount != statp->nscount)
386 needclose++;
387 else
388 for (ns = 0; ns < MAXNS; ns++) {
389 unsigned int map = EXT(statp).nsmap[ns];
390 if (map < MAXNS
391 && !sock_eq((struct sockaddr_in6 *)
392 &statp->nsaddr_list[map],
393 EXT(statp).nsaddrs[ns]))
395 needclose++;
396 break;
399 if (needclose)
400 __res_iclose(statp, false);
404 * Maybe initialize our private copy of the ns_addr_list.
406 if (EXT(statp).nsinit == 0) {
407 unsigned char map[MAXNS];
409 memset (map, MAXNS, sizeof (map));
410 for (n = 0; n < MAXNS; n++) {
411 ns = EXT(statp).nsmap[n];
412 if (ns < statp->nscount)
413 map[ns] = n;
414 else if (ns < MAXNS) {
415 free(EXT(statp).nsaddrs[n]);
416 EXT(statp).nsaddrs[n] = NULL;
417 EXT(statp).nsmap[n] = MAXNS;
420 n = statp->nscount;
421 if (statp->nscount > EXT(statp).nscount)
422 for (n = EXT(statp).nscount, ns = 0;
423 n < statp->nscount; n++) {
424 while (ns < MAXNS
425 && EXT(statp).nsmap[ns] != MAXNS)
426 ns++;
427 if (ns == MAXNS)
428 break;
429 EXT(statp).nsmap[ns] = n;
430 map[n] = ns++;
432 EXT(statp).nscount = n;
433 for (ns = 0; ns < EXT(statp).nscount; ns++) {
434 n = map[ns];
435 if (EXT(statp).nsaddrs[n] == NULL)
436 EXT(statp).nsaddrs[n] =
437 malloc(sizeof (struct sockaddr_in6));
438 if (EXT(statp).nsaddrs[n] != NULL) {
439 memset (mempcpy(EXT(statp).nsaddrs[n],
440 &statp->nsaddr_list[ns],
441 sizeof (struct sockaddr_in)),
442 '\0',
443 sizeof (struct sockaddr_in6)
444 - sizeof (struct sockaddr_in));
445 EXT(statp).nssocks[n] = -1;
446 n++;
449 EXT(statp).nsinit = 1;
453 * Some resolvers want to even out the load on their nameservers.
454 * Note that RES_BLAST overrides RES_ROTATE.
456 if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
457 (statp->options & RES_BLAST) == 0) {
458 struct sockaddr_in6 *ina;
459 unsigned int map;
461 n = 0;
462 while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
463 n++;
464 if (n < MAXNS) {
465 ina = EXT(statp).nsaddrs[n];
466 map = EXT(statp).nsmap[n];
467 for (;;) {
468 ns = n + 1;
469 while (ns < MAXNS
470 && EXT(statp).nsmap[ns] == MAXNS)
471 ns++;
472 if (ns == MAXNS)
473 break;
474 EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
475 EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
476 n = ns;
478 EXT(statp).nsaddrs[n] = ina;
479 EXT(statp).nsmap[n] = map;
484 * Send request, RETRY times, or until successful.
486 for (try = 0; try < statp->retry; try++) {
487 for (ns = 0; ns < MAXNS; ns++)
489 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
491 if (nsap == NULL)
492 goto next_ns;
493 same_ns:
494 #ifdef USE_HOOKS
495 if (__builtin_expect (statp->qhook != NULL, 0)) {
496 int done = 0, loops = 0;
498 do {
499 res_sendhookact act;
501 struct sockaddr_in *nsap4;
502 nsap4 = (struct sockaddr_in *) nsap;
503 act = (*statp->qhook)(&nsap4, &buf, &buflen,
504 ans, anssiz, &resplen);
505 nsap = (struct sockaddr_in6 *) nsap4;
506 switch (act) {
507 case res_goahead:
508 done = 1;
509 break;
510 case res_nextns:
511 __res_iclose(statp, false);
512 goto next_ns;
513 case res_done:
514 return (resplen);
515 case res_modified:
516 /* give the hook another try */
517 if (++loops < 42) /*doug adams*/
518 break;
519 /*FALLTHROUGH*/
520 case res_error:
521 /*FALLTHROUGH*/
522 default:
523 return (-1);
525 } while (!done);
527 #endif
529 #ifdef DEBUG
530 char tmpbuf[40];
531 #endif
532 Dprint(statp->options & RES_DEBUG,
533 (stdout, ";; Querying server (# %d) address = %s\n",
534 ns + 1, inet_ntop(AF_INET6, &nsap->sin6_addr,
535 tmpbuf, sizeof (tmpbuf))));
537 if (__builtin_expect (v_circuit, 0)) {
538 /* Use VC; at most one attempt per server. */
539 try = statp->retry;
540 n = send_vc(statp, buf, buflen, buf2, buflen2,
541 &ans, &anssiz, &terrno,
542 ns, ansp, ansp2, nansp2, resplen2);
543 if (n < 0)
544 return (-1);
545 if (n == 0)
546 goto next_ns;
547 } else {
548 /* Use datagrams. */
549 n = send_dg(statp, buf, buflen, buf2, buflen2,
550 &ans, &anssiz, &terrno,
551 ns, &v_circuit, &gotsomewhere, ansp,
552 ansp2, nansp2, resplen2);
553 if (n < 0)
554 return (-1);
555 if (n == 0)
556 goto next_ns;
557 if (v_circuit)
558 // XXX Check whether both requests failed or
559 // XXX whether one has been answered successfully
560 goto same_ns;
563 resplen = n;
565 Dprint((statp->options & RES_DEBUG) ||
566 ((statp->pfcode & RES_PRF_REPLY) &&
567 (statp->pfcode & RES_PRF_HEAD1)),
568 (stdout, ";; got answer:\n"));
570 DprintQ((statp->options & RES_DEBUG) ||
571 (statp->pfcode & RES_PRF_REPLY),
572 (stdout, "%s", ""),
573 ans, (resplen > anssiz) ? anssiz : resplen);
574 if (buf2 != NULL)
575 DprintQ((statp->options & RES_DEBUG) ||
576 (statp->pfcode & RES_PRF_REPLY),
577 (stdout, "%s", ""),
578 *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
581 * If we have temporarily opened a virtual circuit,
582 * or if we haven't been asked to keep a socket open,
583 * close the socket.
585 if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
586 (statp->options & RES_STAYOPEN) == 0) {
587 __res_iclose(statp, false);
589 #ifdef USE_HOOKS
590 if (__builtin_expect (statp->rhook, 0)) {
591 int done = 0, loops = 0;
593 do {
594 res_sendhookact act;
596 act = (*statp->rhook)((struct sockaddr_in *)
597 nsap, buf, buflen,
598 ans, anssiz, &resplen);
599 switch (act) {
600 case res_goahead:
601 case res_done:
602 done = 1;
603 break;
604 case res_nextns:
605 __res_iclose(statp, false);
606 goto next_ns;
607 case res_modified:
608 /* give the hook another try */
609 if (++loops < 42) /*doug adams*/
610 break;
611 /*FALLTHROUGH*/
612 case res_error:
613 /*FALLTHROUGH*/
614 default:
615 return (-1);
617 } while (!done);
620 #endif
621 return (resplen);
622 next_ns: ;
623 } /*foreach ns*/
624 } /*foreach retry*/
625 __res_iclose(statp, false);
626 if (!v_circuit) {
627 if (!gotsomewhere)
628 __set_errno (ECONNREFUSED); /* no nameservers found */
629 else
630 __set_errno (ETIMEDOUT); /* no answer obtained */
631 } else
632 __set_errno (terrno);
633 return (-1);
637 res_nsend(res_state statp,
638 const u_char *buf, int buflen, u_char *ans, int anssiz)
640 return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
641 NULL, NULL, NULL, NULL);
643 libresolv_hidden_def (res_nsend)
645 /* Private */
647 static int
648 send_vc(res_state statp,
649 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
650 u_char **ansp, int *anssizp,
651 int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
652 int *resplen2)
654 const HEADER *hp = (HEADER *) buf;
655 const HEADER *hp2 = (HEADER *) buf2;
656 u_char *ans = *ansp;
657 int orig_anssizp = *anssizp;
658 // XXX REMOVE
659 // int anssiz = *anssizp;
660 HEADER *anhp = (HEADER *) ans;
661 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
662 int truncating, connreset, resplen, n;
663 struct iovec iov[4];
664 u_short len;
665 u_short len2;
666 u_char *cp;
668 if (resplen2 != NULL)
669 *resplen2 = 0;
670 connreset = 0;
671 same_ns:
672 truncating = 0;
674 /* Are we still talking to whom we want to talk to? */
675 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
676 struct sockaddr_in6 peer;
677 socklen_t size = sizeof peer;
679 if (getpeername(statp->_vcsock,
680 (struct sockaddr *)&peer, &size) < 0 ||
681 !sock_eq(&peer, nsap)) {
682 __res_iclose(statp, false);
683 statp->_flags &= ~RES_F_VC;
687 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
688 if (statp->_vcsock >= 0)
689 __res_iclose(statp, false);
691 statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0);
692 if (statp->_vcsock < 0) {
693 *terrno = errno;
694 Perror(statp, stderr, "socket(vc)", errno);
695 return (-1);
697 __set_errno (0);
698 if (connect(statp->_vcsock, (struct sockaddr *)nsap,
699 nsap->sin6_family == AF_INET
700 ? sizeof (struct sockaddr_in)
701 : sizeof (struct sockaddr_in6)) < 0) {
702 *terrno = errno;
703 Aerror(statp, stderr, "connect/vc", errno,
704 (struct sockaddr *) nsap);
705 __res_iclose(statp, false);
706 return (0);
708 statp->_flags |= RES_F_VC;
712 * Send length & message
714 len = htons ((u_short) buflen);
715 evConsIovec(&len, INT16SZ, &iov[0]);
716 evConsIovec((void*)buf, buflen, &iov[1]);
717 int niov = 2;
718 ssize_t explen = INT16SZ + buflen;
719 if (buf2 != NULL) {
720 len2 = htons ((u_short) buflen2);
721 evConsIovec(&len2, INT16SZ, &iov[2]);
722 evConsIovec((void*)buf2, buflen2, &iov[3]);
723 niov = 4;
724 explen += INT16SZ + buflen2;
726 if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
727 *terrno = errno;
728 Perror(statp, stderr, "write failed", errno);
729 __res_iclose(statp, false);
730 return (0);
733 * Receive length & response
735 int recvresp1 = 0;
736 int recvresp2 = buf2 == NULL;
737 uint16_t rlen16;
738 read_len:
739 cp = (u_char *)&rlen16;
740 len = sizeof(rlen16);
741 while ((n = TEMP_FAILURE_RETRY (read(statp->_vcsock, cp,
742 (int)len))) > 0) {
743 cp += n;
744 if ((len -= n) <= 0)
745 break;
747 if (n <= 0) {
748 *terrno = errno;
749 Perror(statp, stderr, "read failed", errno);
750 __res_iclose(statp, false);
752 * A long running process might get its TCP
753 * connection reset if the remote server was
754 * restarted. Requery the server instead of
755 * trying a new one. When there is only one
756 * server, this means that a query might work
757 * instead of failing. We only allow one reset
758 * per query to prevent looping.
760 if (*terrno == ECONNRESET && !connreset) {
761 connreset = 1;
762 goto same_ns;
764 return (0);
766 int rlen = ntohs (rlen16);
768 int *thisanssizp;
769 u_char **thisansp;
770 int *thisresplenp;
771 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
772 thisanssizp = anssizp;
773 thisansp = anscp ?: ansp;
774 assert (anscp != NULL || ansp2 == NULL);
775 thisresplenp = &resplen;
776 } else {
777 if (*anssizp != MAXPACKET) {
778 /* No buffer allocated for the first
779 reply. We can try to use the rest
780 of the user-provided buffer. */
781 #ifdef _STRING_ARCH_unaligned
782 *anssizp2 = orig_anssizp - resplen;
783 *ansp2 = *ansp + resplen;
784 #else
785 int aligned_resplen
786 = ((resplen + __alignof__ (HEADER) - 1)
787 & ~(__alignof__ (HEADER) - 1));
788 *anssizp2 = orig_anssizp - aligned_resplen;
789 *ansp2 = *ansp + aligned_resplen;
790 #endif
791 } else {
792 /* The first reply did not fit into the
793 user-provided buffer. Maybe the second
794 answer will. */
795 *anssizp2 = orig_anssizp;
796 *ansp2 = *ansp;
799 thisanssizp = anssizp2;
800 thisansp = ansp2;
801 thisresplenp = resplen2;
803 anhp = (HEADER *) *thisansp;
805 *thisresplenp = rlen;
806 if (rlen > *thisanssizp) {
807 /* Yes, we test ANSCP here. If we have two buffers
808 both will be allocatable. */
809 if (__builtin_expect (anscp != NULL, 1)) {
810 u_char *newp = malloc (MAXPACKET);
811 if (newp == NULL) {
812 *terrno = ENOMEM;
813 __res_iclose(statp, false);
814 return (0);
816 *thisanssizp = MAXPACKET;
817 *thisansp = newp;
818 anhp = (HEADER *) newp;
819 len = rlen;
820 } else {
821 Dprint(statp->options & RES_DEBUG,
822 (stdout, ";; response truncated\n")
824 truncating = 1;
825 len = *thisanssizp;
827 } else
828 len = rlen;
830 if (__builtin_expect (len < HFIXEDSZ, 0)) {
832 * Undersized message.
834 Dprint(statp->options & RES_DEBUG,
835 (stdout, ";; undersized: %d\n", len));
836 *terrno = EMSGSIZE;
837 __res_iclose(statp, false);
838 return (0);
841 cp = *thisansp;
842 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
843 cp += n;
844 len -= n;
846 if (__builtin_expect (n <= 0, 0)) {
847 *terrno = errno;
848 Perror(statp, stderr, "read(vc)", errno);
849 __res_iclose(statp, false);
850 return (0);
852 if (__builtin_expect (truncating, 0)) {
854 * Flush rest of answer so connection stays in synch.
856 anhp->tc = 1;
857 len = rlen - *thisanssizp;
858 while (len != 0) {
859 char junk[PACKETSZ];
861 n = read(statp->_vcsock, junk,
862 (len > sizeof junk) ? sizeof junk : len);
863 if (n > 0)
864 len -= n;
865 else
866 break;
870 * If the calling applicating has bailed out of
871 * a previous call and failed to arrange to have
872 * the circuit closed or the server has got
873 * itself confused, then drop the packet and
874 * wait for the correct one.
876 if ((recvresp1 || hp->id != anhp->id)
877 && (recvresp2 || hp2->id != anhp->id)) {
878 DprintQ((statp->options & RES_DEBUG) ||
879 (statp->pfcode & RES_PRF_REPLY),
880 (stdout, ";; old answer (unexpected):\n"),
881 *thisansp,
882 (rlen > *thisanssiz) ? *thisanssiz: rlen);
883 goto read_len;
886 /* Mark which reply we received. */
887 if (recvresp1 == 0 && hp->id == anhp->id)
888 recvresp1 = 1;
889 else
890 recvresp2 = 1;
891 /* Repeat waiting if we have a second answer to arrive. */
892 if ((recvresp1 & recvresp2) == 0)
893 goto read_len;
896 * All is well, or the error is fatal. Signal that the
897 * next nameserver ought not be tried.
899 return resplen;
902 static int
903 send_dg(res_state statp,
904 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
905 u_char **ansp, int *anssizp,
906 int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
907 u_char **ansp2, int *anssizp2, int *resplen2)
909 const HEADER *hp = (HEADER *) buf;
910 const HEADER *hp2 = (HEADER *) buf2;
911 u_char *ans = *ansp;
912 int orig_anssizp = *anssizp;
913 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
914 struct timespec now, timeout, finish;
915 struct pollfd pfd[1];
916 int ptimeout;
917 struct sockaddr_in6 from;
918 int resplen, seconds, n;
920 if (EXT(statp).nssocks[ns] == -1) {
921 /* only try IPv6 if IPv6 NS and if not failed before */
922 if ((EXT(statp).nscount6 > 0) && !statp->ipv6_unavail) {
923 EXT(statp).nssocks[ns] =
924 socket(PF_INET6, SOCK_DGRAM, 0);
925 if (EXT(statp).nssocks[ns] < 0)
926 statp->ipv6_unavail = errno == EAFNOSUPPORT;
927 /* If IPv6 socket and nsap is IPv4, make it
928 IPv4-mapped */
929 else if (nsap->sin6_family == AF_INET)
930 convaddr4to6(nsap);
932 if (EXT(statp).nssocks[ns] < 0)
933 EXT(statp).nssocks[ns] = socket(PF_INET, SOCK_DGRAM, 0);
934 if (EXT(statp).nssocks[ns] < 0) {
935 *terrno = errno;
936 Perror(statp, stderr, "socket(dg)", errno);
937 return (-1);
941 * On a 4.3BSD+ machine (client and server,
942 * actually), sending to a nameserver datagram
943 * port with no nameserver will cause an
944 * ICMP port unreachable message to be returned.
945 * If our datagram socket is "connected" to the
946 * server, we get an ECONNREFUSED error on the next
947 * socket operation, and select returns if the
948 * error message is received. We can thus detect
949 * the absence of a nameserver without timing out.
951 if (connect(EXT(statp).nssocks[ns], (struct sockaddr *)nsap,
952 sizeof *nsap) < 0) {
953 Aerror(statp, stderr, "connect(dg)", errno,
954 (struct sockaddr *) nsap);
955 __res_iclose(statp, false);
956 return (0);
958 /* Make socket non-blocking. */
959 int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL);
960 if (fl != -1)
961 __fcntl (EXT(statp).nssocks[ns], F_SETFL,
962 fl | O_NONBLOCK);
963 Dprint(statp->options & RES_DEBUG,
964 (stdout, ";; new DG socket\n"))
968 * Compute time for the total operation.
970 seconds = (statp->retrans << ns);
971 if (ns > 0)
972 seconds /= statp->nscount;
973 if (seconds <= 0)
974 seconds = 1;
975 evNowTime(&now);
976 evConsTime(&timeout, seconds, 0);
977 evAddTime(&finish, &now, &timeout);
978 int need_recompute = 0;
979 int nwritten = 0;
980 int recvresp1 = 0;
981 int recvresp2 = buf2 == NULL;
982 pfd[0].fd = EXT(statp).nssocks[ns];
983 pfd[0].events = POLLOUT;
984 if (resplen2 != NULL)
985 *resplen2 = 0;
986 wait:
987 if (need_recompute) {
988 recompute_resend:
989 evNowTime(&now);
990 if (evCmpTime(finish, now) <= 0) {
991 poll_err_out:
992 Perror(statp, stderr, "poll", errno);
993 err_out:
994 __res_iclose(statp, false);
995 return (0);
997 evSubTime(&timeout, &finish, &now);
999 /* Convert struct timespec in milliseconds. */
1000 ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
1002 n = 0;
1003 if (nwritten == 0)
1004 n = __poll (pfd, 1, 0);
1005 if (__builtin_expect (n == 0, 0)) {
1006 n = __poll (pfd, 1, ptimeout);
1007 need_recompute = 1;
1009 if (n == 0) {
1010 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1011 if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
1013 *resplen2 = 1;
1014 return resplen;
1017 *gotsomewhere = 1;
1018 return (0);
1020 if (n < 0) {
1021 if (errno == EINTR)
1022 goto recompute_resend;
1024 goto poll_err_out;
1026 __set_errno (0);
1027 if (pfd[0].revents & POLLOUT) {
1028 ssize_t sr;
1029 if (nwritten != 0)
1030 sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
1031 else
1032 sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
1034 if (sr != buflen) {
1035 if (errno == EINTR || errno == EAGAIN)
1036 goto recompute_resend;
1037 Perror(statp, stderr, "send", errno);
1038 goto err_out;
1040 if (nwritten != 0 || buf2 == NULL)
1041 pfd[0].events = POLLIN;
1042 else
1043 pfd[0].events = POLLIN | POLLOUT;
1044 ++nwritten;
1045 goto wait;
1046 } else if (pfd[0].revents & POLLIN) {
1047 int *thisanssizp;
1048 u_char **thisansp;
1049 int *thisresplenp;
1051 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1052 thisanssizp = anssizp;
1053 thisansp = anscp ?: ansp;
1054 assert (anscp != NULL || ansp2 == NULL);
1055 thisresplenp = &resplen;
1056 } else {
1057 if (*anssizp != MAXPACKET) {
1058 /* No buffer allocated for the first
1059 reply. We can try to use the rest
1060 of the user-provided buffer. */
1061 #ifdef _STRING_ARCH_unaligned
1062 *anssizp2 = orig_anssizp - resplen;
1063 *ansp2 = *ansp + resplen;
1064 #else
1065 int aligned_resplen
1066 = ((resplen + __alignof__ (HEADER) - 1)
1067 & ~(__alignof__ (HEADER) - 1));
1068 *anssizp2 = orig_anssizp - aligned_resplen;
1069 *ansp2 = *ansp + aligned_resplen;
1070 #endif
1071 } else {
1072 /* The first reply did not fit into the
1073 user-provided buffer. Maybe the second
1074 answer will. */
1075 *anssizp2 = orig_anssizp;
1076 *ansp2 = *ansp;
1079 thisanssizp = anssizp2;
1080 thisansp = ansp2;
1081 thisresplenp = resplen2;
1084 if (*thisanssizp < MAXPACKET
1085 /* Yes, we test ANSCP here. If we have two buffers
1086 both will be allocatable. */
1087 && anscp
1088 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
1089 || *thisanssizp < *thisresplenp)) {
1090 u_char *newp = malloc (MAXPACKET);
1091 if (newp != NULL) {
1092 *anssizp = MAXPACKET;
1093 *thisansp = ans = newp;
1096 HEADER *anhp = (HEADER *) *thisansp;
1097 socklen_t fromlen = sizeof(struct sockaddr_in6);
1098 assert (sizeof(from) <= fromlen);
1099 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1100 *thisanssizp, 0,
1101 (struct sockaddr *)&from, &fromlen);
1102 if (__builtin_expect (*thisresplenp <= 0, 0)) {
1103 if (errno == EINTR || errno == EAGAIN) {
1104 need_recompute = 1;
1105 goto wait;
1107 Perror(statp, stderr, "recvfrom", errno);
1108 goto err_out;
1110 *gotsomewhere = 1;
1111 if (__builtin_expect (*thisresplenp < HFIXEDSZ, 0)) {
1113 * Undersized message.
1115 Dprint(statp->options & RES_DEBUG,
1116 (stdout, ";; undersized: %d\n",
1117 *thisresplen));
1118 *terrno = EMSGSIZE;
1119 goto err_out;
1121 if ((recvresp1 || hp->id != anhp->id)
1122 && (recvresp2 || hp2->id != anhp->id)) {
1124 * response from old query, ignore it.
1125 * XXX - potential security hazard could
1126 * be detected here.
1128 DprintQ((statp->options & RES_DEBUG) ||
1129 (statp->pfcode & RES_PRF_REPLY),
1130 (stdout, ";; old answer:\n"),
1131 thisansp,
1132 (*thisresplen > *thisanssiz)
1133 ? *thisanssiz : *thisresplen);
1134 goto wait;
1136 if (!(statp->options & RES_INSECURE1) &&
1137 !res_ourserver_p(statp, &from)) {
1139 * response from wrong server? ignore it.
1140 * XXX - potential security hazard could
1141 * be detected here.
1143 DprintQ((statp->options & RES_DEBUG) ||
1144 (statp->pfcode & RES_PRF_REPLY),
1145 (stdout, ";; not our server:\n"),
1146 thisansp,
1147 (*thisresplen > *thisanssiz)
1148 ? *thisanssiz : *thisresplen);
1149 goto wait;
1151 #ifdef RES_USE_EDNS0
1152 if (anhp->rcode == FORMERR
1153 && (statp->options & RES_USE_EDNS0) != 0U) {
1155 * Do not retry if the server does not understand
1156 * EDNS0. The case has to be captured here, as
1157 * FORMERR packet do not carry query section, hence
1158 * res_queriesmatch() returns 0.
1160 DprintQ(statp->options & RES_DEBUG,
1161 (stdout,
1162 "server rejected query with EDNS0:\n"),
1163 thisans,
1164 (*thisresplen > *thisanssiz)
1165 ? *thisanssiz : *thisresplen);
1166 /* record the error */
1167 statp->_flags |= RES_F_EDNS0ERR;
1168 goto err_out;
1170 #endif
1171 if (!(statp->options & RES_INSECURE2)
1172 && (recvresp1 || !res_queriesmatch(buf, buf + buflen,
1173 *thisansp,
1174 *thisansp
1175 + *thisanssizp))
1176 && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
1177 *thisansp,
1178 *thisansp
1179 + *thisanssizp))) {
1181 * response contains wrong query? ignore it.
1182 * XXX - potential security hazard could
1183 * be detected here.
1185 DprintQ((statp->options & RES_DEBUG) ||
1186 (statp->pfcode & RES_PRF_REPLY),
1187 (stdout, ";; wrong query name:\n"),
1188 thisansp,
1189 (*thisresplen > *thisanssiz)
1190 ? *thisanssiz : *thisresplen);
1191 goto wait;
1193 if (anhp->rcode == SERVFAIL ||
1194 anhp->rcode == NOTIMP ||
1195 anhp->rcode == REFUSED) {
1196 DprintQ(statp->options & RES_DEBUG,
1197 (stdout, "server rejected query:\n"),
1198 thisansp,
1199 (*thisresplen > *thisanssiz)
1200 ? *thisanssiz : *thisresplen);
1202 if (recvresp1 || (buf2 != NULL && recvresp2))
1204 *resplen2 = 1;
1205 return resplen;
1207 if (buf2 != NULL)
1209 /* We are waiting for a possible second reply. */
1210 resplen = 1;
1211 if (hp->id == anhp->id)
1212 recvresp1 = 1;
1213 else
1214 recvresp2 = 1;
1216 goto wait;
1219 next_ns:
1220 __res_iclose(statp, false);
1221 /* don't retry if called from dig */
1222 if (!statp->pfcode)
1223 return (0);
1225 if (anhp->rcode == NOERROR && anhp->ancount == 0
1226 && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
1227 DprintQ(statp->options & RES_DEBUG,
1228 (stdout, "referred query:\n"),
1229 thisansp,
1230 (*thisresplen > *thisanssiz)
1231 ? *thisanssiz : *thisresplen);
1232 goto next_ns;
1234 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1236 * To get the rest of answer,
1237 * use TCP with same server.
1239 Dprint(statp->options & RES_DEBUG,
1240 (stdout, ";; truncated answer\n"));
1241 *v_circuit = 1;
1242 __res_iclose(statp, false);
1243 // XXX if we have received one reply we could
1244 // XXX use it and not repeat it over TCP...
1245 return (1);
1247 /* Mark which reply we received. */
1248 if (recvresp1 == 0 && hp->id == anhp->id)
1249 recvresp1 = 1;
1250 else
1251 recvresp2 = 1;
1252 /* Repeat waiting if we have a second answer to arrive. */
1253 if ((recvresp1 & recvresp2) == 0)
1254 goto wait;
1256 * All is well, or the error is fatal. Signal that the
1257 * next nameserver ought not be tried.
1259 return (resplen);
1260 } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
1261 /* Something went wrong. We can stop trying. */
1262 goto err_out;
1264 else {
1265 /* poll should not have returned > 0 in this case. */
1266 abort ();
1270 #ifdef DEBUG
1271 static void
1272 Aerror(const res_state statp, FILE *file, const char *string, int error,
1273 const struct sockaddr *address)
1275 int save = errno;
1277 if ((statp->options & RES_DEBUG) != 0) {
1278 char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
1280 fprintf(file, "res_send: %s ([%s].%u): %s\n",
1281 string,
1282 (address->sa_family == AF_INET
1283 ? inet_ntop(address->sa_family,
1284 &((const struct sockaddr_in *) address)->sin_addr,
1285 tmp, sizeof tmp)
1286 : inet_ntop(address->sa_family,
1287 &((const struct sockaddr_in6 *) address)->sin6_addr,
1288 tmp, sizeof tmp)),
1289 (address->sa_family == AF_INET
1290 ? ntohs(((struct sockaddr_in *) address)->sin_port)
1291 : address->sa_family == AF_INET6
1292 ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
1293 : 0),
1294 strerror(error));
1296 __set_errno (save);
1299 static void
1300 Perror(const res_state statp, FILE *file, const char *string, int error) {
1301 int save = errno;
1303 if ((statp->options & RES_DEBUG) != 0)
1304 fprintf(file, "res_send: %s: %s\n",
1305 string, strerror(error));
1306 __set_errno (save);
1308 #endif
1310 static int
1311 sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
1312 if (a1->sin6_family == a2->sin6_family) {
1313 if (a1->sin6_family == AF_INET)
1314 return ((((struct sockaddr_in *)a1)->sin_port ==
1315 ((struct sockaddr_in *)a2)->sin_port) &&
1316 (((struct sockaddr_in *)a1)->sin_addr.s_addr ==
1317 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1318 else
1319 return ((a1->sin6_port == a2->sin6_port) &&
1320 !memcmp(&a1->sin6_addr, &a2->sin6_addr,
1321 sizeof (struct in6_addr)));
1323 if (a1->sin6_family == AF_INET) {
1324 struct sockaddr_in6 *sap = a1;
1325 a1 = a2;
1326 a2 = sap;
1327 } /* assumes that AF_INET and AF_INET6 are the only possibilities */
1328 return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) &&
1329 IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) &&
1330 (a1->sin6_addr.s6_addr32[3] ==
1331 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1335 * Converts IPv4 family, address and port to
1336 * IPv6 family, IPv4-mapped IPv6 address and port.
1338 static void
1339 convaddr4to6(struct sockaddr_in6 *sa)
1341 struct sockaddr_in *sa4p = (struct sockaddr_in *) sa;
1342 in_port_t port = sa4p->sin_port;
1343 in_addr_t addr = sa4p->sin_addr.s_addr;
1345 sa->sin6_family = AF_INET6;
1346 sa->sin6_port = port;
1347 sa->sin6_addr.s6_addr32[0] = 0;
1348 sa->sin6_addr.s6_addr32[1] = 0;
1349 sa->sin6_addr.s6_addr32[2] = htonl(0xFFFF);
1350 sa->sin6_addr.s6_addr32[3] = addr;