1 /* $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $ */
2
3 /*
4 * Copyright 2008 Android Open Source Project (source port randomization)
5 * Copyright (c) 1985, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 /*
38 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
39 *
40 * Permission to use, copy, modify, and distribute this software for any
41 * purpose with or without fee is hereby granted, provided that the above
42 * copyright notice and this permission notice appear in all copies, and that
43 * the name of Digital Equipment Corporation not be used in advertising or
44 * publicity pertaining to distribution of the document or software without
45 * specific, written prior permission.
46 *
47 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
48 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
50 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
51 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
52 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
53 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54 * SOFTWARE.
55 */
56
57 /*
58 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
59 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
60 *
61 * Permission to use, copy, modify, and distribute this software for any
62 * purpose with or without fee is hereby granted, provided that the above
63 * copyright notice and this permission notice appear in all copies.
64 *
65 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
66 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
67 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
68 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
69 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
70 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
71 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
72 */
73
74 #include <sys/cdefs.h>
75 #if defined(LIBC_SCCS) && !defined(lint)
76 #ifdef notdef
77 static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
78 static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp";
79 #else
80 __RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
81 #endif
82 #endif /* LIBC_SCCS and not lint */
83
84 /* set to 1 to use our small/simple/limited DNS cache */
85 #define USE_RESOLV_CACHE 1
86
87 /*
88 * Send query to name server and wait for reply.
89 */
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 <netinet/in6.h>
99 #include "arpa_nameser.h"
100 #include <arpa/inet.h>
101
102 #include <errno.h>
103 #include <netdb.h>
104 #ifdef ANDROID_CHANGES
105 #include "resolv_private.h"
106 #else
107 #include <resolv.h>
108 #endif
109 #include <signal.h>
110 #include <stdio.h>
111 #include <stdlib.h>
112 #include <string.h>
113 #include <unistd.h>
114
115 #include <isc/eventlib.h>
116
117 #if USE_RESOLV_CACHE
118 # include <resolv_cache.h>
119 #endif
120
121 #ifndef DE_CONST
122 #define DE_CONST(c,v) v = ((c) ? \
123 strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
124 #endif
125
126 /* Options. Leave them on. */
127 #ifndef DEBUG
128 #define DEBUG
129 #endif
130 #include "res_debug.h"
131 #include "res_private.h"
132
133 #define EXT(res) ((res)->_u._ext)
134
135 static const int highestFD = FD_SETSIZE - 1;
136
137 /* Forward. */
138
139 static int get_salen __P((const struct sockaddr *));
140 static struct sockaddr * get_nsaddr __P((res_state, size_t));
141 static int send_vc(res_state, const u_char *, int,
142 u_char *, int, int *, int);
143 static int send_dg(res_state, const u_char *, int,
144 u_char *, int, int *, int,
145 int *, int *);
146 static void Aerror(const res_state, FILE *, const char *, int,
147 const struct sockaddr *, int);
148 static void Perror(const res_state, FILE *, const char *, int);
149 static int sock_eq(struct sockaddr *, struct sockaddr *);
150 #ifdef NEED_PSELECT
151 static int pselect(int, void *, void *, void *,
152 struct timespec *,
153 const sigset_t *);
154 #endif
155 void res_pquery(const res_state, const u_char *, int, FILE *);
156
157
158 /* BIONIC-BEGIN: implement source port randomization */
159 typedef union {
160 struct sockaddr sa;
161 struct sockaddr_in sin;
162 struct sockaddr_in6 sin6;
163 } _sockaddr_union;
164
165 static int
random_bind(int s,int family)166 random_bind( int s, int family )
167 {
168 _sockaddr_union u;
169 int j;
170 socklen_t slen;
171
172 /* clear all, this also sets the IP4/6 address to 'any' */
173 memset( &u, 0, sizeof u );
174
175 switch (family) {
176 case AF_INET:
177 u.sin.sin_family = family;
178 slen = sizeof u.sin;
179 break;
180 case AF_INET6:
181 u.sin6.sin6_family = family;
182 slen = sizeof u.sin6;
183 break;
184 default:
185 errno = EPROTO;
186 return -1;
187 }
188
189 /* first try to bind to a random source port a few times */
190 for (j = 0; j < 10; j++) {
191 /* find a random port between 1025 .. 65534 */
192 int port = 1025 + (res_randomid() % (65535-1025));
193 if (family == AF_INET)
194 u.sin.sin_port = htons(port);
195 else
196 u.sin6.sin6_port = htons(port);
197
198 if ( !bind( s, &u.sa, slen ) )
199 return 0;
200 }
201
202 /* nothing after 10 tries, our network table is probably busy */
203 /* let the system decide which port is best */
204 if (family == AF_INET)
205 u.sin.sin_port = 0;
206 else
207 u.sin6.sin6_port = 0;
208
209 return bind( s, &u.sa, slen );
210 }
211 /* BIONIC-END */
212
213 static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
214
215 /* Public. */
216
217 /* int
218 * res_isourserver(ina)
219 * looks up "ina" in _res.ns_addr_list[]
220 * returns:
221 * 0 : not found
222 * >0 : found
223 * author:
224 * paul vixie, 29may94
225 */
226 int
res_ourserver_p(const res_state statp,const struct sockaddr * sa)227 res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
228 const struct sockaddr_in *inp, *srv;
229 const struct sockaddr_in6 *in6p, *srv6;
230 int ns;
231
232 switch (sa->sa_family) {
233 case AF_INET:
234 inp = (const struct sockaddr_in *)(const void *)sa;
235 for (ns = 0; ns < statp->nscount; ns++) {
236 srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
237 if (srv->sin_family == inp->sin_family &&
238 srv->sin_port == inp->sin_port &&
239 (srv->sin_addr.s_addr == INADDR_ANY ||
240 srv->sin_addr.s_addr == inp->sin_addr.s_addr))
241 return (1);
242 }
243 break;
244 case AF_INET6:
245 if (EXT(statp).ext == NULL)
246 break;
247 in6p = (const struct sockaddr_in6 *)(const void *)sa;
248 for (ns = 0; ns < statp->nscount; ns++) {
249 srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
250 if (srv6->sin6_family == in6p->sin6_family &&
251 srv6->sin6_port == in6p->sin6_port &&
252 #ifdef HAVE_SIN6_SCOPE_ID
253 (srv6->sin6_scope_id == 0 ||
254 srv6->sin6_scope_id == in6p->sin6_scope_id) &&
255 #endif
256 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
257 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
258 return (1);
259 }
260 break;
261 default:
262 break;
263 }
264 return (0);
265 }
266
267 /* int
268 * res_nameinquery(name, type, class, buf, eom)
269 * look for (name,type,class) in the query section of packet (buf,eom)
270 * requires:
271 * buf + HFIXEDSZ <= eom
272 * returns:
273 * -1 : format error
274 * 0 : not found
275 * >0 : found
276 * author:
277 * paul vixie, 29may94
278 */
279 int
res_nameinquery(const char * name,int type,int class,const u_char * buf,const u_char * eom)280 res_nameinquery(const char *name, int type, int class,
281 const u_char *buf, const u_char *eom)
282 {
283 const u_char *cp = buf + HFIXEDSZ;
284 int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
285
286 while (qdcount-- > 0) {
287 char tname[MAXDNAME+1];
288 int n, ttype, tclass;
289
290 n = dn_expand(buf, eom, cp, tname, sizeof tname);
291 if (n < 0)
292 return (-1);
293 cp += n;
294 if (cp + 2 * INT16SZ > eom)
295 return (-1);
296 ttype = ns_get16(cp); cp += INT16SZ;
297 tclass = ns_get16(cp); cp += INT16SZ;
298 if (ttype == type && tclass == class &&
299 ns_samename(tname, name) == 1)
300 return (1);
301 }
302 return (0);
303 }
304
305 /* int
306 * res_queriesmatch(buf1, eom1, buf2, eom2)
307 * is there a 1:1 mapping of (name,type,class)
308 * in (buf1,eom1) and (buf2,eom2)?
309 * returns:
310 * -1 : format error
311 * 0 : not a 1:1 mapping
312 * >0 : is a 1:1 mapping
313 * author:
314 * paul vixie, 29may94
315 */
316 int
res_queriesmatch(const u_char * buf1,const u_char * eom1,const u_char * buf2,const u_char * eom2)317 res_queriesmatch(const u_char *buf1, const u_char *eom1,
318 const u_char *buf2, const u_char *eom2)
319 {
320 const u_char *cp = buf1 + HFIXEDSZ;
321 int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
322
323 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
324 return (-1);
325
326 /*
327 * Only header section present in replies to
328 * dynamic update packets.
329 */
330 if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
331 (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
332 return (1);
333
334 if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
335 return (0);
336 while (qdcount-- > 0) {
337 char tname[MAXDNAME+1];
338 int n, ttype, tclass;
339
340 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
341 if (n < 0)
342 return (-1);
343 cp += n;
344 if (cp + 2 * INT16SZ > eom1)
345 return (-1);
346 ttype = ns_get16(cp); cp += INT16SZ;
347 tclass = ns_get16(cp); cp += INT16SZ;
348 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
349 return (0);
350 }
351 return (1);
352 }
353
354
355 int
res_nsend(res_state statp,const u_char * buf,int buflen,u_char * ans,int anssiz)356 res_nsend(res_state statp,
357 const u_char *buf, int buflen, u_char *ans, int anssiz)
358 {
359 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
360 char abuf[NI_MAXHOST];
361 #if USE_RESOLV_CACHE
362 struct resolv_cache* cache;
363 ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED;
364 #endif
365
366 if (statp->nscount == 0) {
367 errno = ESRCH;
368 return (-1);
369 }
370 if (anssiz < HFIXEDSZ) {
371 errno = EINVAL;
372 return (-1);
373 }
374 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
375 (stdout, ";; res_send()\n"), buf, buflen);
376 v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
377 gotsomewhere = 0;
378 terrno = ETIMEDOUT;
379
380 #if USE_RESOLV_CACHE
381 cache = __get_res_cache();
382 if (cache != NULL) {
383 int anslen = 0;
384 cache_status = _resolv_cache_lookup(
385 cache, buf, buflen,
386 ans, anssiz, &anslen);
387
388 if (cache_status == RESOLV_CACHE_FOUND) {
389 return anslen;
390 }
391 }
392 #endif
393
394 /*
395 * If the ns_addr_list in the resolver context has changed, then
396 * invalidate our cached copy and the associated timing data.
397 */
398 if (EXT(statp).nscount != 0) {
399 int needclose = 0;
400 struct sockaddr_storage peer;
401 socklen_t peerlen;
402
403 if (EXT(statp).nscount != statp->nscount)
404 needclose++;
405 else
406 for (ns = 0; ns < statp->nscount; ns++) {
407 if (statp->nsaddr_list[ns].sin_family &&
408 !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
409 (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
410 needclose++;
411 break;
412 }
413
414 if (EXT(statp).nssocks[ns] == -1)
415 continue;
416 peerlen = sizeof(peer);
417 if (getsockname(EXT(statp).nssocks[ns],
418 (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
419 needclose++;
420 break;
421 }
422 if (!sock_eq((struct sockaddr *)(void *)&peer,
423 get_nsaddr(statp, (size_t)ns))) {
424 needclose++;
425 break;
426 }
427 }
428 if (needclose) {
429 res_nclose(statp);
430 EXT(statp).nscount = 0;
431 }
432 }
433
434 /*
435 * Maybe initialize our private copy of the ns_addr_list.
436 */
437 if (EXT(statp).nscount == 0) {
438 for (ns = 0; ns < statp->nscount; ns++) {
439 EXT(statp).nstimes[ns] = RES_MAXTIME;
440 EXT(statp).nssocks[ns] = -1;
441 if (!statp->nsaddr_list[ns].sin_family)
442 continue;
443 EXT(statp).ext->nsaddrs[ns].sin =
444 statp->nsaddr_list[ns];
445 }
446 EXT(statp).nscount = statp->nscount;
447 }
448
449 /*
450 * Some resolvers want to even out the load on their nameservers.
451 * Note that RES_BLAST overrides RES_ROTATE.
452 */
453 if ((statp->options & RES_ROTATE) != 0U &&
454 (statp->options & RES_BLAST) == 0U) {
455 union res_sockaddr_union inu;
456 struct sockaddr_in ina;
457 int lastns = statp->nscount - 1;
458 int fd;
459 u_int16_t nstime;
460
461 if (EXT(statp).ext != NULL)
462 inu = EXT(statp).ext->nsaddrs[0];
463 ina = statp->nsaddr_list[0];
464 fd = EXT(statp).nssocks[0];
465 nstime = EXT(statp).nstimes[0];
466 for (ns = 0; ns < lastns; ns++) {
467 if (EXT(statp).ext != NULL)
468 EXT(statp).ext->nsaddrs[ns] =
469 EXT(statp).ext->nsaddrs[ns + 1];
470 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
471 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
472 EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
473 }
474 if (EXT(statp).ext != NULL)
475 EXT(statp).ext->nsaddrs[lastns] = inu;
476 statp->nsaddr_list[lastns] = ina;
477 EXT(statp).nssocks[lastns] = fd;
478 EXT(statp).nstimes[lastns] = nstime;
479 }
480
481 /*
482 * Send request, RETRY times, or until successful.
483 */
484 for (try = 0; try < statp->retry; try++) {
485 for (ns = 0; ns < statp->nscount; ns++) {
486 struct sockaddr *nsap;
487 int nsaplen;
488 nsap = get_nsaddr(statp, (size_t)ns);
489 nsaplen = get_salen(nsap);
490 statp->_flags &= ~RES_F_LASTMASK;
491 statp->_flags |= (ns << RES_F_LASTSHIFT);
492 same_ns:
493 if (statp->qhook) {
494 int done = 0, loops = 0;
495
496 do {
497 res_sendhookact act;
498
499 act = (*statp->qhook)(&nsap, &buf, &buflen,
500 ans, anssiz, &resplen);
501 switch (act) {
502 case res_goahead:
503 done = 1;
504 break;
505 case res_nextns:
506 res_nclose(statp);
507 goto next_ns;
508 case res_done:
509 return (resplen);
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 Dprint(((statp->options & RES_DEBUG) &&
524 getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
525 NULL, 0, niflags) == 0),
526 (stdout, ";; Querying server (# %d) address = %s\n",
527 ns + 1, abuf));
528
529
530 if (v_circuit) {
531 /* Use VC; at most one attempt per server. */
532 try = statp->retry;
533 n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
534 ns);
535 if (n < 0)
536 goto fail;
537 if (n == 0)
538 goto next_ns;
539 resplen = n;
540 } else {
541 /* Use datagrams. */
542 n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
543 ns, &v_circuit, &gotsomewhere);
544 if (n < 0)
545 goto fail;
546 if (n == 0)
547 goto next_ns;
548 if (v_circuit)
549 goto same_ns;
550 resplen = n;
551 }
552
553 Dprint((statp->options & RES_DEBUG) ||
554 ((statp->pfcode & RES_PRF_REPLY) &&
555 (statp->pfcode & RES_PRF_HEAD1)),
556 (stdout, ";; got answer:\n"));
557
558 DprintQ((statp->options & RES_DEBUG) ||
559 (statp->pfcode & RES_PRF_REPLY),
560 (stdout, "%s", ""),
561 ans, (resplen > anssiz) ? anssiz : resplen);
562
563 #if USE_RESOLV_CACHE
564 if (cache_status == RESOLV_CACHE_NOTFOUND) {
565 _resolv_cache_add(cache, buf, buflen,
566 ans, resplen);
567 }
568 #endif
569 /*
570 * If we have temporarily opened a virtual circuit,
571 * or if we haven't been asked to keep a socket open,
572 * close the socket.
573 */
574 if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
575 (statp->options & RES_STAYOPEN) == 0U) {
576 res_nclose(statp);
577 }
578 if (statp->rhook) {
579 int done = 0, loops = 0;
580
581 do {
582 res_sendhookact act;
583
584 act = (*statp->rhook)(nsap, buf, buflen,
585 ans, anssiz, &resplen);
586 switch (act) {
587 case res_goahead:
588 case res_done:
589 done = 1;
590 break;
591 case res_nextns:
592 res_nclose(statp);
593 goto next_ns;
594 case res_modified:
595 /* give the hook another try */
596 if (++loops < 42) /*doug adams*/
597 break;
598 /*FALLTHROUGH*/
599 case res_error:
600 /*FALLTHROUGH*/
601 default:
602 goto fail;
603 }
604 } while (!done);
605
606 }
607 return (resplen);
608 next_ns: ;
609 } /*foreach ns*/
610 } /*foreach retry*/
611 res_nclose(statp);
612 if (!v_circuit) {
613 if (!gotsomewhere)
614 errno = ECONNREFUSED; /* no nameservers found */
615 else
616 errno = ETIMEDOUT; /* no answer obtained */
617 } else
618 errno = terrno;
619 return (-1);
620 fail:
621 res_nclose(statp);
622 return (-1);
623 }
624
625 /* Private */
626
627 static int
get_salen(sa)628 get_salen(sa)
629 const struct sockaddr *sa;
630 {
631
632 #ifdef HAVE_SA_LEN
633 /* There are people do not set sa_len. Be forgiving to them. */
634 if (sa->sa_len)
635 return (sa->sa_len);
636 #endif
637
638 if (sa->sa_family == AF_INET)
639 return (sizeof(struct sockaddr_in));
640 else if (sa->sa_family == AF_INET6)
641 return (sizeof(struct sockaddr_in6));
642 else
643 return (0); /* unknown, die on connect */
644 }
645
646 /*
647 * pick appropriate nsaddr_list for use. see res_init() for initialization.
648 */
649 static struct sockaddr *
get_nsaddr(statp,n)650 get_nsaddr(statp, n)
651 res_state statp;
652 size_t n;
653 {
654
655 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
656 /*
657 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
658 * than struct sockaddr, and
659 * - user code did not update statp->nsaddr_list[n].
660 */
661 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
662 } else {
663 /*
664 * - user code updated statp->nsaddr_list[n], or
665 * - statp->nsaddr_list[n] has the same content as
666 * EXT(statp).ext->nsaddrs[n].
667 */
668 return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
669 }
670 }
671
672 static int
send_vc(res_state statp,const u_char * buf,int buflen,u_char * ans,int anssiz,int * terrno,int ns)673 send_vc(res_state statp,
674 const u_char *buf, int buflen, u_char *ans, int anssiz,
675 int *terrno, int ns)
676 {
677 const HEADER *hp = (const HEADER *)(const void *)buf;
678 HEADER *anhp = (HEADER *)(void *)ans;
679 struct sockaddr *nsap;
680 int nsaplen;
681 int truncating, connreset, resplen, n;
682 struct iovec iov[2];
683 u_short len;
684 u_char *cp;
685 void *tmp;
686
687 nsap = get_nsaddr(statp, (size_t)ns);
688 nsaplen = get_salen(nsap);
689
690 connreset = 0;
691 same_ns:
692 truncating = 0;
693
694 /* Are we still talking to whom we want to talk to? */
695 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
696 struct sockaddr_storage peer;
697 socklen_t size = sizeof peer;
698
699 if (getpeername(statp->_vcsock,
700 (struct sockaddr *)(void *)&peer, &size) < 0 ||
701 !sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
702 res_nclose(statp);
703 statp->_flags &= ~RES_F_VC;
704 }
705 }
706
707 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
708 if (statp->_vcsock >= 0)
709 res_nclose(statp);
710
711 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
712 if (statp->_vcsock > highestFD) {
713 res_nclose(statp);
714 errno = ENOTSOCK;
715 }
716 if (statp->_vcsock < 0) {
717 switch (errno) {
718 case EPROTONOSUPPORT:
719 #ifdef EPFNOSUPPORT
720 case EPFNOSUPPORT:
721 #endif
722 case EAFNOSUPPORT:
723 Perror(statp, stderr, "socket(vc)", errno);
724 return (0);
725 default:
726 *terrno = errno;
727 Perror(statp, stderr, "socket(vc)", errno);
728 return (-1);
729 }
730 }
731 errno = 0;
732 if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
733 *terrno = errno;
734 Aerror(statp, stderr, "bind/vc", errno, nsap,
735 nsaplen);
736 res_nclose(statp);
737 return (0);
738 }
739 if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) {
740 *terrno = errno;
741 Aerror(statp, stderr, "connect/vc", errno, nsap,
742 nsaplen);
743 res_nclose(statp);
744 return (0);
745 }
746 statp->_flags |= RES_F_VC;
747 }
748
749 /*
750 * Send length & message
751 */
752 ns_put16((u_short)buflen, (u_char*)(void *)&len);
753 iov[0] = evConsIovec(&len, INT16SZ);
754 DE_CONST(buf, tmp);
755 iov[1] = evConsIovec(tmp, (size_t)buflen);
756 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
757 *terrno = errno;
758 Perror(statp, stderr, "write failed", errno);
759 res_nclose(statp);
760 return (0);
761 }
762 /*
763 * Receive length & response
764 */
765 read_len:
766 cp = ans;
767 len = INT16SZ;
768 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
769 cp += n;
770 if ((len -= n) == 0)
771 break;
772 }
773 if (n <= 0) {
774 *terrno = errno;
775 Perror(statp, stderr, "read failed", errno);
776 res_nclose(statp);
777 /*
778 * A long running process might get its TCP
779 * connection reset if the remote server was
780 * restarted. Requery the server instead of
781 * trying a new one. When there is only one
782 * server, this means that a query might work
783 * instead of failing. We only allow one reset
784 * per query to prevent looping.
785 */
786 if (*terrno == ECONNRESET && !connreset) {
787 connreset = 1;
788 res_nclose(statp);
789 goto same_ns;
790 }
791 res_nclose(statp);
792 return (0);
793 }
794 resplen = ns_get16(ans);
795 if (resplen > anssiz) {
796 Dprint(statp->options & RES_DEBUG,
797 (stdout, ";; response truncated\n")
798 );
799 truncating = 1;
800 len = anssiz;
801 } else
802 len = resplen;
803 if (len < HFIXEDSZ) {
804 /*
805 * Undersized message.
806 */
807 Dprint(statp->options & RES_DEBUG,
808 (stdout, ";; undersized: %d\n", len));
809 *terrno = EMSGSIZE;
810 res_nclose(statp);
811 return (0);
812 }
813 cp = ans;
814 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
815 cp += n;
816 len -= n;
817 }
818 if (n <= 0) {
819 *terrno = errno;
820 Perror(statp, stderr, "read(vc)", errno);
821 res_nclose(statp);
822 return (0);
823 }
824 if (truncating) {
825 /*
826 * Flush rest of answer so connection stays in synch.
827 */
828 anhp->tc = 1;
829 len = resplen - anssiz;
830 while (len != 0) {
831 char junk[PACKETSZ];
832
833 n = read(statp->_vcsock, junk,
834 (len > sizeof junk) ? sizeof junk : len);
835 if (n > 0)
836 len -= n;
837 else
838 break;
839 }
840 }
841 /*
842 * If the calling applicating has bailed out of
843 * a previous call and failed to arrange to have
844 * the circuit closed or the server has got
845 * itself confused, then drop the packet and
846 * wait for the correct one.
847 */
848 if (hp->id != anhp->id) {
849 DprintQ((statp->options & RES_DEBUG) ||
850 (statp->pfcode & RES_PRF_REPLY),
851 (stdout, ";; old answer (unexpected):\n"),
852 ans, (resplen > anssiz) ? anssiz: resplen);
853 goto read_len;
854 }
855
856 /*
857 * All is well, or the error is fatal. Signal that the
858 * next nameserver ought not be tried.
859 */
860 return (resplen);
861 }
862
863 static int
send_dg(res_state statp,const u_char * buf,int buflen,u_char * ans,int anssiz,int * terrno,int ns,int * v_circuit,int * gotsomewhere)864 send_dg(res_state statp,
865 const u_char *buf, int buflen, u_char *ans, int anssiz,
866 int *terrno, int ns, int *v_circuit, int *gotsomewhere)
867 {
868 const HEADER *hp = (const HEADER *)(const void *)buf;
869 HEADER *anhp = (HEADER *)(void *)ans;
870 const struct sockaddr *nsap;
871 int nsaplen;
872 struct timespec now, timeout, finish;
873 fd_set dsmask;
874 struct sockaddr_storage from;
875 socklen_t fromlen;
876 int resplen, seconds, n, s;
877
878 nsap = get_nsaddr(statp, (size_t)ns);
879 nsaplen = get_salen(nsap);
880 if (EXT(statp).nssocks[ns] == -1) {
881 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
882 if (EXT(statp).nssocks[ns] > highestFD) {
883 res_nclose(statp);
884 errno = ENOTSOCK;
885 }
886 if (EXT(statp).nssocks[ns] < 0) {
887 switch (errno) {
888 case EPROTONOSUPPORT:
889 #ifdef EPFNOSUPPORT
890 case EPFNOSUPPORT:
891 #endif
892 case EAFNOSUPPORT:
893 Perror(statp, stderr, "socket(dg)", errno);
894 return (0);
895 default:
896 *terrno = errno;
897 Perror(statp, stderr, "socket(dg)", errno);
898 return (-1);
899 }
900 }
901 #ifndef CANNOT_CONNECT_DGRAM
902 /*
903 * On a 4.3BSD+ machine (client and server,
904 * actually), sending to a nameserver datagram
905 * port with no nameserver will cause an
906 * ICMP port unreachable message to be returned.
907 * If our datagram socket is "connected" to the
908 * server, we get an ECONNREFUSED error on the next
909 * socket operation, and select returns if the
910 * error message is received. We can thus detect
911 * the absence of a nameserver without timing out.
912 */
913 if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) {
914 Aerror(statp, stderr, "bind(dg)", errno, nsap,
915 nsaplen);
916 res_nclose(statp);
917 return (0);
918 }
919 if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
920 Aerror(statp, stderr, "connect(dg)", errno, nsap,
921 nsaplen);
922 res_nclose(statp);
923 return (0);
924 }
925 #endif /* !CANNOT_CONNECT_DGRAM */
926 Dprint(statp->options & RES_DEBUG,
927 (stdout, ";; new DG socket\n"))
928 }
929 s = EXT(statp).nssocks[ns];
930 #ifndef CANNOT_CONNECT_DGRAM
931 if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
932 Perror(statp, stderr, "send", errno);
933 res_nclose(statp);
934 return (0);
935 }
936 #else /* !CANNOT_CONNECT_DGRAM */
937 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
938 {
939 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
940 res_nclose(statp);
941 return (0);
942 }
943 #endif /* !CANNOT_CONNECT_DGRAM */
944
945 /*
946 * Wait for reply.
947 */
948 seconds = (statp->retrans << ns);
949 if (ns > 0)
950 seconds /= statp->nscount;
951 if (seconds <= 0)
952 seconds = 1;
953 now = evNowTime();
954 timeout = evConsTime((long)seconds, 0L);
955 finish = evAddTime(now, timeout);
956 goto nonow;
957 wait:
958 now = evNowTime();
959 nonow:
960 FD_ZERO(&dsmask);
961 FD_SET(s, &dsmask);
962 if (evCmpTime(finish, now) > 0)
963 timeout = evSubTime(finish, now);
964 else
965 timeout = evConsTime(0L, 0L);
966 n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
967 if (n == 0) {
968 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
969 *gotsomewhere = 1;
970 return (0);
971 }
972 if (n < 0) {
973 if (errno == EINTR)
974 goto wait;
975 Perror(statp, stderr, "select", errno);
976 res_nclose(statp);
977 return (0);
978 }
979 errno = 0;
980 fromlen = sizeof(from);
981 resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
982 (struct sockaddr *)(void *)&from, &fromlen);
983 if (resplen <= 0) {
984 Perror(statp, stderr, "recvfrom", errno);
985 res_nclose(statp);
986 return (0);
987 }
988 *gotsomewhere = 1;
989 if (resplen < HFIXEDSZ) {
990 /*
991 * Undersized message.
992 */
993 Dprint(statp->options & RES_DEBUG,
994 (stdout, ";; undersized: %d\n",
995 resplen));
996 *terrno = EMSGSIZE;
997 res_nclose(statp);
998 return (0);
999 }
1000 if (hp->id != anhp->id) {
1001 /*
1002 * response from old query, ignore it.
1003 * XXX - potential security hazard could
1004 * be detected here.
1005 */
1006 DprintQ((statp->options & RES_DEBUG) ||
1007 (statp->pfcode & RES_PRF_REPLY),
1008 (stdout, ";; old answer:\n"),
1009 ans, (resplen > anssiz) ? anssiz : resplen);
1010 goto wait;
1011 }
1012 if (!(statp->options & RES_INSECURE1) &&
1013 !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
1014 /*
1015 * response from wrong server? ignore it.
1016 * XXX - potential security hazard could
1017 * be detected here.
1018 */
1019 DprintQ((statp->options & RES_DEBUG) ||
1020 (statp->pfcode & RES_PRF_REPLY),
1021 (stdout, ";; not our server:\n"),
1022 ans, (resplen > anssiz) ? anssiz : resplen);
1023 goto wait;
1024 }
1025 #ifdef RES_USE_EDNS0
1026 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1027 /*
1028 * Do not retry if the server do not understand EDNS0.
1029 * The case has to be captured here, as FORMERR packet do not
1030 * carry query section, hence res_queriesmatch() returns 0.
1031 */
1032 DprintQ(statp->options & RES_DEBUG,
1033 (stdout, "server rejected query with EDNS0:\n"),
1034 ans, (resplen > anssiz) ? anssiz : resplen);
1035 /* record the error */
1036 statp->_flags |= RES_F_EDNS0ERR;
1037 res_nclose(statp);
1038 return (0);
1039 }
1040 #endif
1041 if (!(statp->options & RES_INSECURE2) &&
1042 !res_queriesmatch(buf, buf + buflen,
1043 ans, ans + anssiz)) {
1044 /*
1045 * response contains wrong query? ignore it.
1046 * XXX - potential security hazard could
1047 * be detected here.
1048 */
1049 DprintQ((statp->options & RES_DEBUG) ||
1050 (statp->pfcode & RES_PRF_REPLY),
1051 (stdout, ";; wrong query name:\n"),
1052 ans, (resplen > anssiz) ? anssiz : resplen);
1053 goto wait;
1054 }
1055 if (anhp->rcode == SERVFAIL ||
1056 anhp->rcode == NOTIMP ||
1057 anhp->rcode == REFUSED) {
1058 DprintQ(statp->options & RES_DEBUG,
1059 (stdout, "server rejected query:\n"),
1060 ans, (resplen > anssiz) ? anssiz : resplen);
1061 res_nclose(statp);
1062 /* don't retry if called from dig */
1063 if (!statp->pfcode)
1064 return (0);
1065 }
1066 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1067 /*
1068 * To get the rest of answer,
1069 * use TCP with same server.
1070 */
1071 Dprint(statp->options & RES_DEBUG,
1072 (stdout, ";; truncated answer\n"));
1073 *v_circuit = 1;
1074 res_nclose(statp);
1075 return (1);
1076 }
1077 /*
1078 * All is well, or the error is fatal. Signal that the
1079 * next nameserver ought not be tried.
1080 */
1081 return (resplen);
1082 }
1083
1084 static void
Aerror(const res_state statp,FILE * file,const char * string,int error,const struct sockaddr * address,int alen)1085 Aerror(const res_state statp, FILE *file, const char *string, int error,
1086 const struct sockaddr *address, int alen)
1087 {
1088 int save = errno;
1089 char hbuf[NI_MAXHOST];
1090 char sbuf[NI_MAXSERV];
1091
1092 alen = alen;
1093
1094 if ((statp->options & RES_DEBUG) != 0U) {
1095 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
1096 sbuf, sizeof(sbuf), niflags)) {
1097 strncpy(hbuf, "?", sizeof(hbuf) - 1);
1098 hbuf[sizeof(hbuf) - 1] = '\0';
1099 strncpy(sbuf, "?", sizeof(sbuf) - 1);
1100 sbuf[sizeof(sbuf) - 1] = '\0';
1101 }
1102 fprintf(file, "res_send: %s ([%s].%s): %s\n",
1103 string, hbuf, sbuf, strerror(error));
1104 }
1105 errno = save;
1106 }
1107
1108 static void
Perror(const res_state statp,FILE * file,const char * string,int error)1109 Perror(const res_state statp, FILE *file, const char *string, int error) {
1110 int save = errno;
1111
1112 if ((statp->options & RES_DEBUG) != 0U)
1113 fprintf(file, "res_send: %s: %s\n",
1114 string, strerror(error));
1115 errno = save;
1116 }
1117
1118 static int
sock_eq(struct sockaddr * a,struct sockaddr * b)1119 sock_eq(struct sockaddr *a, struct sockaddr *b) {
1120 struct sockaddr_in *a4, *b4;
1121 struct sockaddr_in6 *a6, *b6;
1122
1123 if (a->sa_family != b->sa_family)
1124 return 0;
1125 switch (a->sa_family) {
1126 case AF_INET:
1127 a4 = (struct sockaddr_in *)(void *)a;
1128 b4 = (struct sockaddr_in *)(void *)b;
1129 return a4->sin_port == b4->sin_port &&
1130 a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1131 case AF_INET6:
1132 a6 = (struct sockaddr_in6 *)(void *)a;
1133 b6 = (struct sockaddr_in6 *)(void *)b;
1134 return a6->sin6_port == b6->sin6_port &&
1135 #ifdef HAVE_SIN6_SCOPE_ID
1136 a6->sin6_scope_id == b6->sin6_scope_id &&
1137 #endif
1138 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1139 default:
1140 return 0;
1141 }
1142 }
1143
1144 #ifdef NEED_PSELECT
1145 /* XXX needs to move to the porting library. */
1146 static int
pselect(int nfds,void * rfds,void * wfds,void * efds,struct timespec * tsp,const sigset_t * sigmask)1147 pselect(int nfds, void *rfds, void *wfds, void *efds,
1148 struct timespec *tsp, const sigset_t *sigmask)
1149 {
1150 struct timeval tv, *tvp;
1151 sigset_t sigs;
1152 int n;
1153
1154 if (tsp) {
1155 tvp = &tv;
1156 tv = evTimeVal(*tsp);
1157 } else
1158 tvp = NULL;
1159 if (sigmask)
1160 sigprocmask(SIG_SETMASK, sigmask, &sigs);
1161 n = select(nfds, rfds, wfds, efds, tvp);
1162 if (sigmask)
1163 sigprocmask(SIG_SETMASK, &sigs, NULL);
1164 if (tsp)
1165 *tsp = evTimeSpec(tv);
1166 return (n);
1167 }
1168 #endif
1169