2 * Copyright (c) 1985, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies, and that
40 * the name of Digital Equipment Corporation not be used in advertising or
41 * publicity pertaining to distribution of the document or software without
42 * specific, written prior permission.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
47 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
55 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
57 * Permission to use, copy, modify, and distribute this software for any
58 * purpose with or without fee is hereby granted, provided that the above
59 * copyright notice and this permission notice appear in all copies.
61 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
62 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
64 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
65 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
66 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
67 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
71 #if defined(LIBC_SCCS) && !defined(lint)
72 static const char sccsid
[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
73 static const char rcsid
[] = "$Id: res_send.c,v 1.1 2006/03/01 19:01:38 majka Exp $";
74 #endif /* LIBC_SCCS and not lint */
77 * Send query to name server and wait for reply.
81 #include "port_before.h"
82 #include "fd_setsize.h"
86 * internal_recvfrom uses RFC 2292 API (IPV6_PKTINFO)
87 * __APPLE_USE_RFC_2292 selects the appropriate API in <netinet6/in6.h>
89 #define __APPLE_USE_RFC_2292
91 #include <sys/types.h>
92 #include <sys/param.h>
94 #include <sys/socket.h>
97 #include <netinet/in.h>
98 #include <arpa/nameser.h>
99 #include <arpa/inet.h>
113 #include <net/if_dl.h>
114 #include "res_private.h"
117 #include <isc/eventlib.h>
118 #include "port_after.h"
122 #define ISC_SOCKLEN_T unsigned int
125 /* Options. Leave them on. */
127 #define CANNOT_CONNECT_DGRAM
132 #include "res_debug.h"
133 #include "res_private.h"
134 #include <sys/fcntl.h>
136 #define EXT(res) ((res)->_u._ext)
138 static const int highestFD
= FD_SETSIZE
- 1;
140 #define MAX_HOOK_RETRIES 42
142 /* port randomization */
143 #define RANDOM_BIND_MAX_TRIES 16
144 #define RANDOM_BIND_FIRST IPPORT_HIFIRSTAUTO
145 #define RANDOM_BIND_LAST IPPORT_HILASTAUTO
149 static int get_salen
__P((const struct sockaddr
*));
150 static int send_vc(res_state
, const u_char
*, int, u_char
*, int *, int *, int, struct sockaddr
*, int *, int);
151 static int send_dg(res_state
, const u_char
*, int, u_char
*, int *, int *, int, int *, int *, struct sockaddr
*, int *, int);
152 static void Aerror(const res_state
, FILE *, const char *, int, const struct sockaddr
*, int);
153 static void Perror(const res_state
, FILE *, const char *, int);
154 static int sock_eq(struct sockaddr
*, struct sockaddr
*);
155 #ifdef USE_DNS_PSELECT
156 static int dns_pselect(int, void *, void *, void *, struct timespec
*, const sigset_t
*);
159 static const int niflags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
161 /* interrupt mechanism is shared with res_query.c */
162 __attribute__((__visibility__("hidden"))) int interrupt_pipe_enabled
= 0;
163 __attribute__((__visibility__("hidden"))) pthread_key_t interrupt_pipe_key
;
166 bind_random(int sock
, int family
)
170 struct sockaddr_storage local
;
171 struct sockaddr_in
*sin
;
172 struct sockaddr_in6
*sin6
;
178 for (i
= 0; (i
< RANDOM_BIND_MAX_TRIES
) && (status
< 0); i
++)
180 /* random port in the range RANDOM_BIND_FIRST to RANDOM_BIND_LAST */
181 src_port
= (res_randomid() % (RANDOM_BIND_LAST
- RANDOM_BIND_FIRST
)) + RANDOM_BIND_FIRST
;
182 memset(&local
, 0, sizeof(local
));
185 sin
= (struct sockaddr_in
*)&local
;
186 sin
->sin_len
= sizeof(struct sockaddr_in
);
187 sin
->sin_family
= family
;
188 sin
->sin_port
= htons(src_port
);
191 sin6
= (struct sockaddr_in6
*)&local
;
192 sin6
->sin6_len
= sizeof(struct sockaddr_in6
);
193 sin6
->sin6_family
= family
;
194 sin6
->sin6_port
= htons(src_port
);
198 sa
= (struct sockaddr
*)&local
;
199 status
= bind(sock
, sa
, sa
->sa_len
);
206 res_delete_interrupt_token(void *token
)
210 interrupt_pipe
= token
;
211 if (interrupt_pipe
== NULL
) return;
213 if (interrupt_pipe
[0] >= 0)
215 close(interrupt_pipe
[0]);
216 interrupt_pipe
[0] = -1;
219 if (interrupt_pipe
[1] >= 0)
221 close(interrupt_pipe
[1]);
222 interrupt_pipe
[1] = -1;
225 pthread_setspecific(interrupt_pipe_key
, NULL
);
226 free(interrupt_pipe
);
230 res_init_interrupt_token(void)
234 interrupt_pipe
= (int *)malloc(2 * sizeof(int));
235 if (interrupt_pipe
== NULL
) return NULL
;
237 if (pipe(interrupt_pipe
) < 0)
239 /* this shouldn't happen */
240 interrupt_pipe
[0] = -1;
241 interrupt_pipe
[1] = -1;
245 fcntl(interrupt_pipe
[0], F_SETFD
, FD_CLOEXEC
| O_NONBLOCK
);
246 fcntl(interrupt_pipe
[1], F_SETFD
, FD_CLOEXEC
| O_NONBLOCK
);
249 pthread_setspecific(interrupt_pipe_key
, interrupt_pipe
);
251 return interrupt_pipe
;
255 res_interrupt_requests_enable(void)
257 interrupt_pipe_enabled
= 1;
258 pthread_key_create(&interrupt_pipe_key
, NULL
);
262 res_interrupt_requests_disable(void)
264 interrupt_pipe_enabled
= 0;
265 pthread_key_delete(interrupt_pipe_key
);
269 res_interrupt_request(void *token
)
274 interrupt_pipe
= token
;
276 if ((interrupt_pipe
== NULL
) || (interrupt_pipe_enabled
== 0)) return;
278 oldwrite
= interrupt_pipe
[1];
279 interrupt_pipe
[1] = -1;
281 if (oldwrite
>= 0) close(oldwrite
);
286 evConsIovec(void *buf
, size_t cnt
)
290 memset(&ret
, 0xf5, sizeof ret
);
296 static struct timespec
297 evConsTime(time_t sec
, long nsec
)
306 static struct timespec
307 evTimeSpec(struct timeval tv
)
311 ts
.tv_sec
= tv
.tv_sec
;
312 ts
.tv_nsec
= tv
.tv_usec
* 1000;
316 static struct timespec
321 if (gettimeofday(&now
, NULL
) < 0) return (evConsTime(0, 0));
322 return (evTimeSpec(now
));
325 #ifdef USE_DNS_PSELECT
326 static struct timeval
327 evTimeVal(struct timespec ts
)
331 tv
.tv_sec
= ts
.tv_sec
;
332 tv
.tv_usec
= ts
.tv_nsec
/ 1000;
337 #define BILLION 1000000000
338 static struct timespec
339 evAddTime(struct timespec addend1
, struct timespec addend2
)
343 x
.tv_sec
= addend1
.tv_sec
+ addend2
.tv_sec
;
344 x
.tv_nsec
= addend1
.tv_nsec
+ addend2
.tv_nsec
;
345 if (x
.tv_nsec
>= BILLION
)
348 x
.tv_nsec
-= BILLION
;
354 static struct timespec
355 evSubTime(struct timespec minuend
, struct timespec subtrahend
)
359 x
.tv_sec
= minuend
.tv_sec
- subtrahend
.tv_sec
;
360 if (minuend
.tv_nsec
>= subtrahend
.tv_nsec
)
362 x
.tv_nsec
= minuend
.tv_nsec
- subtrahend
.tv_nsec
;
366 x
.tv_nsec
= BILLION
- subtrahend
.tv_nsec
+ minuend
.tv_nsec
;
374 evCmpTime(struct timespec a
, struct timespec b
)
376 long x
= a
.tv_sec
- b
.tv_sec
;
378 if (x
== 0L) x
= a
.tv_nsec
- b
.tv_nsec
;
379 return (x
< 0L ? (-1) : x
> 0L ? (1) : (0));
382 #endif /* __APPLE__ */
387 * res_isourserver(ina)
388 * looks up "ina" in _res.ns_addr_list[]
393 * paul vixie, 29may94
396 res_ourserver_p(const res_state statp
, const struct sockaddr
*sa
)
398 const struct sockaddr_in
*inp
, *srv
;
399 const struct sockaddr_in6
*in6p
, *srv6
;
402 switch (sa
->sa_family
)
405 inp
= (const struct sockaddr_in
*)sa
;
406 for (ns
= 0; ns
< statp
->nscount
; ns
++)
408 srv
= (struct sockaddr_in
*)get_nsaddr(statp
, ns
);
409 if (srv
->sin_family
== inp
->sin_family
&&
410 srv
->sin_port
== inp
->sin_port
&&
411 (srv
->sin_addr
.s_addr
== INADDR_ANY
||
412 srv
->sin_addr
.s_addr
== inp
->sin_addr
.s_addr
))
417 if (EXT(statp
).ext
== NULL
) break;
418 in6p
= (const struct sockaddr_in6
*)sa
;
419 for (ns
= 0; ns
< statp
->nscount
; ns
++)
421 srv6
= (struct sockaddr_in6
*)get_nsaddr(statp
, ns
);
422 if (srv6
->sin6_family
== in6p
->sin6_family
&&
423 srv6
->sin6_port
== in6p
->sin6_port
&&
424 (IN6_IS_ADDR_UNSPECIFIED(&srv6
->sin6_addr
) ||
425 IN6_ARE_ADDR_EQUAL(&srv6
->sin6_addr
, &in6p
->sin6_addr
)))
436 * res_nameinquery(name, type, class, buf, eom)
437 * look for (name,type,class) in the query section of packet (buf,eom)
439 * buf + NS_HFIXEDSZ <= eom
445 * paul vixie, 29may94
448 res_nameinquery(const char *name
, int type
, int class, const u_char
*buf
, const u_char
*eom
)
450 const u_char
*cp
= buf
+ NS_HFIXEDSZ
;
451 int qdcount
= ntohs(((const HEADER
*)buf
)->qdcount
);
453 while (qdcount
-- > 0)
455 char tname
[NS_MAXDNAME
+1];
456 int n
, ttype
, tclass
;
458 n
= dn_expand(buf
, eom
, cp
, tname
, sizeof tname
);
459 if (n
< 0) return (-1);
462 if (cp
+ 2 * NS_INT16SZ
> eom
) return (-1);
464 ttype
= ns_get16(cp
); cp
+= NS_INT16SZ
;
465 tclass
= ns_get16(cp
); cp
+= NS_INT16SZ
;
466 if (ttype
== type
&& tclass
== class && ns_samename(tname
, name
) == 1) return (1);
473 * res_queriesmatch(buf1, eom1, buf2, eom2)
474 * is there a 1:1 mapping of (name,type,class)
475 * in (buf1,eom1) and (buf2,eom2)?
478 * 0 : not a 1:1 mapping
479 * >0 : is a 1:1 mapping
481 * paul vixie, 29may94
484 res_queriesmatch(const u_char
*buf1
, const u_char
*eom1
, const u_char
*buf2
, const u_char
*eom2
)
486 const u_char
*cp
= buf1
+ NS_HFIXEDSZ
;
487 int qdcount
= ntohs(((const HEADER
*)buf1
)->qdcount
);
489 if (buf1
+ NS_HFIXEDSZ
> eom1
|| buf2
+ NS_HFIXEDSZ
> eom2
)
493 * Only header section present in replies to
494 * dynamic update packets.
496 if ((((const HEADER
*)buf1
)->opcode
== ns_o_update
) &&
497 (((const HEADER
*)buf2
)->opcode
== ns_o_update
))
500 if (qdcount
!= ntohs(((const HEADER
*)buf2
)->qdcount
)) return (0);
502 while (qdcount
-- > 0)
504 char tname
[NS_MAXDNAME
+1];
505 int n
, ttype
, tclass
;
507 n
= dn_expand(buf1
, eom1
, cp
, tname
, sizeof tname
);
508 if (n
< 0) return (-1);
511 if (cp
+ 2 * NS_INT16SZ
> eom1
) return (-1);
513 ttype
= ns_get16(cp
); cp
+= NS_INT16SZ
;
514 tclass
= ns_get16(cp
); cp
+= NS_INT16SZ
;
515 if (!res_nameinquery(tname
, ttype
, tclass
, buf2
, eom2
)) return (0);
522 dns_res_send(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
, int *anssiz
, struct sockaddr
*from
, int *fromlen
)
524 int gotsomewhere
, terrno
, try, v_circuit
, resplen
, ns
;
525 char abuf
[NI_MAXHOST
];
527 int notify_token
, status
, send_status
, reply_buf_size
;
528 uint64_t exit_requested
;
530 if (statp
->nscount
== 0)
533 return DNS_RES_STATUS_INVALID_RES_STATE
;
536 reply_buf_size
= *anssiz
;
537 if (reply_buf_size
< NS_HFIXEDSZ
)
540 return DNS_RES_STATUS_INVALID_ARGUMENT
;
543 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_QUERY
), (stdout
, ";; res_send()\n"), buf
, buflen
);
545 v_circuit
= (statp
->options
& RES_USEVC
) || (buflen
> NS_PACKETSZ
);
551 * If the ns_addr_list in the resolver context has changed, then
552 * invalidate our cached copy and the associated timing data.
554 if (EXT(statp
).nscount
!= 0)
557 struct sockaddr_storage peer
;
558 ISC_SOCKLEN_T peerlen
;
560 if (EXT(statp
).nscount
!= statp
->nscount
)
566 for (ns
= 0; ns
< statp
->nscount
; ns
++)
568 if ((statp
->nsaddr_list
[ns
].sin_family
) && (EXT(statp
).ext
!= NULL
) && (!sock_eq((struct sockaddr
*)&statp
->nsaddr_list
[ns
], (struct sockaddr
*)&EXT(statp
).ext
->nsaddrs
[ns
])))
574 if (EXT(statp
).nssocks
[ns
] == -1) continue;
576 peerlen
= sizeof(peer
);
577 if (getsockname(EXT(statp
).nssocks
[ns
], (struct sockaddr
*)&peer
, &peerlen
) < 0)
583 if (!sock_eq((struct sockaddr
*)&peer
, get_nsaddr(statp
, ns
)))
594 EXT(statp
).nscount
= 0;
599 * Maybe initialize our private copy of the ns_addr_list.
601 if (EXT(statp
).nscount
== 0)
603 for (ns
= 0; ns
< statp
->nscount
; ns
++)
605 EXT(statp
).nstimes
[ns
] = RES_MAXTIME
;
606 EXT(statp
).nssocks
[ns
] = -1;
607 if (!statp
->nsaddr_list
[ns
].sin_family
) continue;
608 if (EXT(statp
).ext
!= NULL
) EXT(statp
).ext
->nsaddrs
[ns
].sin
= statp
->nsaddr_list
[ns
];
611 EXT(statp
).nscount
= statp
->nscount
;
615 * Some resolvers want to even out the load on their nameservers.
616 * Note that RES_BLAST overrides RES_ROTATE.
618 if (((statp
->options
& RES_ROTATE
) != 0) && ((statp
->options
& RES_BLAST
) == 0))
620 union res_sockaddr_union inu
;
621 struct sockaddr_in ina
;
622 int lastns
= statp
->nscount
- 1;
626 if (EXT(statp
).ext
!= NULL
) inu
= EXT(statp
).ext
->nsaddrs
[0];
627 ina
= statp
->nsaddr_list
[0];
628 fd
= EXT(statp
).nssocks
[0];
629 nstime
= EXT(statp
).nstimes
[0];
631 for (ns
= 0; ns
< lastns
; ns
++)
633 if (EXT(statp
).ext
!= NULL
)
635 EXT(statp
).ext
->nsaddrs
[ns
] =EXT(statp
).ext
->nsaddrs
[ns
+ 1];
638 statp
->nsaddr_list
[ns
] = statp
->nsaddr_list
[ns
+ 1];
639 EXT(statp
).nssocks
[ns
] = EXT(statp
).nssocks
[ns
+ 1];
640 EXT(statp
).nstimes
[ns
] = EXT(statp
).nstimes
[ns
+ 1];
643 if (EXT(statp
).ext
!= NULL
) EXT(statp
).ext
->nsaddrs
[lastns
] = inu
;
644 statp
->nsaddr_list
[lastns
] = ina
;
645 EXT(statp
).nssocks
[lastns
] = fd
;
646 EXT(statp
).nstimes
[lastns
] = nstime
;
650 * Get notification token
651 * we use a self-notification token to allow a caller
652 * to signal the thread doing this DNS query to quit.
657 asprintf(¬ify_name
, "self.thread.%lu", (unsigned long)pthread_self());
658 if (notify_name
!= NULL
)
660 status
= notify_register_plain(notify_name
, ¬ify_token
);
665 * Send request, RETRY times, or until successful.
667 for (try = 0; try < statp
->retry
; try++)
669 for (ns
= 0; ns
< statp
->nscount
; ns
++)
671 struct sockaddr
*nsap
;
673 nsap
= get_nsaddr(statp
, ns
);
674 nsaplen
= get_salen(nsap
);
680 int done
= 0, loops
= 0;
686 act
= (*statp
->qhook
)(&nsap
, &buf
, &buflen
, ans
, reply_buf_size
, &resplen
);
696 if (notify_token
!= -1) notify_cancel(notify_token
);
697 return DNS_RES_STATUS_CANCELLED
;
699 /* give the hook another try */
700 if (++loops
< MAX_HOOK_RETRIES
) break;
705 if (notify_token
!= -1) notify_cancel(notify_token
);
706 return DNS_RES_STATUS_CANCELLED
;
711 if (notify_token
!= -1)
714 status
= notify_get_state(notify_token
, &exit_requested
);
715 if (exit_requested
== ThreadStateExitRequested
)
717 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
719 notify_cancel(notify_token
);
720 return DNS_RES_STATUS_CANCELLED
;
724 Dprint(((statp
->options
& RES_DEBUG
) && getnameinfo(nsap
, nsaplen
, abuf
, sizeof(abuf
), NULL
, 0, niflags
) == 0), (stdout
, ";; Querying server (# %d) address = %s\n", ns
+ 1, abuf
));
726 send_status
= ns_r_noerror
;
730 /* Use VC; at most one attempt per server. */
733 *anssiz
= reply_buf_size
;
734 send_status
= send_vc(statp
, buf
, buflen
, ans
, anssiz
, &terrno
, ns
, from
, fromlen
, notify_token
);
739 send_status
= send_dg(statp
, buf
, buflen
, ans
, anssiz
, &terrno
, ns
, &v_circuit
, &gotsomewhere
, from
, fromlen
, notify_token
);
740 if (v_circuit
!= 0) goto send_same_ns
;
743 if ((send_status
== DNS_RES_STATUS_SYSTEM_ERROR
) || (send_status
== DNS_RES_STATUS_CANCELLED
))
746 if (notify_token
!= -1) notify_cancel(notify_token
);
750 if (send_status
!= ns_r_noerror
) goto send_next_ns
;
752 Dprint((statp
->options
& RES_DEBUG
) || ((statp
->pfcode
& RES_PRF_REPLY
) && (statp
->pfcode
& RES_PRF_HEAD1
)), (stdout
, ";; got answer:\n"));
753 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, "%s", ""), ans
, (*anssiz
> reply_buf_size
) ? reply_buf_size
: *anssiz
);
756 * If we have temporarily opened a virtual circuit,
757 * or if we haven't been asked to keep a socket open,
760 if (((v_circuit
!= 0) && (statp
->options
& RES_USEVC
) == 0) || (statp
->options
& RES_STAYOPEN
) == 0) res_nclose(statp
);
764 int done
= 0, loops
= 0;
770 act
= (*statp
->rhook
)(nsap
, buf
, buflen
, ans
, *anssiz
, &resplen
);
781 /* give the hook another try */
782 if (++loops
< MAX_HOOK_RETRIES
) break;
788 if (notify_token
!= -1) notify_cancel(notify_token
);
789 return DNS_RES_STATUS_CANCELLED
;
795 if (notify_token
!= -1) notify_cancel(notify_token
);
800 } /* foreach retry */
803 if (notify_token
!= -1) notify_cancel(notify_token
);
808 if (gotsomewhere
!= 0)
810 errno
= ECONNREFUSED
;
811 return DNS_RES_STATUS_CONNECTION_REFUSED
;
815 return DNS_RES_STATUS_TIMEOUT
;
824 res_nsend_2(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
, int anssiz
, struct sockaddr
*from
, int *fromlen
)
829 status
= dns_res_send(statp
, buf
, buflen
, ans
, &len
, from
, fromlen
);
830 if (status
!= ns_r_noerror
) len
= -1;
835 res_nsend(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
, int anssiz
)
837 struct sockaddr_storage from
;
840 fromlen
= sizeof(struct sockaddr_storage
);
842 return res_nsend_2(statp
, buf
, buflen
, ans
, anssiz
, (struct sockaddr
*)&from
, &fromlen
);
848 get_salen(const struct sockaddr
*sa
)
851 /* There are people do not set sa_len. Be forgiving to them. */
852 if (sa
->sa_len
) return (sa
->sa_len
);
855 if (sa
->sa_family
== AF_INET
) return (sizeof(struct sockaddr_in
));
856 else if (sa
->sa_family
== AF_INET6
) return (sizeof(struct sockaddr_in6
));
857 else return (0); /* unknown, die on connect */
861 * pick appropriate nsaddr_list for use. see res_init() for initialization.
864 get_nsaddr(res_state statp
, size_t n
)
866 if ((!statp
->nsaddr_list
[n
].sin_family
) && (EXT(statp
).ext
!= NULL
))
869 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
870 * than struct sockaddr, and
871 * - user code did not update statp->nsaddr_list[n].
873 return (struct sockaddr
*)(void *)&EXT(statp
).ext
->nsaddrs
[n
];
878 * - user code updated statp->nsaddr_list[n], or
879 * - statp->nsaddr_list[n] has the same content as
880 * EXT(statp).ext->nsaddrs[n].
882 return (struct sockaddr
*)(void *)&statp
->nsaddr_list
[n
];
887 send_vc(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
, int *anssiz
, int *terrno
, int ns
, struct sockaddr
*from
, int *fromlen
, int notify_token
)
889 const HEADER
*hp
= (const HEADER
*) buf
;
890 HEADER
*anhp
= (HEADER
*) ans
;
891 struct sockaddr
*nsap
;
893 int truncating
, connreset
, resplen
, n
;
899 uint64_t exit_requested
;
901 nsap
= get_nsaddr(statp
, ns
);
902 nsaplen
= get_salen(nsap
);
908 if (notify_token
!= -1)
911 status
= notify_get_state(notify_token
, &exit_requested
);
912 if (exit_requested
== ThreadStateExitRequested
)
914 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
916 return DNS_RES_STATUS_CANCELLED
;
922 /* Are we still talking to whom we want to talk? */
923 if (statp
->_vcsock
>= 0 && (statp
->_flags
& RES_F_VC
) != 0)
925 struct sockaddr_storage peer
;
926 ISC_SOCKLEN_T size
= sizeof peer
;
928 if (getpeername(statp
->_vcsock
, (struct sockaddr
*)&peer
, &size
) < 0 || !sock_eq((struct sockaddr
*)&peer
, nsap
))
931 statp
->_flags
&= ~RES_F_VC
;
935 if ((statp
->_vcsock
< 0) || ((statp
->_flags
& RES_F_VC
) == 0))
937 if (statp
->_vcsock
>= 0) res_nclose(statp
);
939 statp
->_vcsock
= socket(nsap
->sa_family
, SOCK_STREAM
, 0);
940 if (statp
->_vcsock
> highestFD
)
946 if (statp
->_vcsock
< 0)
949 Perror(statp
, stderr
, "socket(vc)", errno
);
950 return DNS_RES_STATUS_SYSTEM_ERROR
;
954 if (connect(statp
->_vcsock
, nsap
, nsaplen
) < 0)
957 Aerror(statp
, stderr
, "connect(vc)", errno
, nsap
, nsaplen
);
959 return DNS_RES_STATUS_CONNECTION_REFUSED
;
962 statp
->_flags
|= RES_F_VC
;
966 * Send length & message
968 putshort((u_short
)buflen
, (u_char
*)&len
);
969 iov
[0] = evConsIovec(&len
, NS_INT16SZ
);
975 iov
[1] = evConsIovec(tmp
, buflen
);
976 if (writev(statp
->_vcsock
, iov
, 2) != (NS_INT16SZ
+ buflen
))
979 Perror(statp
, stderr
, "write failed", errno
);
981 return DNS_RES_STATUS_CONNECTION_FAILED
;
985 * Receive length & response
989 if (notify_token
!= -1)
992 status
= notify_get_state(notify_token
, &exit_requested
);
993 if (exit_requested
== ThreadStateExitRequested
)
995 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
997 return DNS_RES_STATUS_CANCELLED
;
1003 while ((n
= read(statp
->_vcsock
, (char *)cp
, (int)len
)) > 0)
1006 if ((len
-= n
) <= 0) break;
1012 Perror(statp
, stderr
, "read failed", errno
);
1016 * A long running process might get its TCP
1017 * connection reset if the remote server was
1018 * restarted. Requery the server instead of
1019 * trying a new one. When there is only one
1020 * server, this means that a query might work
1021 * instead of failing. We only allow one reset
1022 * per query to prevent looping.
1024 if (*terrno
== ECONNRESET
&& !connreset
)
1032 return DNS_RES_STATUS_CONNECTION_FAILED
;
1035 resplen
= ns_get16(ans
);
1036 if (resplen
> *anssiz
)
1038 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; response truncated\n"));
1047 if (len
< NS_HFIXEDSZ
)
1050 * Undersized message.
1052 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; undersized: %d\n", len
));
1056 return DNS_RES_STATUS_INVALID_REPLY
;
1060 while (len
!= 0 && (n
= read(statp
->_vcsock
, (char *)cp
, (int)len
)) > 0)
1069 Perror(statp
, stderr
, "read(vc)", errno
);
1071 return DNS_RES_STATUS_CONNECTION_FAILED
;
1077 * Flush rest of answer so connection stays in synch.
1080 len
= resplen
- *anssiz
;
1083 char junk
[NS_PACKETSZ
];
1085 n
= read(statp
->_vcsock
, junk
, (len
> sizeof junk
) ? sizeof junk
: len
);
1086 if (n
> 0) len
-= n
;
1092 * If the calling applicating has bailed out of
1093 * a previous call and failed to arrange to have
1094 * the circuit closed or the server has got
1095 * itself confused, then drop the packet and
1096 * wait for the correct one.
1098 if (hp
->id
!= anhp
->id
)
1100 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, ";; old answer (unexpected):\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1105 * All is well, or the error is fatal. Signal that the
1106 * next nameserver ought not be tried.
1109 *fromlen
= sizeof(nsap
);
1110 memcpy(from
, &nsap
, *fromlen
);
1112 return ns_r_noerror
;
1116 internal_recvfrom(int s
, void *buf
, size_t len
, struct sockaddr
*from
, int *fromlen
, int *iface
)
1118 struct sockaddr_dl
*sdl
;
1119 struct iovec databuffers
= { buf
, len
};
1122 struct cmsghdr
*cmp
;
1123 char ancillary
[1024], ifname
[IF_NAMESIZE
];
1124 struct in6_pktinfo
*ip6_info
;
1125 struct sockaddr_in
*s4
;
1126 struct sockaddr_in6
*s6
;
1128 memset(&msg
, 0, sizeof(struct msghdr
));
1129 msg
.msg_name
= (caddr_t
)from
;
1130 msg
.msg_namelen
= *fromlen
;
1131 msg
.msg_iov
= &databuffers
;
1133 msg
.msg_control
= (caddr_t
)&ancillary
;
1134 msg
.msg_controllen
= sizeof(ancillary
);
1136 /* Receive the data */
1137 n
= recvmsg(s
, &msg
, 0);
1138 if ((n
< 0) || (msg
.msg_controllen
< sizeof(struct cmsghdr
)) || (msg
.msg_flags
& MSG_CTRUNC
))
1143 *fromlen
= msg
.msg_namelen
;
1145 s4
= (struct sockaddr_in
*)from
;
1146 s6
= (struct sockaddr_in6
*)from
;
1148 for (cmp
= CMSG_FIRSTHDR(&msg
); cmp
; cmp
= CMSG_NXTHDR(&msg
, cmp
))
1150 if ((cmp
->cmsg_level
== IPPROTO_IP
) && (cmp
->cmsg_type
== IP_RECVIF
))
1152 sdl
= (struct sockaddr_dl
*)CMSG_DATA(cmp
);
1153 if (sdl
->sdl_nlen
< IF_NAMESIZE
)
1155 memcpy(ifname
, sdl
->sdl_data
, sdl
->sdl_nlen
);
1156 ifname
[sdl
->sdl_nlen
] = 0;
1157 *iface
= if_nametoindex(ifname
);
1160 else if ((cmp
->cmsg_level
== IPPROTO_IPV6
) && (cmp
->cmsg_type
== IPV6_PKTINFO
))
1162 ip6_info
= (struct in6_pktinfo
*)CMSG_DATA(cmp
);
1163 *iface
= ip6_info
->ipi6_ifindex
;
1171 send_dg(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
, int *anssiz
, int *terrno
, int ns
, int *v_circuit
, int *gotsomewhere
, struct sockaddr
*from
, int *fromlen
, int notify_token
)
1173 const HEADER
*hp
= (const HEADER
*) buf
;
1174 HEADER
*anhp
= (HEADER
*) ans
;
1175 const struct sockaddr
*nsap
;
1177 struct timespec now
, timeout
, finish
;
1179 int iface
, rif
, status
;
1180 uint64_t exit_requested
;
1181 int *interrupt_pipe
;
1183 struct sockaddr_storage from
;
1184 ISC_SOCKLEN_T fromlen
;
1186 int resplen
, seconds
, ntry
, n
, s
;
1191 interrupt_pipe
= NULL
;
1193 nsap
= get_nsaddr(statp
, ns
);
1194 nsaplen
= get_salen(nsap
);
1195 if (EXT(statp
).nssocks
[ns
] == -1)
1197 EXT(statp
).nssocks
[ns
] = socket(nsap
->sa_family
, SOCK_DGRAM
, 0);
1198 if (EXT(statp
).nssocks
[ns
] > highestFD
)
1204 if (EXT(statp
).nssocks
[ns
] < 0)
1207 Perror(statp
, stderr
, "socket(dg)", errno
);
1208 return DNS_RES_STATUS_SYSTEM_ERROR
;
1211 bind_random(EXT(statp
).nssocks
[ns
], nsap
->sa_family
);
1213 #ifndef CANNOT_CONNECT_DGRAM
1215 * On a 4.3BSD+ machine (client and server,
1216 * actually), sending to a nameserver datagram
1217 * port with no nameserver will cause an
1218 * ICMP port unreachable message to be returned.
1219 * If our datagram socket is "connected" to the
1220 * server, we get an ECONNREFUSED error on the next
1221 * socket operation, and select returns if the
1222 * error message is received. We can thus detect
1223 * the absence of a nameserver without timing out.
1225 if (connect(EXT(statp
).nssocks
[ns
], nsap
, nsaplen
) < 0)
1227 Aerror(statp
, stderr
, "connect(dg)", errno
, nsap
, nsaplen
);
1229 return DNS_RES_STATUS_CONNECTION_REFUSED
;
1232 #endif /* !CANNOT_CONNECT_DGRAM */
1233 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; new DG socket\n"))
1236 s
= EXT(statp
).nssocks
[ns
];
1238 setsockopt(s
, IPPROTO_IP
, IP_RECVIF
, &rif
, sizeof(int));
1239 setsockopt(s
, IPPROTO_IPV6
, IPV6_PKTINFO
, &rif
, sizeof(int));
1244 if ((nsap
->sa_family
== AF_INET
) && (IN_MULTICAST(ntohl(((struct sockaddr_in
*)nsap
)->sin_addr
.s_addr
)))) multicast
= AF_INET
;
1245 else if ((nsap
->sa_family
== AF_INET6
) && (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6
*)nsap
)->sin6_addr
))) multicast
= AF_INET6
;
1249 struct ifaddrs
*ifa
, *p
;
1250 struct sockaddr_in
*sin4
;
1251 struct sockaddr_in6
*sin6
;
1254 if (getifaddrs(&ifa
) < 0)
1256 Aerror(statp
, stderr
, "getifaddrs", errno
, nsap
, nsaplen
);
1258 return DNS_RES_STATUS_SYSTEM_ERROR
;
1261 for (p
= ifa
; p
!= NULL
; p
= p
->ifa_next
)
1263 if (p
->ifa_addr
== NULL
) continue;
1264 if ((p
->ifa_flags
& IFF_UP
) == 0) continue;
1265 if (p
->ifa_addr
->sa_family
!= multicast
) continue;
1266 if ((p
->ifa_flags
& IFF_MULTICAST
) == 0) continue;
1267 if ((p
->ifa_flags
& IFF_POINTOPOINT
) != 0)
1269 if ((multicast
== AF_INET
) && (ntohl(((struct sockaddr_in
*)nsap
)->sin_addr
.s_addr
) <= INADDR_MAX_LOCAL_GROUP
)) continue;
1272 sin4
= (struct sockaddr_in
*)p
->ifa_addr
;
1273 sin6
= (struct sockaddr_in6
*)p
->ifa_addr
;
1275 if (multicast
== AF_INET
) i
= setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_IF
, &sin4
->sin_addr
, sizeof(sin4
->sin_addr
));
1276 else if (multicast
== AF_INET6
)
1278 ifnum
= if_nametoindex(p
->ifa_name
);
1279 ((struct sockaddr_in6
*)nsap
)->sin6_scope_id
= ifnum
;
1280 i
= setsockopt(s
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, &ifnum
, sizeof(ifnum
));
1285 Aerror(statp
, stderr
, "setsockopt", errno
, nsap
, nsaplen
);
1286 if (multicast
== AF_INET6
) ((struct sockaddr_in6
*)nsap
)->sin6_scope_id
= 0;
1291 if (sendto(s
, (const char*)buf
, buflen
, 0, nsap
, nsaplen
) != buflen
)
1293 Aerror(statp
, stderr
, "sendto", errno
, nsap
, nsaplen
);
1294 if (multicast
== AF_INET6
) ((struct sockaddr_in6
*)nsap
)->sin6_scope_id
= 0;
1298 if (multicast
== AF_INET6
) ((struct sockaddr_in6
*)nsap
)->sin6_scope_id
= 0;
1306 #endif /* MULTICAST */
1308 #ifndef CANNOT_CONNECT_DGRAM
1309 if (send(s
, (const char*)buf
, buflen
, 0) != buflen
)
1311 Perror(statp
, stderr
, "send", errno
);
1313 return DNS_RES_STATUS_CONNECTION_FAILED
;
1316 #else /* !CANNOT_CONNECT_DGRAM */
1317 if (sendto(s
, (const char*)buf
, buflen
, 0, nsap
, nsaplen
) != buflen
)
1319 Aerror(statp
, stderr
, "sendto", errno
, nsap
, nsaplen
);
1321 return DNS_RES_STATUS_CONNECTION_FAILED
;
1323 #endif /* !CANNOT_CONNECT_DGRAM */
1327 #endif /* MULTICAST */
1333 ntry
= statp
->nscount
* statp
->retry
;
1334 seconds
= statp
->retrans
/ ntry
;
1335 if (seconds
<= 0) seconds
= 1;
1336 timeout
.tv_sec
= seconds
;
1337 timeout
.tv_nsec
= ((statp
->retrans
- (seconds
* ntry
)) * 1000) / ntry
;
1338 timeout
.tv_nsec
*= 1000000;
1340 finish
= evAddTime(now
, timeout
);
1342 if (interrupt_pipe_enabled
!= 0) interrupt_pipe
= pthread_getspecific(interrupt_pipe_key
);
1344 seconds
= (statp
->retrans
<< ns
);
1345 if (ns
> 0) seconds
/= statp
->nscount
;
1346 if (seconds
<= 0) seconds
= 1;
1348 timeout
= evConsTime(seconds
, 0);
1349 finish
= evAddTime(now
, timeout
);
1350 #endif /* __APPLE__ */
1358 if (notify_token
!= -1)
1361 status
= notify_get_state(notify_token
, &exit_requested
);
1362 if (exit_requested
== ThreadStateExitRequested
)
1364 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
1365 return DNS_RES_STATUS_CANCELLED
;
1373 if ((interrupt_pipe_enabled
!= 0) && (interrupt_pipe
!= NULL
))
1375 if (interrupt_pipe
[0] >= 0)
1377 FD_SET(interrupt_pipe
[0], &dsmask
);
1378 nfds
= MAX(s
, interrupt_pipe
[0]) + 1;
1382 if (evCmpTime(finish
, now
) > 0) timeout
= evSubTime(finish
, now
);
1383 else timeout
= evConsTime(0, 0);
1385 #ifdef USE_DNS_PSELECT
1386 n
= dns_pselect(nfds
, &dsmask
, NULL
, NULL
, &timeout
, NULL
);
1388 n
= pselect(nfds
, &dsmask
, NULL
, NULL
, &timeout
, NULL
);
1392 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; timeout\n"));
1394 return DNS_RES_STATUS_TIMEOUT
;
1399 if (errno
== EINTR
) goto wait
;
1400 Perror(statp
, stderr
, "select", errno
);
1402 return DNS_RES_STATUS_SYSTEM_ERROR
;
1405 /* socket s and/or interrupt pipe got data */
1406 if ((interrupt_pipe_enabled
!= 0) && (interrupt_pipe
!= NULL
) && ((interrupt_pipe
[0] < 0) || (FD_ISSET(interrupt_pipe
[0], &dsmask
))))
1408 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
1409 return DNS_RES_STATUS_CANCELLED
;
1414 resplen
= internal_recvfrom(s
, (char *)ans
, *anssiz
, from
, fromlen
, &iface
);
1417 Perror(statp
, stderr
, "recvfrom", errno
);
1419 return DNS_RES_STATUS_CONNECTION_FAILED
;
1422 if (nsap
->sa_family
== AF_INET
) memcpy(((struct sockaddr_in
*)from
)->sin_zero
, &iface
, 4);
1423 else if (nsap
->sa_family
== AF_INET6
) ((struct sockaddr_in6
*)from
)->sin6_scope_id
= iface
;
1426 if (resplen
< NS_HFIXEDSZ
)
1429 * Undersized message.
1431 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; undersized: %d\n", resplen
));
1434 return DNS_RES_STATUS_INVALID_REPLY
;
1437 if (hp
->id
!= anhp
->id
)
1440 * response from old query, ignore it.
1441 * XXX - potential security hazard could
1444 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, ";; old answer:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1451 #endif /* MULTICAST */
1453 if (!(statp
->options
& RES_INSECURE1
) && !res_ourserver_p(statp
, from
))
1456 * response from wrong server? ignore it.
1457 * XXX - potential security hazard could
1460 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, ";; not our server:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1466 #endif /* MULTICAST */
1468 #ifdef RES_USE_EDNS0
1469 if (anhp
->rcode
== ns_r_formerr
&& (statp
->options
& RES_USE_EDNS0
) != 0)
1472 * Do not retry if the server do not understand EDNS0.
1473 * The case has to be captured here, as FORMERR packet do not
1474 * carry query section, hence res_queriesmatch() returns 0.
1476 DprintQ(statp
->options
& RES_DEBUG
, (stdout
, "server rejected query with EDNS0:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1477 /* record the error */
1478 statp
->_flags
|= RES_F_EDNS0ERR
;
1480 return DNS_RES_STATUS_CONNECTION_REFUSED
;
1484 if (!(statp
->options
& RES_INSECURE2
) && !res_queriesmatch(buf
, buf
+ buflen
, ans
, ans
+ *anssiz
))
1487 * response contains wrong query? ignore it.
1488 * XXX - potential security hazard could
1491 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, ";; wrong query name:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1493 return DNS_RES_STATUS_INVALID_REPLY
;
1496 if (anhp
->rcode
== ns_r_servfail
|| anhp
->rcode
== ns_r_notimpl
|| anhp
->rcode
== ns_r_refused
)
1498 DprintQ(statp
->options
& RES_DEBUG
, (stdout
, "server rejected query:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1500 /* don't retry if called from dig */
1501 if (!statp
->pfcode
) return anhp
->rcode
;
1504 if (!(statp
->options
& RES_IGNTC
) && anhp
->tc
)
1507 * To get the rest of answer,
1508 * use TCP with same server.
1510 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; truncated answer\n"));
1513 return ns_r_noerror
;
1517 * All is well, or the error is fatal. Signal that the
1518 * next nameserver ought not be tried.
1521 return ns_r_noerror
;
1525 Aerror(const res_state statp
, FILE *file
, const char *string
, int error
, const struct sockaddr
*address
, int alen
)
1528 char hbuf
[NI_MAXHOST
];
1529 char sbuf
[NI_MAXSERV
];
1531 if ((statp
->options
& RES_DEBUG
) != 0)
1533 if (getnameinfo(address
, alen
, hbuf
, sizeof(hbuf
), sbuf
, sizeof(sbuf
), niflags
))
1535 strncpy(hbuf
, "?", sizeof(hbuf
) - 1);
1536 hbuf
[sizeof(hbuf
) - 1] = '\0';
1537 strncpy(sbuf
, "?", sizeof(sbuf
) - 1);
1538 sbuf
[sizeof(sbuf
) - 1] = '\0';
1541 fprintf(file
, "res_send: %s ([%s].%s): %s\n", string
, hbuf
, sbuf
, strerror(error
));
1548 Perror(const res_state statp
, FILE *file
, const char *string
, int error
)
1552 if ((statp
->options
& RES_DEBUG
) != 0) fprintf(file
, "res_send: %s: %s\n", string
, strerror(error
));
1557 sock_eq(struct sockaddr
*a
, struct sockaddr
*b
)
1559 struct sockaddr_in
*a4
, *b4
;
1560 struct sockaddr_in6
*a6
, *b6
;
1562 if (a
->sa_family
!= b
->sa_family
) return 0;
1564 switch (a
->sa_family
)
1567 a4
= (struct sockaddr_in
*)a
;
1568 b4
= (struct sockaddr_in
*)b
;
1569 return a4
->sin_port
== b4
->sin_port
&& a4
->sin_addr
.s_addr
== b4
->sin_addr
.s_addr
;
1571 a6
= (struct sockaddr_in6
*)a
;
1572 b6
= (struct sockaddr_in6
*)b
;
1573 return a6
->sin6_port
== b6
->sin6_port
&&
1574 #ifdef HAVE_SIN6_SCOPE_ID
1575 a6
->sin6_scope_id
== b6
->sin6_scope_id
&&
1577 IN6_ARE_ADDR_EQUAL(&a6
->sin6_addr
, &b6
->sin6_addr
);
1583 #ifdef USE_DNS_PSELECT
1585 dns_pselect(int nfds
, void *rfds
, void *wfds
, void *efds
, struct timespec
*tsp
, const sigset_t
*sigmask
)
1587 struct timeval tv
, *tvp
= NULL
;
1594 tv
= evTimeVal(*tsp
);
1597 if (sigmask
) sigprocmask(SIG_SETMASK
, sigmask
, &sigs
);
1598 n
= select(nfds
, rfds
, wfds
, efds
, tvp
);
1599 if (sigmask
) sigprocmask(SIG_SETMASK
, &sigs
, NULL
);
1600 if (tsp
) *tsp
= evTimeSpec(tv
);