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