res_send.c revision 1.10 1 /* $NetBSD: res_send.c,v 1.10 2007/01/27 22:26:44 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.9.18.8 2006/10/16 23:00:58 marka Exp";
78 #else
79 __RCSID("$NetBSD: res_send.c,v 1.10 2007/01/27 22:26:44 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, try, 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 (try = 0; try < statp->retry; try++) {
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 try = 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, try, &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
625 nsap = get_nsaddr(statp, (size_t)ns);
626 nsaplen = get_salen(nsap);
627
628 connreset = 0;
629 same_ns:
630 truncating = 0;
631
632 /* Are we still talking to whom we want to talk to? */
633 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
634 struct sockaddr_storage peer;
635 ISC_SOCKLEN_T size = sizeof peer;
636
637 if (getpeername(statp->_vcsock,
638 (struct sockaddr *)(void *)&peer, &size) < 0 ||
639 !sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
640 res_nclose(statp);
641 statp->_flags &= ~RES_F_VC;
642 }
643 }
644
645 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
646 if (statp->_vcsock >= 0)
647 res_nclose(statp);
648
649 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
650 if (statp->_vcsock > highestFD) {
651 res_nclose(statp);
652 errno = ENOTSOCK;
653 }
654 if (statp->_vcsock < 0) {
655 switch (errno) {
656 case EPROTONOSUPPORT:
657 #ifdef EPFNOSUPPORT
658 case EPFNOSUPPORT:
659 #endif
660 case EAFNOSUPPORT:
661 Perror(statp, stderr, "socket(vc)", errno);
662 return (0);
663 default:
664 *terrno = errno;
665 Perror(statp, stderr, "socket(vc)", errno);
666 return (-1);
667 }
668 }
669 errno = 0;
670 if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) {
671 *terrno = errno;
672 Aerror(statp, stderr, "connect/vc", errno, nsap,
673 nsaplen);
674 res_nclose(statp);
675 return (0);
676 }
677 statp->_flags |= RES_F_VC;
678 }
679
680 /*
681 * Send length & message
682 */
683 ns_put16((u_short)buflen, (u_char*)(void *)&len);
684 iov[0] = evConsIovec(&len, INT16SZ);
685 DE_CONST(buf, tmp);
686 iov[1] = evConsIovec(tmp, (size_t)buflen);
687 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
688 *terrno = errno;
689 Perror(statp, stderr, "write failed", errno);
690 res_nclose(statp);
691 return (0);
692 }
693 /*
694 * Receive length & response
695 */
696 read_len:
697 cp = ans;
698 len = INT16SZ;
699 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
700 cp += n;
701 if ((len -= n) == 0)
702 break;
703 }
704 if (n <= 0) {
705 *terrno = errno;
706 Perror(statp, stderr, "read failed", errno);
707 res_nclose(statp);
708 /*
709 * A long running process might get its TCP
710 * connection reset if the remote server was
711 * restarted. Requery the server instead of
712 * trying a new one. When there is only one
713 * server, this means that a query might work
714 * instead of failing. We only allow one reset
715 * per query to prevent looping.
716 */
717 if (*terrno == ECONNRESET && !connreset) {
718 connreset = 1;
719 res_nclose(statp);
720 goto same_ns;
721 }
722 res_nclose(statp);
723 return (0);
724 }
725 resplen = ns_get16(ans);
726 if (resplen > anssiz) {
727 Dprint(statp->options & RES_DEBUG,
728 (stdout, ";; response truncated\n")
729 );
730 truncating = 1;
731 len = anssiz;
732 } else
733 len = resplen;
734 if (len < HFIXEDSZ) {
735 /*
736 * Undersized message.
737 */
738 Dprint(statp->options & RES_DEBUG,
739 (stdout, ";; undersized: %d\n", len));
740 *terrno = EMSGSIZE;
741 res_nclose(statp);
742 return (0);
743 }
744 cp = ans;
745 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
746 cp += n;
747 len -= n;
748 }
749 if (n <= 0) {
750 *terrno = errno;
751 Perror(statp, stderr, "read(vc)", errno);
752 res_nclose(statp);
753 return (0);
754 }
755 if (truncating) {
756 /*
757 * Flush rest of answer so connection stays in synch.
758 */
759 anhp->tc = 1;
760 len = resplen - anssiz;
761 while (len != 0) {
762 char junk[PACKETSZ];
763
764 n = read(statp->_vcsock, junk,
765 (len > sizeof junk) ? sizeof junk : len);
766 if (n > 0)
767 len -= n;
768 else
769 break;
770 }
771 }
772 /*
773 * If the calling applicating has bailed out of
774 * a previous call and failed to arrange to have
775 * the circuit closed or the server has got
776 * itself confused, then drop the packet and
777 * wait for the correct one.
778 */
779 if (hp->id != anhp->id) {
780 DprintQ((statp->options & RES_DEBUG) ||
781 (statp->pfcode & RES_PRF_REPLY),
782 (stdout, ";; old answer (unexpected):\n"),
783 ans, (resplen > anssiz) ? anssiz: resplen);
784 goto read_len;
785 }
786
787 /*
788 * All is well, or the error is fatal. Signal that the
789 * next nameserver ought not be tried.
790 */
791 return (resplen);
792 }
793
794 static int
795 send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans,
796 int anssiz, int *terrno, int ns, int try, int *v_circuit,
797 int *gotsomewhere)
798 {
799 const HEADER *hp = (const HEADER *)(const void *)buf;
800 HEADER *anhp = (HEADER *)(void *)ans;
801 const struct sockaddr *nsap;
802 int nsaplen;
803 struct timespec now, timeout, finish;
804 struct sockaddr_storage from;
805 ISC_SOCKLEN_T fromlen;
806 int resplen, seconds, n, s;
807 #ifdef USE_POLL
808 int polltimeout;
809 struct pollfd pollfd;
810 #else
811 fd_set dsmask;
812 #endif
813
814 nsap = get_nsaddr(statp, (size_t)ns);
815 nsaplen = get_salen(nsap);
816 if (EXT(statp).nssocks[ns] == -1) {
817 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
818 if (EXT(statp).nssocks[ns] > highestFD) {
819 res_nclose(statp);
820 errno = ENOTSOCK;
821 }
822 if (EXT(statp).nssocks[ns] < 0) {
823 switch (errno) {
824 case EPROTONOSUPPORT:
825 #ifdef EPFNOSUPPORT
826 case EPFNOSUPPORT:
827 #endif
828 case EAFNOSUPPORT:
829 Perror(statp, stderr, "socket(dg)", errno);
830 return (0);
831 default:
832 *terrno = errno;
833 Perror(statp, stderr, "socket(dg)", errno);
834 return (-1);
835 }
836 }
837 #ifndef CANNOT_CONNECT_DGRAM
838 /*
839 * On a 4.3BSD+ machine (client and server,
840 * actually), sending to a nameserver datagram
841 * port with no nameserver will cause an
842 * ICMP port unreachable message to be returned.
843 * If our datagram socket is "connected" to the
844 * server, we get an ECONNREFUSED error on the next
845 * socket operation, and select returns if the
846 * error message is received. We can thus detect
847 * the absence of a nameserver without timing out.
848 */
849 if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
850 Aerror(statp, stderr, "connect(dg)", errno, nsap,
851 nsaplen);
852 res_nclose(statp);
853 return (0);
854 }
855 #endif /* !CANNOT_CONNECT_DGRAM */
856 Dprint(statp->options & RES_DEBUG,
857 (stdout, ";; new DG socket\n"))
858 }
859 s = EXT(statp).nssocks[ns];
860 #ifndef CANNOT_CONNECT_DGRAM
861 if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
862 Perror(statp, stderr, "send", errno);
863 res_nclose(statp);
864 return (0);
865 }
866 #else /* !CANNOT_CONNECT_DGRAM */
867 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
868 {
869 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
870 res_nclose(statp);
871 return (0);
872 }
873 #endif /* !CANNOT_CONNECT_DGRAM */
874
875 /*
876 * Wait for reply.
877 */
878 seconds = (statp->retrans << try);
879 if (ns > 0)
880 seconds /= statp->nscount;
881 if (seconds <= 0)
882 seconds = 1;
883 now = evNowTime();
884 timeout = evConsTime((long)seconds, 0L);
885 finish = evAddTime(now, timeout);
886 goto nonow;
887 wait:
888 now = evNowTime();
889 nonow:
890 #ifndef USE_POLL
891 FD_ZERO(&dsmask);
892 FD_SET(s, &dsmask);
893 if (evCmpTime(finish, now) > 0)
894 timeout = evSubTime(finish, now);
895 else
896 timeout = evConsTime(0L, 0L);
897 n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
898 #else
899 timeout = evSubTime(finish, now);
900 if (timeout.tv_sec < 0)
901 timeout = evConsTime(0, 0);
902 polltimeout = 1000*timeout.tv_sec +
903 timeout.tv_nsec/1000000;
904 pollfd.fd = s;
905 pollfd.events = POLLRDNORM;
906 n = poll(&pollfd, 1, polltimeout);
907 #endif /* USE_POLL */
908
909 if (n == 0) {
910 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
911 *gotsomewhere = 1;
912 return (0);
913 }
914 if (n < 0) {
915 if (errno == EINTR)
916 goto wait;
917 #ifndef USE_POLL
918 Perror(statp, stderr, "select", errno);
919 #else
920 Perror(statp, stderr, "poll", errno);
921 #endif /* USE_POLL */
922 res_nclose(statp);
923 return (0);
924 }
925 errno = 0;
926 fromlen = sizeof(from);
927 resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
928 (struct sockaddr *)(void *)&from, &fromlen);
929 if (resplen <= 0) {
930 Perror(statp, stderr, "recvfrom", errno);
931 res_nclose(statp);
932 return (0);
933 }
934 *gotsomewhere = 1;
935 if (resplen < HFIXEDSZ) {
936 /*
937 * Undersized message.
938 */
939 Dprint(statp->options & RES_DEBUG,
940 (stdout, ";; undersized: %d\n",
941 resplen));
942 *terrno = EMSGSIZE;
943 res_nclose(statp);
944 return (0);
945 }
946 if (hp->id != anhp->id) {
947 /*
948 * response from old query, ignore it.
949 * XXX - potential security hazard could
950 * be detected here.
951 */
952 DprintQ((statp->options & RES_DEBUG) ||
953 (statp->pfcode & RES_PRF_REPLY),
954 (stdout, ";; old answer:\n"),
955 ans, (resplen > anssiz) ? anssiz : resplen);
956 goto wait;
957 }
958 if (!(statp->options & RES_INSECURE1) &&
959 !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
960 /*
961 * response from wrong server? ignore it.
962 * XXX - potential security hazard could
963 * be detected here.
964 */
965 DprintQ((statp->options & RES_DEBUG) ||
966 (statp->pfcode & RES_PRF_REPLY),
967 (stdout, ";; not our server:\n"),
968 ans, (resplen > anssiz) ? anssiz : resplen);
969 goto wait;
970 }
971 #ifdef RES_USE_EDNS0
972 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
973 /*
974 * Do not retry if the server do not understand EDNS0.
975 * The case has to be captured here, as FORMERR packet do not
976 * carry query section, hence res_queriesmatch() returns 0.
977 */
978 DprintQ(statp->options & RES_DEBUG,
979 (stdout, "server rejected query with EDNS0:\n"),
980 ans, (resplen > anssiz) ? anssiz : resplen);
981 /* record the error */
982 statp->_flags |= RES_F_EDNS0ERR;
983 res_nclose(statp);
984 return (0);
985 }
986 #endif
987 if (!(statp->options & RES_INSECURE2) &&
988 !res_queriesmatch(buf, buf + buflen,
989 ans, ans + anssiz)) {
990 /*
991 * response contains wrong query? ignore it.
992 * XXX - potential security hazard could
993 * be detected here.
994 */
995 DprintQ((statp->options & RES_DEBUG) ||
996 (statp->pfcode & RES_PRF_REPLY),
997 (stdout, ";; wrong query name:\n"),
998 ans, (resplen > anssiz) ? anssiz : resplen);
999 goto wait;
1000 }
1001 if (anhp->rcode == SERVFAIL ||
1002 anhp->rcode == NOTIMP ||
1003 anhp->rcode == REFUSED) {
1004 DprintQ(statp->options & RES_DEBUG,
1005 (stdout, "server rejected query:\n"),
1006 ans, (resplen > anssiz) ? anssiz : resplen);
1007 res_nclose(statp);
1008 /* don't retry if called from dig */
1009 if (!statp->pfcode)
1010 return (0);
1011 }
1012 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1013 /*
1014 * To get the rest of answer,
1015 * use TCP with same server.
1016 */
1017 Dprint(statp->options & RES_DEBUG,
1018 (stdout, ";; truncated answer\n"));
1019 *v_circuit = 1;
1020 res_nclose(statp);
1021 return (1);
1022 }
1023 /*
1024 * All is well, or the error is fatal. Signal that the
1025 * next nameserver ought not be tried.
1026 */
1027 return (resplen);
1028 }
1029
1030 static void
1031 Aerror(const res_state statp, FILE *file, const char *string, int error,
1032 const struct sockaddr *address, int alen)
1033 {
1034 int save = errno;
1035 char hbuf[NI_MAXHOST];
1036 char sbuf[NI_MAXSERV];
1037
1038 alen = alen;
1039
1040 if ((statp->options & RES_DEBUG) != 0U) {
1041 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
1042 sbuf, sizeof(sbuf), niflags)) {
1043 strncpy(hbuf, "?", sizeof(hbuf) - 1);
1044 hbuf[sizeof(hbuf) - 1] = '\0';
1045 strncpy(sbuf, "?", sizeof(sbuf) - 1);
1046 sbuf[sizeof(sbuf) - 1] = '\0';
1047 }
1048 fprintf(file, "res_send: %s ([%s].%s): %s\n",
1049 string, hbuf, sbuf, strerror(error));
1050 }
1051 errno = save;
1052 }
1053
1054 static void
1055 Perror(const res_state statp, FILE *file, const char *string, int error) {
1056 int save = errno;
1057
1058 if ((statp->options & RES_DEBUG) != 0U)
1059 fprintf(file, "res_send: %s: %s\n",
1060 string, strerror(error));
1061 errno = save;
1062 }
1063
1064 static int
1065 sock_eq(struct sockaddr *a, struct sockaddr *b) {
1066 struct sockaddr_in *a4, *b4;
1067 struct sockaddr_in6 *a6, *b6;
1068
1069 if (a->sa_family != b->sa_family)
1070 return 0;
1071 switch (a->sa_family) {
1072 case AF_INET:
1073 a4 = (struct sockaddr_in *)(void *)a;
1074 b4 = (struct sockaddr_in *)(void *)b;
1075 return a4->sin_port == b4->sin_port &&
1076 a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1077 case AF_INET6:
1078 a6 = (struct sockaddr_in6 *)(void *)a;
1079 b6 = (struct sockaddr_in6 *)(void *)b;
1080 return a6->sin6_port == b6->sin6_port &&
1081 #ifdef HAVE_SIN6_SCOPE_ID
1082 a6->sin6_scope_id == b6->sin6_scope_id &&
1083 #endif
1084 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1085 default:
1086 return 0;
1087 }
1088 }
1089
1090 #if defined(NEED_PSELECT) && !defined(USE_POLL)
1091 /* XXX needs to move to the porting library. */
1092 static int
1093 pselect(int nfds, void *rfds, void *wfds, void *efds,
1094 struct timespec *tsp, const sigset_t *sigmask)
1095 {
1096 struct timeval tv, *tvp;
1097 sigset_t sigs;
1098 int n;
1099
1100 if (tsp) {
1101 tvp = &tv;
1102 tv = evTimeVal(*tsp);
1103 } else
1104 tvp = NULL;
1105 if (sigmask)
1106 sigprocmask(SIG_SETMASK, sigmask, &sigs);
1107 n = select(nfds, rfds, wfds, efds, tvp);
1108 if (sigmask)
1109 sigprocmask(SIG_SETMASK, &sigs, NULL);
1110 if (tsp)
1111 *tsp = evTimeSpec(tv);
1112 return (n);
1113 }
1114 #endif
1115