res_send.c revision 1.14 1 /* $NetBSD: res_send.c,v 1.14 2008/06/21 20:41:48 christos Exp $ */
2
3 /*
4 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 /*
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 */
55
56 /*
57 * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC")
58 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
59 *
60 * Permission to use, copy, modify, and distribute this software for any
61 * purpose with or without fee is hereby granted, provided that the above
62 * copyright notice and this permission notice appear in all copies.
63 *
64 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
65 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
66 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
67 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
68 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
69 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
70 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
71 */
72
73 #include <sys/cdefs.h>
74 #if defined(LIBC_SCCS) && !defined(lint)
75 #ifdef notdef
76 static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
77 static const char rcsid[] = "Id: res_send.c,v 1.18.10.1 2008/01/27 02:06:46 marka Exp";
78 #else
79 __RCSID("$NetBSD: res_send.c,v 1.14 2008/06/21 20:41:48 christos Exp $");
80 #endif
81 #endif /* LIBC_SCCS and not lint */
82
83 /*! \file
84 * \brief
85 * Send query to name server and wait for reply.
86 */
87
88 #include "namespace.h"
89 #include "port_before.h"
90 #include "fd_setsize.h"
91
92 #include <sys/types.h>
93 #include <sys/param.h>
94 #include <sys/time.h>
95 #include <sys/socket.h>
96 #include <sys/uio.h>
97
98 #include <netinet/in.h>
99 #include <arpa/nameser.h>
100 #include <arpa/inet.h>
101
102 #include <errno.h>
103 #include <netdb.h>
104 #include <resolv.h>
105 #include <signal.h>
106 #include <stdio.h>
107 #include <stdlib.h>
108 #include <string.h>
109 #include <unistd.h>
110
111 #include <isc/eventlib.h>
112
113 #include "port_after.h"
114
115 #if 0
116 #ifdef __weak_alias
117 __weak_alias(res_ourserver_p,__res_ourserver_p)
118 __weak_alias(res_nameinquery,__res_nameinquery)
119 __weak_alias(res_queriesmatch,__res_queriesmatch)
120 __weak_alias(res_nsend,__res_nsend)
121 #endif
122 #endif
123
124
125 #ifdef USE_POLL
126 #ifdef HAVE_STROPTS_H
127 #include <stropts.h>
128 #endif
129 #include <poll.h>
130 #endif /* USE_POLL */
131
132 /* Options. Leave them on. */
133 #define DEBUG
134 #include "res_debug.h"
135 #include "res_private.h"
136
137 #define EXT(res) ((res)->_u._ext)
138
139 #ifndef USE_POLL
140 static const int highestFD = FD_SETSIZE - 1;
141 #else
142 static int highestFD = 0;
143 #endif
144
145 /* Forward. */
146
147 static int get_salen __P((const struct sockaddr *));
148 static struct sockaddr * get_nsaddr __P((res_state, size_t));
149 static int send_vc(res_state, const u_char *, int,
150 u_char *, int, int *, int);
151 static int send_dg(res_state, const u_char *, int,
152 u_char *, int, int *, int, int,
153 int *, int *);
154 static void Aerror(const res_state, FILE *, const char *, int,
155 const struct sockaddr *, int);
156 static void Perror(const res_state, FILE *, const char *, int);
157 static int sock_eq(struct sockaddr *, struct sockaddr *);
158 #if defined(NEED_PSELECT) && !defined(USE_POLL)
159 static int pselect(int, void *, void *, void *,
160 struct timespec *,
161 const sigset_t *);
162 #endif
163 void res_pquery(const res_state, const u_char *, int, FILE *);
164
165 static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
166
167 /* Public. */
168
169 /*%
170 * looks up "ina" in _res.ns_addr_list[]
171 *
172 * returns:
173 *\li 0 : not found
174 *\li >0 : found
175 *
176 * author:
177 *\li paul vixie, 29may94
178 */
179 int
180 res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
181 const struct sockaddr_in *inp, *srv;
182 const struct sockaddr_in6 *in6p, *srv6;
183 int ns;
184
185 switch (sa->sa_family) {
186 case AF_INET:
187 inp = (const struct sockaddr_in *)(const void *)sa;
188 for (ns = 0; ns < statp->nscount; ns++) {
189 srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
190 if (srv->sin_family == inp->sin_family &&
191 srv->sin_port == inp->sin_port &&
192 (srv->sin_addr.s_addr == INADDR_ANY ||
193 srv->sin_addr.s_addr == inp->sin_addr.s_addr))
194 return (1);
195 }
196 break;
197 case AF_INET6:
198 if (EXT(statp).ext == NULL)
199 break;
200 in6p = (const struct sockaddr_in6 *)(const void *)sa;
201 for (ns = 0; ns < statp->nscount; ns++) {
202 srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
203 if (srv6->sin6_family == in6p->sin6_family &&
204 srv6->sin6_port == in6p->sin6_port &&
205 #ifdef HAVE_SIN6_SCOPE_ID
206 (srv6->sin6_scope_id == 0 ||
207 srv6->sin6_scope_id == in6p->sin6_scope_id) &&
208 #endif
209 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
210 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
211 return (1);
212 }
213 break;
214 default:
215 break;
216 }
217 return (0);
218 }
219
220 /*%
221 * look for (name,type,class) in the query section of packet (buf,eom)
222 *
223 * requires:
224 *\li buf + HFIXEDSZ <= eom
225 *
226 * returns:
227 *\li -1 : format error
228 *\li 0 : not found
229 *\li >0 : found
230 *
231 * author:
232 *\li paul vixie, 29may94
233 */
234 int
235 res_nameinquery(const char *name, int type, int class,
236 const u_char *buf, const u_char *eom)
237 {
238 const u_char *cp = buf + HFIXEDSZ;
239 int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
240
241 while (qdcount-- > 0) {
242 char tname[MAXDNAME+1];
243 int n, ttype, tclass;
244
245 n = dn_expand(buf, eom, cp, tname, sizeof tname);
246 if (n < 0)
247 return (-1);
248 cp += n;
249 if (cp + 2 * INT16SZ > eom)
250 return (-1);
251 ttype = ns_get16(cp); cp += INT16SZ;
252 tclass = ns_get16(cp); cp += INT16SZ;
253 if (ttype == type && tclass == class &&
254 ns_samename(tname, name) == 1)
255 return (1);
256 }
257 return (0);
258 }
259
260 /*%
261 * is there a 1:1 mapping of (name,type,class)
262 * in (buf1,eom1) and (buf2,eom2)?
263 *
264 * returns:
265 *\li -1 : format error
266 *\li 0 : not a 1:1 mapping
267 *\li >0 : is a 1:1 mapping
268 *
269 * author:
270 *\li paul vixie, 29may94
271 */
272 int
273 res_queriesmatch(const u_char *buf1, const u_char *eom1,
274 const u_char *buf2, const u_char *eom2)
275 {
276 const u_char *cp = buf1 + HFIXEDSZ;
277 int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
278
279 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
280 return (-1);
281
282 /*
283 * Only header section present in replies to
284 * dynamic update packets.
285 */
286 if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
287 (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
288 return (1);
289
290 if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
291 return (0);
292 while (qdcount-- > 0) {
293 char tname[MAXDNAME+1];
294 int n, ttype, tclass;
295
296 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
297 if (n < 0)
298 return (-1);
299 cp += n;
300 if (cp + 2 * INT16SZ > eom1)
301 return (-1);
302 ttype = ns_get16(cp); cp += INT16SZ;
303 tclass = ns_get16(cp); cp += INT16SZ;
304 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
305 return (0);
306 }
307 return (1);
308 }
309
310 int
311 res_nsend(res_state statp,
312 const u_char *buf, int buflen, u_char *ans, int anssiz)
313 {
314 int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
315 char abuf[NI_MAXHOST];
316
317 #ifdef USE_POLL
318 highestFD = sysconf(_SC_OPEN_MAX) - 1;
319 #endif
320
321 /* No name servers or res_init() failure */
322 if (statp->nscount == 0 || EXT(statp).ext == NULL) {
323 errno = ESRCH;
324 return (-1);
325 }
326 if (anssiz < HFIXEDSZ) {
327 errno = EINVAL;
328 return (-1);
329 }
330 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
331 (stdout, ";; res_send()\n"), buf, buflen);
332 v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
333 gotsomewhere = 0;
334 terrno = ETIMEDOUT;
335
336 /*
337 * If the ns_addr_list in the resolver context has changed, then
338 * invalidate our cached copy and the associated timing data.
339 */
340 if (EXT(statp).nscount != 0) {
341 int needclose = 0;
342 struct sockaddr_storage peer;
343 ISC_SOCKLEN_T peerlen;
344
345 if (EXT(statp).nscount != statp->nscount)
346 needclose++;
347 else
348 for (ns = 0; ns < statp->nscount; ns++) {
349 if (statp->nsaddr_list[ns].sin_family &&
350 !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
351 (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
352 needclose++;
353 break;
354 }
355
356 if (EXT(statp).nssocks[ns] == -1)
357 continue;
358 peerlen = sizeof(peer);
359 if (getsockname(EXT(statp).nssocks[ns],
360 (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
361 needclose++;
362 break;
363 }
364 if (!sock_eq((struct sockaddr *)(void *)&peer,
365 get_nsaddr(statp, (size_t)ns))) {
366 needclose++;
367 break;
368 }
369 }
370 if (needclose) {
371 res_nclose(statp);
372 EXT(statp).nscount = 0;
373 }
374 }
375
376 /*
377 * Maybe initialize our private copy of the ns_addr_list.
378 */
379 if (EXT(statp).nscount == 0) {
380 for (ns = 0; ns < statp->nscount; ns++) {
381 EXT(statp).nstimes[ns] = RES_MAXTIME;
382 EXT(statp).nssocks[ns] = -1;
383 if (!statp->nsaddr_list[ns].sin_family)
384 continue;
385 EXT(statp).ext->nsaddrs[ns].sin =
386 statp->nsaddr_list[ns];
387 }
388 EXT(statp).nscount = statp->nscount;
389 }
390
391 /*
392 * Some resolvers want to even out the load on their nameservers.
393 * Note that RES_BLAST overrides RES_ROTATE.
394 */
395 if ((statp->options & RES_ROTATE) != 0U &&
396 (statp->options & RES_BLAST) == 0U) {
397 union res_sockaddr_union inu;
398 struct sockaddr_in ina;
399 int lastns = statp->nscount - 1;
400 int fd;
401 u_int16_t nstime;
402
403 if (EXT(statp).ext != NULL)
404 inu = EXT(statp).ext->nsaddrs[0];
405 ina = statp->nsaddr_list[0];
406 fd = EXT(statp).nssocks[0];
407 nstime = EXT(statp).nstimes[0];
408 for (ns = 0; ns < lastns; ns++) {
409 if (EXT(statp).ext != NULL)
410 EXT(statp).ext->nsaddrs[ns] =
411 EXT(statp).ext->nsaddrs[ns + 1];
412 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
413 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
414 EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
415 }
416 if (EXT(statp).ext != NULL)
417 EXT(statp).ext->nsaddrs[lastns] = inu;
418 statp->nsaddr_list[lastns] = ina;
419 EXT(statp).nssocks[lastns] = fd;
420 EXT(statp).nstimes[lastns] = nstime;
421 }
422
423 /*
424 * Send request, RETRY times, or until successful.
425 */
426 for (tries = 0; tries < statp->retry; tries++) {
427 for (ns = 0; ns < statp->nscount; ns++) {
428 struct sockaddr *nsap;
429 int nsaplen;
430 nsap = get_nsaddr(statp, (size_t)ns);
431 nsaplen = get_salen(nsap);
432 statp->_flags &= ~RES_F_LASTMASK;
433 statp->_flags |= (ns << RES_F_LASTSHIFT);
434 same_ns:
435 if (statp->qhook) {
436 int done = 0, loops = 0;
437
438 do {
439 res_sendhookact act;
440
441 act = (*statp->qhook)(&nsap, &buf, &buflen,
442 ans, anssiz, &resplen);
443 switch (act) {
444 case res_goahead:
445 done = 1;
446 break;
447 case res_nextns:
448 res_nclose(statp);
449 goto next_ns;
450 case res_done:
451 return (resplen);
452 case res_modified:
453 /* give the hook another try */
454 if (++loops < 42) /*doug adams*/
455 break;
456 /*FALLTHROUGH*/
457 case res_error:
458 /*FALLTHROUGH*/
459 default:
460 goto fail;
461 }
462 } while (!done);
463 }
464
465 Dprint(((statp->options & RES_DEBUG) &&
466 getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
467 NULL, 0, niflags) == 0),
468 (stdout, ";; Querying server (# %d) address = %s\n",
469 ns + 1, abuf));
470
471
472 if (v_circuit) {
473 /* Use VC; at most one attempt per server. */
474 tries = statp->retry;
475 n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
476 ns);
477 if (n < 0)
478 goto fail;
479 if (n == 0)
480 goto next_ns;
481 resplen = n;
482 } else {
483 /* Use datagrams. */
484 n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
485 ns, tries, &v_circuit, &gotsomewhere);
486 if (n < 0)
487 goto fail;
488 if (n == 0)
489 goto next_ns;
490 if (v_circuit)
491 goto same_ns;
492 resplen = n;
493 }
494
495 Dprint((statp->options & RES_DEBUG) ||
496 ((statp->pfcode & RES_PRF_REPLY) &&
497 (statp->pfcode & RES_PRF_HEAD1)),
498 (stdout, ";; got answer:\n"));
499
500 DprintQ((statp->options & RES_DEBUG) ||
501 (statp->pfcode & RES_PRF_REPLY),
502 (stdout, "%s", ""),
503 ans, (resplen > anssiz) ? anssiz : resplen);
504
505 /*
506 * If we have temporarily opened a virtual circuit,
507 * or if we haven't been asked to keep a socket open,
508 * close the socket.
509 */
510 if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
511 (statp->options & RES_STAYOPEN) == 0U) {
512 res_nclose(statp);
513 }
514 if (statp->rhook) {
515 int done = 0, loops = 0;
516
517 do {
518 res_sendhookact act;
519
520 act = (*statp->rhook)(nsap, buf, buflen,
521 ans, anssiz, &resplen);
522 switch (act) {
523 case res_goahead:
524 case res_done:
525 done = 1;
526 break;
527 case res_nextns:
528 res_nclose(statp);
529 goto next_ns;
530 case res_modified:
531 /* give the hook another try */
532 if (++loops < 42) /*doug adams*/
533 break;
534 /*FALLTHROUGH*/
535 case res_error:
536 /*FALLTHROUGH*/
537 default:
538 goto fail;
539 }
540 } while (!done);
541
542 }
543 return (resplen);
544 next_ns: ;
545 } /*foreach ns*/
546 } /*foreach retry*/
547 res_nclose(statp);
548 if (!v_circuit) {
549 if (!gotsomewhere)
550 errno = ECONNREFUSED; /*%< no nameservers found */
551 else
552 errno = ETIMEDOUT; /*%< no answer obtained */
553 } else
554 errno = terrno;
555 return (-1);
556 fail:
557 res_nclose(statp);
558 return (-1);
559 }
560
561 /* Private */
562
563 static int
564 get_salen(sa)
565 const struct sockaddr *sa;
566 {
567
568 #ifdef HAVE_SA_LEN
569 /* There are people do not set sa_len. Be forgiving to them. */
570 if (sa->sa_len)
571 return (sa->sa_len);
572 #endif
573
574 if (sa->sa_family == AF_INET)
575 return (sizeof(struct sockaddr_in));
576 else if (sa->sa_family == AF_INET6)
577 return (sizeof(struct sockaddr_in6));
578 else
579 return (0); /*%< unknown, die on connect */
580 }
581
582 /*%
583 * pick appropriate nsaddr_list for use. see res_init() for initialization.
584 */
585 static struct sockaddr *
586 get_nsaddr(statp, n)
587 res_state statp;
588 size_t n;
589 {
590
591 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
592 /*
593 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
594 * than struct sockaddr, and
595 * - user code did not update statp->nsaddr_list[n].
596 */
597 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
598 } else {
599 /*
600 * - user code updated statp->nsaddr_list[n], or
601 * - statp->nsaddr_list[n] has the same content as
602 * EXT(statp).ext->nsaddrs[n].
603 */
604 return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
605 }
606 }
607
608 static int
609 send_vc(res_state statp,
610 const u_char *buf, int buflen, u_char *ans, int anssiz,
611 int *terrno, int ns)
612 {
613 const HEADER *hp = (const HEADER *)(const void *)buf;
614 HEADER *anhp = (HEADER *)(void *)ans;
615 struct sockaddr *nsap;
616 int nsaplen;
617 int truncating, connreset, resplen, n;
618 struct iovec iov[2];
619 u_short len;
620 u_char *cp;
621 void *tmp;
622 #ifdef SO_NOSIGPIPE
623 int on = 1;
624 #endif
625
626 nsap = get_nsaddr(statp, (size_t)ns);
627 nsaplen = get_salen(nsap);
628
629 connreset = 0;
630 same_ns:
631 truncating = 0;
632
633 /* Are we still talking to whom we want to talk to? */
634 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
635 struct sockaddr_storage peer;
636 ISC_SOCKLEN_T size = sizeof peer;
637
638 if (getpeername(statp->_vcsock,
639 (struct sockaddr *)(void *)&peer, &size) < 0 ||
640 !sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
641 res_nclose(statp);
642 statp->_flags &= ~RES_F_VC;
643 }
644 }
645
646 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
647 if (statp->_vcsock >= 0)
648 res_nclose(statp);
649
650 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
651 if (statp->_vcsock > highestFD) {
652 res_nclose(statp);
653 errno = ENOTSOCK;
654 }
655 if (statp->_vcsock < 0) {
656 switch (errno) {
657 case EPROTONOSUPPORT:
658 #ifdef EPFNOSUPPORT
659 case EPFNOSUPPORT:
660 #endif
661 case EAFNOSUPPORT:
662 Perror(statp, stderr, "socket(vc)", errno);
663 return (0);
664 default:
665 *terrno = errno;
666 Perror(statp, stderr, "socket(vc)", errno);
667 return (-1);
668 }
669 }
670 #ifdef SO_NOSIGPIPE
671 /*
672 * Disable generation of SIGPIPE when writing to a closed
673 * socket. Write should return -1 and set errno to EPIPE
674 * instead.
675 *
676 * Push on even if setsockopt(SO_NOSIGPIPE) fails.
677 */
678 (void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
679 sizeof(on));
680 #endif
681 errno = 0;
682 if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) {
683 *terrno = errno;
684 Aerror(statp, stderr, "connect/vc", errno, nsap,
685 nsaplen);
686 res_nclose(statp);
687 return (0);
688 }
689 statp->_flags |= RES_F_VC;
690 }
691
692 /*
693 * Send length & message
694 */
695 ns_put16((u_short)buflen, (u_char*)(void *)&len);
696 iov[0] = evConsIovec(&len, INT16SZ);
697 DE_CONST(buf, tmp);
698 iov[1] = evConsIovec(tmp, (size_t)buflen);
699 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
700 *terrno = errno;
701 Perror(statp, stderr, "write failed", errno);
702 res_nclose(statp);
703 return (0);
704 }
705 /*
706 * Receive length & response
707 */
708 read_len:
709 cp = ans;
710 len = INT16SZ;
711 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
712 cp += n;
713 if ((len -= n) == 0)
714 break;
715 }
716 if (n <= 0) {
717 *terrno = errno;
718 Perror(statp, stderr, "read failed", errno);
719 res_nclose(statp);
720 /*
721 * A long running process might get its TCP
722 * connection reset if the remote server was
723 * restarted. Requery the server instead of
724 * trying a new one. When there is only one
725 * server, this means that a query might work
726 * instead of failing. We only allow one reset
727 * per query to prevent looping.
728 */
729 if (*terrno == ECONNRESET && !connreset) {
730 connreset = 1;
731 res_nclose(statp);
732 goto same_ns;
733 }
734 res_nclose(statp);
735 return (0);
736 }
737 resplen = ns_get16(ans);
738 if (resplen > anssiz) {
739 Dprint(statp->options & RES_DEBUG,
740 (stdout, ";; response truncated\n")
741 );
742 truncating = 1;
743 len = anssiz;
744 } else
745 len = resplen;
746 if (len < HFIXEDSZ) {
747 /*
748 * Undersized message.
749 */
750 Dprint(statp->options & RES_DEBUG,
751 (stdout, ";; undersized: %d\n", len));
752 *terrno = EMSGSIZE;
753 res_nclose(statp);
754 return (0);
755 }
756 cp = ans;
757 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
758 cp += n;
759 len -= n;
760 }
761 if (n <= 0) {
762 *terrno = errno;
763 Perror(statp, stderr, "read(vc)", errno);
764 res_nclose(statp);
765 return (0);
766 }
767 if (truncating) {
768 /*
769 * Flush rest of answer so connection stays in synch.
770 */
771 anhp->tc = 1;
772 len = resplen - anssiz;
773 while (len != 0) {
774 char junk[PACKETSZ];
775
776 n = read(statp->_vcsock, junk,
777 (len > sizeof junk) ? sizeof junk : len);
778 if (n > 0)
779 len -= n;
780 else
781 break;
782 }
783 }
784 /*
785 * If the calling applicating has bailed out of
786 * a previous call and failed to arrange to have
787 * the circuit closed or the server has got
788 * itself confused, then drop the packet and
789 * wait for the correct one.
790 */
791 if (hp->id != anhp->id) {
792 DprintQ((statp->options & RES_DEBUG) ||
793 (statp->pfcode & RES_PRF_REPLY),
794 (stdout, ";; old answer (unexpected):\n"),
795 ans, (resplen > anssiz) ? anssiz: resplen);
796 goto read_len;
797 }
798
799 /*
800 * All is well, or the error is fatal. Signal that the
801 * next nameserver ought not be tried.
802 */
803 return (resplen);
804 }
805
806 static int
807 send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans,
808 int anssiz, int *terrno, int ns, int tries, int *v_circuit,
809 int *gotsomewhere)
810 {
811 const HEADER *hp = (const HEADER *)(const void *)buf;
812 HEADER *anhp = (HEADER *)(void *)ans;
813 const struct sockaddr *nsap;
814 int nsaplen;
815 struct timespec now, timeout, finish;
816 struct sockaddr_storage from;
817 ISC_SOCKLEN_T fromlen;
818 int resplen, seconds, n, s;
819 #ifdef USE_POLL
820 int polltimeout;
821 struct pollfd pollfd;
822 #else
823 fd_set dsmask;
824 #endif
825
826 nsap = get_nsaddr(statp, (size_t)ns);
827 nsaplen = get_salen(nsap);
828 if (EXT(statp).nssocks[ns] == -1) {
829 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
830 if (EXT(statp).nssocks[ns] > highestFD) {
831 res_nclose(statp);
832 errno = ENOTSOCK;
833 }
834 if (EXT(statp).nssocks[ns] < 0) {
835 switch (errno) {
836 case EPROTONOSUPPORT:
837 #ifdef EPFNOSUPPORT
838 case EPFNOSUPPORT:
839 #endif
840 case EAFNOSUPPORT:
841 Perror(statp, stderr, "socket(dg)", errno);
842 return (0);
843 default:
844 *terrno = errno;
845 Perror(statp, stderr, "socket(dg)", errno);
846 return (-1);
847 }
848 }
849 #ifndef CANNOT_CONNECT_DGRAM
850 /*
851 * On a 4.3BSD+ machine (client and server,
852 * actually), sending to a nameserver datagram
853 * port with no nameserver will cause an
854 * ICMP port unreachable message to be returned.
855 * If our datagram socket is "connected" to the
856 * server, we get an ECONNREFUSED error on the next
857 * socket operation, and select returns if the
858 * error message is received. We can thus detect
859 * the absence of a nameserver without timing out.
860 */
861 if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
862 Aerror(statp, stderr, "connect(dg)", errno, nsap,
863 nsaplen);
864 res_nclose(statp);
865 return (0);
866 }
867 #endif /* !CANNOT_CONNECT_DGRAM */
868 Dprint(statp->options & RES_DEBUG,
869 (stdout, ";; new DG socket\n"))
870 }
871 s = EXT(statp).nssocks[ns];
872 #ifndef CANNOT_CONNECT_DGRAM
873 if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
874 Perror(statp, stderr, "send", errno);
875 res_nclose(statp);
876 return (0);
877 }
878 #else /* !CANNOT_CONNECT_DGRAM */
879 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
880 {
881 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
882 res_nclose(statp);
883 return (0);
884 }
885 #endif /* !CANNOT_CONNECT_DGRAM */
886
887 /*
888 * Wait for reply.
889 */
890 seconds = (statp->retrans << tries);
891 if (ns > 0)
892 seconds /= statp->nscount;
893 if (seconds <= 0)
894 seconds = 1;
895 now = evNowTime();
896 timeout = evConsTime((long)seconds, 0L);
897 finish = evAddTime(now, timeout);
898 goto nonow;
899 wait:
900 now = evNowTime();
901 nonow:
902 #ifndef USE_POLL
903 FD_ZERO(&dsmask);
904 FD_SET(s, &dsmask);
905 if (evCmpTime(finish, now) > 0)
906 timeout = evSubTime(finish, now);
907 else
908 timeout = evConsTime(0L, 0L);
909 n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
910 #else
911 timeout = evSubTime(finish, now);
912 if (timeout.tv_sec < 0)
913 timeout = evConsTime(0L, 0L);
914 polltimeout = 1000*timeout.tv_sec +
915 timeout.tv_nsec/1000000;
916 pollfd.fd = s;
917 pollfd.events = POLLRDNORM;
918 n = poll(&pollfd, 1, polltimeout);
919 #endif /* USE_POLL */
920
921 if (n == 0) {
922 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
923 *gotsomewhere = 1;
924 return (0);
925 }
926 if (n < 0) {
927 if (errno == EINTR)
928 goto wait;
929 #ifndef USE_POLL
930 Perror(statp, stderr, "select", errno);
931 #else
932 Perror(statp, stderr, "poll", errno);
933 #endif /* USE_POLL */
934 res_nclose(statp);
935 return (0);
936 }
937 errno = 0;
938 fromlen = sizeof(from);
939 resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
940 (struct sockaddr *)(void *)&from, &fromlen);
941 if (resplen <= 0) {
942 Perror(statp, stderr, "recvfrom", errno);
943 res_nclose(statp);
944 return (0);
945 }
946 *gotsomewhere = 1;
947 if (resplen < HFIXEDSZ) {
948 /*
949 * Undersized message.
950 */
951 Dprint(statp->options & RES_DEBUG,
952 (stdout, ";; undersized: %d\n",
953 resplen));
954 *terrno = EMSGSIZE;
955 res_nclose(statp);
956 return (0);
957 }
958 if (hp->id != anhp->id) {
959 /*
960 * response from old query, ignore it.
961 * XXX - potential security hazard could
962 * be detected here.
963 */
964 DprintQ((statp->options & RES_DEBUG) ||
965 (statp->pfcode & RES_PRF_REPLY),
966 (stdout, ";; old answer:\n"),
967 ans, (resplen > anssiz) ? anssiz : resplen);
968 goto wait;
969 }
970 if (!(statp->options & RES_INSECURE1) &&
971 !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
972 /*
973 * response from wrong server? ignore it.
974 * XXX - potential security hazard could
975 * be detected here.
976 */
977 DprintQ((statp->options & RES_DEBUG) ||
978 (statp->pfcode & RES_PRF_REPLY),
979 (stdout, ";; not our server:\n"),
980 ans, (resplen > anssiz) ? anssiz : resplen);
981 goto wait;
982 }
983 #ifdef RES_USE_EDNS0
984 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
985 /*
986 * Do not retry if the server do not understand EDNS0.
987 * The case has to be captured here, as FORMERR packet do not
988 * carry query section, hence res_queriesmatch() returns 0.
989 */
990 DprintQ(statp->options & RES_DEBUG,
991 (stdout, "server rejected query with EDNS0:\n"),
992 ans, (resplen > anssiz) ? anssiz : resplen);
993 /* record the error */
994 statp->_flags |= RES_F_EDNS0ERR;
995 res_nclose(statp);
996 return (0);
997 }
998 #endif
999 if (!(statp->options & RES_INSECURE2) &&
1000 !res_queriesmatch(buf, buf + buflen,
1001 ans, ans + anssiz)) {
1002 /*
1003 * response contains wrong query? ignore it.
1004 * XXX - potential security hazard could
1005 * be detected here.
1006 */
1007 DprintQ((statp->options & RES_DEBUG) ||
1008 (statp->pfcode & RES_PRF_REPLY),
1009 (stdout, ";; wrong query name:\n"),
1010 ans, (resplen > anssiz) ? anssiz : resplen);
1011 goto wait;
1012 }
1013 if (anhp->rcode == SERVFAIL ||
1014 anhp->rcode == NOTIMP ||
1015 anhp->rcode == REFUSED) {
1016 DprintQ(statp->options & RES_DEBUG,
1017 (stdout, "server rejected query:\n"),
1018 ans, (resplen > anssiz) ? anssiz : resplen);
1019 res_nclose(statp);
1020 /* don't retry if called from dig */
1021 if (!statp->pfcode)
1022 return (0);
1023 }
1024 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1025 /*
1026 * To get the rest of answer,
1027 * use TCP with same server.
1028 */
1029 Dprint(statp->options & RES_DEBUG,
1030 (stdout, ";; truncated answer\n"));
1031 *v_circuit = 1;
1032 res_nclose(statp);
1033 return (1);
1034 }
1035 /*
1036 * All is well, or the error is fatal. Signal that the
1037 * next nameserver ought not be tried.
1038 */
1039 return (resplen);
1040 }
1041
1042 static void
1043 Aerror(const res_state statp, FILE *file, const char *string, int error,
1044 const struct sockaddr *address, int alen)
1045 {
1046 int save = errno;
1047 char hbuf[NI_MAXHOST];
1048 char sbuf[NI_MAXSERV];
1049
1050 alen = alen;
1051
1052 if ((statp->options & RES_DEBUG) != 0U) {
1053 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
1054 sbuf, sizeof(sbuf), niflags)) {
1055 strncpy(hbuf, "?", sizeof(hbuf) - 1);
1056 hbuf[sizeof(hbuf) - 1] = '\0';
1057 strncpy(sbuf, "?", sizeof(sbuf) - 1);
1058 sbuf[sizeof(sbuf) - 1] = '\0';
1059 }
1060 fprintf(file, "res_send: %s ([%s].%s): %s\n",
1061 string, hbuf, sbuf, strerror(error));
1062 }
1063 errno = save;
1064 }
1065
1066 static void
1067 Perror(const res_state statp, FILE *file, const char *string, int error) {
1068 int save = errno;
1069
1070 if ((statp->options & RES_DEBUG) != 0U)
1071 fprintf(file, "res_send: %s: %s\n",
1072 string, strerror(error));
1073 errno = save;
1074 }
1075
1076 static int
1077 sock_eq(struct sockaddr *a, struct sockaddr *b) {
1078 struct sockaddr_in *a4, *b4;
1079 struct sockaddr_in6 *a6, *b6;
1080
1081 if (a->sa_family != b->sa_family)
1082 return 0;
1083 switch (a->sa_family) {
1084 case AF_INET:
1085 a4 = (struct sockaddr_in *)(void *)a;
1086 b4 = (struct sockaddr_in *)(void *)b;
1087 return a4->sin_port == b4->sin_port &&
1088 a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1089 case AF_INET6:
1090 a6 = (struct sockaddr_in6 *)(void *)a;
1091 b6 = (struct sockaddr_in6 *)(void *)b;
1092 return a6->sin6_port == b6->sin6_port &&
1093 #ifdef HAVE_SIN6_SCOPE_ID
1094 a6->sin6_scope_id == b6->sin6_scope_id &&
1095 #endif
1096 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1097 default:
1098 return 0;
1099 }
1100 }
1101
1102 #if defined(NEED_PSELECT) && !defined(USE_POLL)
1103 /* XXX needs to move to the porting library. */
1104 static int
1105 pselect(int nfds, void *rfds, void *wfds, void *efds,
1106 struct timespec *tsp, const sigset_t *sigmask)
1107 {
1108 struct timeval tv, *tvp;
1109 sigset_t sigs;
1110 int n;
1111
1112 if (tsp) {
1113 tvp = &tv;
1114 tv = evTimeVal(*tsp);
1115 } else
1116 tvp = NULL;
1117 if (sigmask)
1118 sigprocmask(SIG_SETMASK, sigmask, &sigs);
1119 n = select(nfds, rfds, wfds, efds, tvp);
1120 if (sigmask)
1121 sigprocmask(SIG_SETMASK, &sigs, NULL);
1122 if (tsp)
1123 *tsp = evTimeSpec(tv);
1124 return (n);
1125 }
1126 #endif
1127