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