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