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