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