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