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