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