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