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"
85 #include <sys/types.h>
86 #include <sys/param.h>
88 #include <sys/socket.h>
91 #include <netinet/in.h>
92 #include <arpa/nameser.h>
93 #include <arpa/inet.h>
107 #include <net/if_dl.h>
108 #include "res_private.h"
111 #include <isc/eventlib.h>
112 #include "port_after.h"
116 #define ISC_SOCKLEN_T unsigned int
119 /* Options. Leave them on. */
121 #define CANNOT_CONNECT_DGRAM
126 #include "res_debug.h"
127 #include "res_private.h"
128 #include <sys/fcntl.h>
130 #define EXT(res) ((res)->_u._ext)
132 static const int highestFD
= FD_SETSIZE
- 1;
134 #define MAX_HOOK_RETRIES 42
136 /* port randomization */
137 #define RANDOM_BIND_MAX_TRIES 16
138 #define RANDOM_BIND_FIRST IPPORT_HIFIRSTAUTO
139 #define RANDOM_BIND_LAST IPPORT_HILASTAUTO
143 static int get_salen
__P((const struct sockaddr
*));
144 static int send_vc(res_state
, const u_char
*, int, u_char
*, int *, int *, int, struct sockaddr
*, int *, int);
145 static int send_dg(res_state
, const u_char
*, int, u_char
*, int *, int *, int, int *, int *, struct sockaddr
*, int *, int);
146 static void Aerror(const res_state
, FILE *, const char *, int, const struct sockaddr
*, int);
147 static void Perror(const res_state
, FILE *, const char *, int);
148 static int sock_eq(struct sockaddr
*, struct sockaddr
*);
150 static int pselect(int, void *, void *, void *, struct timespec
*, const sigset_t
*);
153 static const int niflags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
154 static int interrupt_pipe_enabled
= 0;
155 static pthread_key_t interrupt_pipe_key
;
158 bind_random(int sock
)
162 struct sockaddr_in local
;
167 for (i
= 0; (i
< RANDOM_BIND_MAX_TRIES
) && (status
< 0); i
++)
169 /* random port in the range RANDOM_BIND_FIRST to RANDOM_BIND_LAST */
170 src_port
= (res_randomid() % (RANDOM_BIND_LAST
- RANDOM_BIND_FIRST
)) + RANDOM_BIND_FIRST
;
171 memset(&local
, 0, sizeof(struct sockaddr_in
));
172 local
.sin_port
= htons(src_port
);
174 status
= bind(sock
, (struct sockaddr
*)&local
, sizeof(struct sockaddr_in
));
181 res_delete_interrupt_token(void *token
)
185 interrupt_pipe
= token
;
186 if (interrupt_pipe
== NULL
) return;
188 if (interrupt_pipe
[0] >= 0)
190 close(interrupt_pipe
[0]);
191 interrupt_pipe
[0] = -1;
194 if (interrupt_pipe
[1] >= 0)
196 close(interrupt_pipe
[1]);
197 interrupt_pipe
[1] = -1;
200 pthread_setspecific(interrupt_pipe_key
, NULL
);
201 free(interrupt_pipe
);
205 res_init_interrupt_token(void)
209 interrupt_pipe
= (int *)malloc(2 * sizeof(int));
210 if (interrupt_pipe
== NULL
) return NULL
;
212 if (pipe(interrupt_pipe
) < 0)
214 /* this shouldn't happen */
215 interrupt_pipe
[0] = -1;
216 interrupt_pipe
[1] = -1;
220 fcntl(interrupt_pipe
[0], F_SETFD
, FD_CLOEXEC
| O_NONBLOCK
);
221 fcntl(interrupt_pipe
[1], F_SETFD
, FD_CLOEXEC
| O_NONBLOCK
);
224 pthread_setspecific(interrupt_pipe_key
, interrupt_pipe
);
226 return interrupt_pipe
;
230 res_interrupt_requests_enable(void)
232 interrupt_pipe_enabled
= 1;
233 pthread_key_create(&interrupt_pipe_key
, NULL
);
237 res_interrupt_requests_disable(void)
239 interrupt_pipe_enabled
= 0;
240 pthread_key_delete(interrupt_pipe_key
);
244 res_interrupt_request(void *token
)
249 interrupt_pipe
= token
;
251 if ((interrupt_pipe
== NULL
) || (interrupt_pipe_enabled
== 0)) return;
253 oldwrite
= interrupt_pipe
[1];
254 interrupt_pipe
[1] = -1;
256 if (oldwrite
>= 0) close(oldwrite
);
261 evConsIovec(void *buf
, size_t cnt
)
265 memset(&ret
, 0xf5, sizeof ret
);
271 static struct timespec
272 evConsTime(time_t sec
, long nsec
)
281 static struct timespec
282 evTimeSpec(struct timeval tv
)
286 ts
.tv_sec
= tv
.tv_sec
;
287 ts
.tv_nsec
= tv
.tv_usec
* 1000;
291 static struct timespec
296 if (gettimeofday(&now
, NULL
) < 0) return (evConsTime(0, 0));
297 return (evTimeSpec(now
));
301 static struct timeval
302 evTimeVal(struct timespec ts
)
306 tv
.tv_sec
= ts
.tv_sec
;
307 tv
.tv_usec
= ts
.tv_nsec
/ 1000;
312 #define BILLION 1000000000
313 static struct timespec
314 evAddTime(struct timespec addend1
, struct timespec addend2
)
318 x
.tv_sec
= addend1
.tv_sec
+ addend2
.tv_sec
;
319 x
.tv_nsec
= addend1
.tv_nsec
+ addend2
.tv_nsec
;
320 if (x
.tv_nsec
>= BILLION
)
323 x
.tv_nsec
-= BILLION
;
329 static struct timespec
330 evSubTime(struct timespec minuend
, struct timespec subtrahend
)
334 x
.tv_sec
= minuend
.tv_sec
- subtrahend
.tv_sec
;
335 if (minuend
.tv_nsec
>= subtrahend
.tv_nsec
)
337 x
.tv_nsec
= minuend
.tv_nsec
- subtrahend
.tv_nsec
;
341 x
.tv_nsec
= BILLION
- subtrahend
.tv_nsec
+ minuend
.tv_nsec
;
349 evCmpTime(struct timespec a
, struct timespec b
)
351 long x
= a
.tv_sec
- b
.tv_sec
;
353 if (x
== 0L) x
= a
.tv_nsec
- b
.tv_nsec
;
354 return (x
< 0L ? (-1) : x
> 0L ? (1) : (0));
357 #endif /* __APPLE__ */
362 * res_isourserver(ina)
363 * looks up "ina" in _res.ns_addr_list[]
368 * paul vixie, 29may94
371 res_ourserver_p(const res_state statp
, const struct sockaddr
*sa
)
373 const struct sockaddr_in
*inp
, *srv
;
374 const struct sockaddr_in6
*in6p
, *srv6
;
377 switch (sa
->sa_family
)
380 inp
= (const struct sockaddr_in
*)sa
;
381 for (ns
= 0; ns
< statp
->nscount
; ns
++)
383 srv
= (struct sockaddr_in
*)get_nsaddr(statp
, ns
);
384 if (srv
->sin_family
== inp
->sin_family
&&
385 srv
->sin_port
== inp
->sin_port
&&
386 (srv
->sin_addr
.s_addr
== INADDR_ANY
||
387 srv
->sin_addr
.s_addr
== inp
->sin_addr
.s_addr
))
392 if (EXT(statp
).ext
== NULL
) break;
393 in6p
= (const struct sockaddr_in6
*)sa
;
394 for (ns
= 0; ns
< statp
->nscount
; ns
++)
396 srv6
= (struct sockaddr_in6
*)get_nsaddr(statp
, ns
);
397 if (srv6
->sin6_family
== in6p
->sin6_family
&&
398 srv6
->sin6_port
== in6p
->sin6_port
&&
399 (IN6_IS_ADDR_UNSPECIFIED(&srv6
->sin6_addr
) ||
400 IN6_ARE_ADDR_EQUAL(&srv6
->sin6_addr
, &in6p
->sin6_addr
)))
411 * res_nameinquery(name, type, class, buf, eom)
412 * look for (name,type,class) in the query section of packet (buf,eom)
414 * buf + NS_HFIXEDSZ <= eom
420 * paul vixie, 29may94
423 res_nameinquery(const char *name
, int type
, int class, const u_char
*buf
, const u_char
*eom
)
425 const u_char
*cp
= buf
+ NS_HFIXEDSZ
;
426 int qdcount
= ntohs(((const HEADER
*)buf
)->qdcount
);
428 while (qdcount
-- > 0)
430 char tname
[NS_MAXDNAME
+1];
431 int n
, ttype
, tclass
;
433 n
= dn_expand(buf
, eom
, cp
, tname
, sizeof tname
);
434 if (n
< 0) return (-1);
437 if (cp
+ 2 * NS_INT16SZ
> eom
) return (-1);
439 ttype
= ns_get16(cp
); cp
+= NS_INT16SZ
;
440 tclass
= ns_get16(cp
); cp
+= NS_INT16SZ
;
441 if (ttype
== type
&& tclass
== class && ns_samename(tname
, name
) == 1) return (1);
448 * res_queriesmatch(buf1, eom1, buf2, eom2)
449 * is there a 1:1 mapping of (name,type,class)
450 * in (buf1,eom1) and (buf2,eom2)?
453 * 0 : not a 1:1 mapping
454 * >0 : is a 1:1 mapping
456 * paul vixie, 29may94
459 res_queriesmatch(const u_char
*buf1
, const u_char
*eom1
, const u_char
*buf2
, const u_char
*eom2
)
461 const u_char
*cp
= buf1
+ NS_HFIXEDSZ
;
462 int qdcount
= ntohs(((const HEADER
*)buf1
)->qdcount
);
464 if (buf1
+ NS_HFIXEDSZ
> eom1
|| buf2
+ NS_HFIXEDSZ
> eom2
)
468 * Only header section present in replies to
469 * dynamic update packets.
471 if ((((const HEADER
*)buf1
)->opcode
== ns_o_update
) &&
472 (((const HEADER
*)buf2
)->opcode
== ns_o_update
))
475 if (qdcount
!= ntohs(((const HEADER
*)buf2
)->qdcount
)) return (0);
477 while (qdcount
-- > 0)
479 char tname
[NS_MAXDNAME
+1];
480 int n
, ttype
, tclass
;
482 n
= dn_expand(buf1
, eom1
, cp
, tname
, sizeof tname
);
483 if (n
< 0) return (-1);
486 if (cp
+ 2 * NS_INT16SZ
> eom1
) return (-1);
488 ttype
= ns_get16(cp
); cp
+= NS_INT16SZ
;
489 tclass
= ns_get16(cp
); cp
+= NS_INT16SZ
;
490 if (!res_nameinquery(tname
, ttype
, tclass
, buf2
, eom2
)) return (0);
497 dns_res_send(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
, int *anssiz
, struct sockaddr
*from
, int *fromlen
)
499 int gotsomewhere
, terrno
, try, v_circuit
, resplen
, ns
;
500 char abuf
[NI_MAXHOST
];
502 int notify_token
, status
, send_status
, reply_buf_size
;
503 uint64_t exit_requested
;
505 if (statp
->nscount
== 0)
508 return DNS_RES_STATUS_INVALID_RES_STATE
;
511 reply_buf_size
= *anssiz
;
512 if (reply_buf_size
< NS_HFIXEDSZ
)
515 return DNS_RES_STATUS_INVALID_ARGUMENT
;
518 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_QUERY
), (stdout
, ";; res_send()\n"), buf
, buflen
);
520 v_circuit
= (statp
->options
& RES_USEVC
) || (buflen
> NS_PACKETSZ
);
526 * If the ns_addr_list in the resolver context has changed, then
527 * invalidate our cached copy and the associated timing data.
529 if (EXT(statp
).nscount
!= 0)
532 struct sockaddr_storage peer
;
533 ISC_SOCKLEN_T peerlen
;
535 if (EXT(statp
).nscount
!= statp
->nscount
)
541 for (ns
= 0; ns
< statp
->nscount
; ns
++)
543 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
])))
549 if (EXT(statp
).nssocks
[ns
] == -1) continue;
551 peerlen
= sizeof(peer
);
552 if (getsockname(EXT(statp
).nssocks
[ns
], (struct sockaddr
*)&peer
, &peerlen
) < 0)
558 if (!sock_eq((struct sockaddr
*)&peer
, get_nsaddr(statp
, ns
)))
569 EXT(statp
).nscount
= 0;
574 * Maybe initialize our private copy of the ns_addr_list.
576 if (EXT(statp
).nscount
== 0)
578 for (ns
= 0; ns
< statp
->nscount
; ns
++)
580 EXT(statp
).nstimes
[ns
] = RES_MAXTIME
;
581 EXT(statp
).nssocks
[ns
] = -1;
582 if (!statp
->nsaddr_list
[ns
].sin_family
) continue;
583 if (EXT(statp
).ext
!= NULL
) EXT(statp
).ext
->nsaddrs
[ns
].sin
= statp
->nsaddr_list
[ns
];
586 EXT(statp
).nscount
= statp
->nscount
;
590 * Some resolvers want to even out the load on their nameservers.
591 * Note that RES_BLAST overrides RES_ROTATE.
593 if (((statp
->options
& RES_ROTATE
) != 0) && ((statp
->options
& RES_BLAST
) == 0))
595 union res_sockaddr_union inu
;
596 struct sockaddr_in ina
;
597 int lastns
= statp
->nscount
- 1;
601 if (EXT(statp
).ext
!= NULL
) inu
= EXT(statp
).ext
->nsaddrs
[0];
602 ina
= statp
->nsaddr_list
[0];
603 fd
= EXT(statp
).nssocks
[0];
604 nstime
= EXT(statp
).nstimes
[0];
606 for (ns
= 0; ns
< lastns
; ns
++)
608 if (EXT(statp
).ext
!= NULL
)
610 EXT(statp
).ext
->nsaddrs
[ns
] =EXT(statp
).ext
->nsaddrs
[ns
+ 1];
613 statp
->nsaddr_list
[ns
] = statp
->nsaddr_list
[ns
+ 1];
614 EXT(statp
).nssocks
[ns
] = EXT(statp
).nssocks
[ns
+ 1];
615 EXT(statp
).nstimes
[ns
] = EXT(statp
).nstimes
[ns
+ 1];
618 if (EXT(statp
).ext
!= NULL
) EXT(statp
).ext
->nsaddrs
[lastns
] = inu
;
619 statp
->nsaddr_list
[lastns
] = ina
;
620 EXT(statp
).nssocks
[lastns
] = fd
;
621 EXT(statp
).nstimes
[lastns
] = nstime
;
625 * Get notification token
626 * we use a self-notification token to allow a caller
627 * to signal the thread doing this DNS query to quit.
632 asprintf(¬ify_name
, "self.thread.%lu", (unsigned long)pthread_self());
633 if (notify_name
!= NULL
)
635 status
= notify_register_plain(notify_name
, ¬ify_token
);
640 * Send request, RETRY times, or until successful.
642 for (try = 0; try < statp
->retry
; try++)
644 for (ns
= 0; ns
< statp
->nscount
; ns
++)
646 struct sockaddr
*nsap
;
648 nsap
= get_nsaddr(statp
, ns
);
649 nsaplen
= get_salen(nsap
);
655 int done
= 0, loops
= 0;
661 act
= (*statp
->qhook
)(&nsap
, &buf
, &buflen
, ans
, reply_buf_size
, &resplen
);
671 if (notify_token
!= -1) notify_cancel(notify_token
);
672 return DNS_RES_STATUS_CANCELLED
;
674 /* give the hook another try */
675 if (++loops
< MAX_HOOK_RETRIES
) break;
680 if (notify_token
!= -1) notify_cancel(notify_token
);
681 return DNS_RES_STATUS_CANCELLED
;
686 if (notify_token
!= -1)
689 status
= notify_get_state(notify_token
, &exit_requested
);
690 if (exit_requested
== ThreadStateExitRequested
)
692 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
694 notify_cancel(notify_token
);
695 return DNS_RES_STATUS_CANCELLED
;
699 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
));
701 send_status
= ns_r_noerror
;
705 /* Use VC; at most one attempt per server. */
708 *anssiz
= reply_buf_size
;
709 send_status
= send_vc(statp
, buf
, buflen
, ans
, anssiz
, &terrno
, ns
, from
, fromlen
, notify_token
);
714 send_status
= send_dg(statp
, buf
, buflen
, ans
, anssiz
, &terrno
, ns
, &v_circuit
, &gotsomewhere
, from
, fromlen
, notify_token
);
715 if (v_circuit
!= 0) goto send_same_ns
;
718 if ((send_status
== DNS_RES_STATUS_SYSTEM_ERROR
) || (send_status
== DNS_RES_STATUS_CANCELLED
))
721 if (notify_token
!= -1) notify_cancel(notify_token
);
725 if (send_status
!= ns_r_noerror
) goto send_next_ns
;
727 Dprint((statp
->options
& RES_DEBUG
) || ((statp
->pfcode
& RES_PRF_REPLY
) && (statp
->pfcode
& RES_PRF_HEAD1
)), (stdout
, ";; got answer:\n"));
728 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, "%s", ""), ans
, (*anssiz
> reply_buf_size
) ? reply_buf_size
: *anssiz
);
731 * If we have temporarily opened a virtual circuit,
732 * or if we haven't been asked to keep a socket open,
735 if (((v_circuit
!= 0) && (statp
->options
& RES_USEVC
) == 0) || (statp
->options
& RES_STAYOPEN
) == 0) res_nclose(statp
);
739 int done
= 0, loops
= 0;
745 act
= (*statp
->rhook
)(nsap
, buf
, buflen
, ans
, *anssiz
, &resplen
);
756 /* give the hook another try */
757 if (++loops
< MAX_HOOK_RETRIES
) break;
763 if (notify_token
!= -1) notify_cancel(notify_token
);
764 return DNS_RES_STATUS_CANCELLED
;
770 if (notify_token
!= -1) notify_cancel(notify_token
);
775 } /* foreach retry */
778 if (notify_token
!= -1) notify_cancel(notify_token
);
783 if (gotsomewhere
!= 0)
785 errno
= ECONNREFUSED
;
786 return DNS_RES_STATUS_CONNECTION_REFUSED
;
790 return DNS_RES_STATUS_TIMEOUT
;
799 res_nsend_2(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
, int anssiz
, struct sockaddr
*from
, int *fromlen
)
804 status
= dns_res_send(statp
, buf
, buflen
, ans
, &len
, from
, fromlen
);
805 if (status
!= ns_r_noerror
) len
= -1;
810 res_nsend(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
, int anssiz
)
812 struct sockaddr_storage from
;
815 fromlen
= sizeof(struct sockaddr_storage
);
817 return res_nsend_2(statp
, buf
, buflen
, ans
, anssiz
, (struct sockaddr
*)&from
, &fromlen
);
823 get_salen(const struct sockaddr
*sa
)
826 /* There are people do not set sa_len. Be forgiving to them. */
827 if (sa
->sa_len
) return (sa
->sa_len
);
830 if (sa
->sa_family
== AF_INET
) return (sizeof(struct sockaddr_in
));
831 else if (sa
->sa_family
== AF_INET6
) return (sizeof(struct sockaddr_in6
));
832 else return (0); /* unknown, die on connect */
836 * pick appropriate nsaddr_list for use. see res_init() for initialization.
839 get_nsaddr(res_state statp
, size_t n
)
841 if ((!statp
->nsaddr_list
[n
].sin_family
) && (EXT(statp
).ext
!= NULL
))
844 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
845 * than struct sockaddr, and
846 * - user code did not update statp->nsaddr_list[n].
848 return (struct sockaddr
*)(void *)&EXT(statp
).ext
->nsaddrs
[n
];
853 * - user code updated statp->nsaddr_list[n], or
854 * - statp->nsaddr_list[n] has the same content as
855 * EXT(statp).ext->nsaddrs[n].
857 return (struct sockaddr
*)(void *)&statp
->nsaddr_list
[n
];
862 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
)
864 const HEADER
*hp
= (const HEADER
*) buf
;
865 HEADER
*anhp
= (HEADER
*) ans
;
866 struct sockaddr
*nsap
;
868 int truncating
, connreset
, resplen
, n
;
874 uint64_t exit_requested
;
876 nsap
= get_nsaddr(statp
, ns
);
877 nsaplen
= get_salen(nsap
);
883 if (notify_token
!= -1)
886 status
= notify_get_state(notify_token
, &exit_requested
);
887 if (exit_requested
== ThreadStateExitRequested
)
889 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
891 return DNS_RES_STATUS_CANCELLED
;
897 /* Are we still talking to whom we want to talk? */
898 if (statp
->_vcsock
>= 0 && (statp
->_flags
& RES_F_VC
) != 0)
900 struct sockaddr_storage peer
;
901 ISC_SOCKLEN_T size
= sizeof peer
;
903 if (getpeername(statp
->_vcsock
, (struct sockaddr
*)&peer
, &size
) < 0 || !sock_eq((struct sockaddr
*)&peer
, nsap
))
906 statp
->_flags
&= ~RES_F_VC
;
910 if ((statp
->_vcsock
< 0) || ((statp
->_flags
& RES_F_VC
) == 0))
912 if (statp
->_vcsock
>= 0) res_nclose(statp
);
914 statp
->_vcsock
= socket(nsap
->sa_family
, SOCK_STREAM
, 0);
915 if (statp
->_vcsock
> highestFD
)
921 if (statp
->_vcsock
< 0)
924 Perror(statp
, stderr
, "socket(vc)", errno
);
925 return DNS_RES_STATUS_SYSTEM_ERROR
;
929 if (connect(statp
->_vcsock
, nsap
, nsaplen
) < 0)
932 Aerror(statp
, stderr
, "connect(vc)", errno
, nsap
, nsaplen
);
934 return DNS_RES_STATUS_CONNECTION_REFUSED
;
937 statp
->_flags
|= RES_F_VC
;
941 * Send length & message
943 putshort((u_short
)buflen
, (u_char
*)&len
);
944 iov
[0] = evConsIovec(&len
, NS_INT16SZ
);
950 iov
[1] = evConsIovec(tmp
, buflen
);
951 if (writev(statp
->_vcsock
, iov
, 2) != (NS_INT16SZ
+ buflen
))
954 Perror(statp
, stderr
, "write failed", errno
);
956 return DNS_RES_STATUS_CONNECTION_FAILED
;
960 * Receive length & response
964 if (notify_token
!= -1)
967 status
= notify_get_state(notify_token
, &exit_requested
);
968 if (exit_requested
== ThreadStateExitRequested
)
970 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
972 return DNS_RES_STATUS_CANCELLED
;
978 while ((n
= read(statp
->_vcsock
, (char *)cp
, (int)len
)) > 0)
981 if ((len
-= n
) <= 0) break;
987 Perror(statp
, stderr
, "read failed", errno
);
991 * A long running process might get its TCP
992 * connection reset if the remote server was
993 * restarted. Requery the server instead of
994 * trying a new one. When there is only one
995 * server, this means that a query might work
996 * instead of failing. We only allow one reset
997 * per query to prevent looping.
999 if (*terrno
== ECONNRESET
&& !connreset
)
1007 return DNS_RES_STATUS_CONNECTION_FAILED
;
1010 resplen
= ns_get16(ans
);
1011 if (resplen
> *anssiz
)
1013 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; response truncated\n"));
1022 if (len
< NS_HFIXEDSZ
)
1025 * Undersized message.
1027 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; undersized: %d\n", len
));
1031 return DNS_RES_STATUS_INVALID_REPLY
;
1035 while (len
!= 0 && (n
= read(statp
->_vcsock
, (char *)cp
, (int)len
)) > 0)
1044 Perror(statp
, stderr
, "read(vc)", errno
);
1046 return DNS_RES_STATUS_CONNECTION_FAILED
;
1052 * Flush rest of answer so connection stays in synch.
1055 len
= resplen
- *anssiz
;
1058 char junk
[NS_PACKETSZ
];
1060 n
= read(statp
->_vcsock
, junk
, (len
> sizeof junk
) ? sizeof junk
: len
);
1061 if (n
> 0) len
-= n
;
1067 * If the calling applicating has bailed out of
1068 * a previous call and failed to arrange to have
1069 * the circuit closed or the server has got
1070 * itself confused, then drop the packet and
1071 * wait for the correct one.
1073 if (hp
->id
!= anhp
->id
)
1075 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, ";; old answer (unexpected):\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1080 * All is well, or the error is fatal. Signal that the
1081 * next nameserver ought not be tried.
1084 *fromlen
= sizeof(nsap
);
1085 memcpy(from
, &nsap
, *fromlen
);
1087 return ns_r_noerror
;
1091 internal_recvfrom(int s
, void *buf
, size_t len
, struct sockaddr
*from
, int *fromlen
, int *iface
)
1093 struct sockaddr_dl
*sdl
;
1094 struct iovec databuffers
= { buf
, len
};
1097 struct cmsghdr
*cmp
;
1098 char ancillary
[1024], ifname
[IF_NAMESIZE
];
1099 struct in6_pktinfo
*ip6_info
;
1100 struct sockaddr_in
*s4
;
1101 struct sockaddr_in6
*s6
;
1103 memset(&msg
, 0, sizeof(struct msghdr
));
1104 msg
.msg_name
= (caddr_t
)from
;
1105 msg
.msg_namelen
= *fromlen
;
1106 msg
.msg_iov
= &databuffers
;
1108 msg
.msg_control
= (caddr_t
)&ancillary
;
1109 msg
.msg_controllen
= sizeof(ancillary
);
1111 /* Receive the data */
1112 n
= recvmsg(s
, &msg
, 0);
1113 if ((n
< 0) || (msg
.msg_controllen
< sizeof(struct cmsghdr
)) || (msg
.msg_flags
& MSG_CTRUNC
))
1118 *fromlen
= msg
.msg_namelen
;
1120 s4
= (struct sockaddr_in
*)from
;
1121 s6
= (struct sockaddr_in6
*)from
;
1123 for (cmp
= CMSG_FIRSTHDR(&msg
); cmp
; cmp
= CMSG_NXTHDR(&msg
, cmp
))
1125 if ((cmp
->cmsg_level
== IPPROTO_IP
) && (cmp
->cmsg_type
== IP_RECVIF
))
1127 sdl
= (struct sockaddr_dl
*)CMSG_DATA(cmp
);
1128 if (sdl
->sdl_nlen
< IF_NAMESIZE
)
1130 memcpy(ifname
, sdl
->sdl_data
, sdl
->sdl_nlen
);
1131 ifname
[sdl
->sdl_nlen
] = 0;
1132 *iface
= if_nametoindex(ifname
);
1135 else if ((cmp
->cmsg_level
== IPPROTO_IPV6
) && (cmp
->cmsg_type
== IPV6_PKTINFO
))
1137 ip6_info
= (struct in6_pktinfo
*)CMSG_DATA(cmp
);
1138 *iface
= ip6_info
->ipi6_ifindex
;
1146 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
)
1148 const HEADER
*hp
= (const HEADER
*) buf
;
1149 HEADER
*anhp
= (HEADER
*) ans
;
1150 const struct sockaddr
*nsap
;
1152 struct timespec now
, timeout
, finish
;
1154 int iface
, rif
, status
;
1155 uint64_t exit_requested
;
1156 int *interrupt_pipe
;
1158 struct sockaddr_storage from
;
1159 ISC_SOCKLEN_T fromlen
;
1161 int resplen
, seconds
, ntry
, n
, s
;
1166 interrupt_pipe
= NULL
;
1168 nsap
= get_nsaddr(statp
, ns
);
1169 nsaplen
= get_salen(nsap
);
1170 if (EXT(statp
).nssocks
[ns
] == -1)
1172 EXT(statp
).nssocks
[ns
] = socket(nsap
->sa_family
, SOCK_DGRAM
, 0);
1173 if (EXT(statp
).nssocks
[ns
] > highestFD
)
1179 if (EXT(statp
).nssocks
[ns
] < 0)
1182 Perror(statp
, stderr
, "socket(dg)", errno
);
1183 return DNS_RES_STATUS_SYSTEM_ERROR
;
1186 bind_random(EXT(statp
).nssocks
[ns
]);
1188 #ifndef CANNOT_CONNECT_DGRAM
1190 * On a 4.3BSD+ machine (client and server,
1191 * actually), sending to a nameserver datagram
1192 * port with no nameserver will cause an
1193 * ICMP port unreachable message to be returned.
1194 * If our datagram socket is "connected" to the
1195 * server, we get an ECONNREFUSED error on the next
1196 * socket operation, and select returns if the
1197 * error message is received. We can thus detect
1198 * the absence of a nameserver without timing out.
1200 if (connect(EXT(statp
).nssocks
[ns
], nsap
, nsaplen
) < 0)
1202 Aerror(statp
, stderr
, "connect(dg)", errno
, nsap
, nsaplen
);
1204 return DNS_RES_STATUS_CONNECTION_REFUSED
;
1207 #endif /* !CANNOT_CONNECT_DGRAM */
1208 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; new DG socket\n"))
1211 s
= EXT(statp
).nssocks
[ns
];
1213 setsockopt(s
, IPPROTO_IP
, IP_RECVIF
, &rif
, sizeof(int));
1214 setsockopt(s
, IPPROTO_IPV6
, IPV6_PKTINFO
, &rif
, sizeof(int));
1219 if ((nsap
->sa_family
== AF_INET
) && (IN_MULTICAST(ntohl(((struct sockaddr_in
*)nsap
)->sin_addr
.s_addr
)))) multicast
= AF_INET
;
1220 else if ((nsap
->sa_family
== AF_INET6
) && (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6
*)nsap
)->sin6_addr
))) multicast
= AF_INET6
;
1224 struct ifaddrs
*ifa
, *p
;
1225 struct sockaddr_in
*sin4
;
1226 struct sockaddr_in6
*sin6
;
1229 if (getifaddrs(&ifa
) < 0)
1231 Aerror(statp
, stderr
, "getifaddrs", errno
, nsap
, nsaplen
);
1233 return DNS_RES_STATUS_SYSTEM_ERROR
;
1236 for (p
= ifa
; p
!= NULL
; p
= p
->ifa_next
)
1238 if (p
->ifa_addr
== NULL
) continue;
1239 if ((p
->ifa_flags
& IFF_UP
) == 0) continue;
1240 if (p
->ifa_addr
->sa_family
!= multicast
) continue;
1241 if ((p
->ifa_flags
& IFF_MULTICAST
) == 0) continue;
1242 if ((p
->ifa_flags
& IFF_POINTOPOINT
) != 0)
1244 if ((multicast
== AF_INET
) && (ntohl(((struct sockaddr_in
*)nsap
)->sin_addr
.s_addr
) <= INADDR_MAX_LOCAL_GROUP
)) continue;
1247 sin4
= (struct sockaddr_in
*)p
->ifa_addr
;
1248 sin6
= (struct sockaddr_in6
*)p
->ifa_addr
;
1250 if (multicast
== AF_INET
) i
= setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_IF
, &sin4
->sin_addr
, sizeof(sin4
->sin_addr
));
1251 else if (multicast
== AF_INET6
)
1253 ifnum
= if_nametoindex(p
->ifa_name
);
1254 ((struct sockaddr_in6
*)nsap
)->sin6_scope_id
= ifnum
;
1255 i
= setsockopt(s
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, &ifnum
, sizeof(ifnum
));
1260 Aerror(statp
, stderr
, "setsockopt", errno
, nsap
, nsaplen
);
1261 if (multicast
== AF_INET6
) ((struct sockaddr_in6
*)nsap
)->sin6_scope_id
= 0;
1266 if (sendto(s
, (const char*)buf
, buflen
, 0, nsap
, nsaplen
) != buflen
)
1268 Aerror(statp
, stderr
, "sendto", errno
, nsap
, nsaplen
);
1269 if (multicast
== AF_INET6
) ((struct sockaddr_in6
*)nsap
)->sin6_scope_id
= 0;
1273 if (multicast
== AF_INET6
) ((struct sockaddr_in6
*)nsap
)->sin6_scope_id
= 0;
1281 #endif /* MULTICAST */
1283 #ifndef CANNOT_CONNECT_DGRAM
1284 if (send(s
, (const char*)buf
, buflen
, 0) != buflen
)
1286 Perror(statp
, stderr
, "send", errno
);
1288 return DNS_RES_STATUS_CONNECTION_FAILED
;
1291 #else /* !CANNOT_CONNECT_DGRAM */
1292 if (sendto(s
, (const char*)buf
, buflen
, 0, nsap
, nsaplen
) != buflen
)
1294 Aerror(statp
, stderr
, "sendto", errno
, nsap
, nsaplen
);
1296 return DNS_RES_STATUS_CONNECTION_FAILED
;
1298 #endif /* !CANNOT_CONNECT_DGRAM */
1302 #endif /* MULTICAST */
1308 ntry
= statp
->nscount
* statp
->retry
;
1309 seconds
= statp
->retrans
/ ntry
;
1310 if (seconds
<= 0) seconds
= 1;
1311 timeout
.tv_sec
= seconds
;
1312 timeout
.tv_nsec
= ((statp
->retrans
- (seconds
* ntry
)) * 1000) / ntry
;
1313 timeout
.tv_nsec
*= 1000000;
1315 finish
= evAddTime(now
, timeout
);
1317 if (interrupt_pipe_enabled
!= 0) interrupt_pipe
= pthread_getspecific(interrupt_pipe_key
);
1319 seconds
= (statp
->retrans
<< ns
);
1320 if (ns
> 0) seconds
/= statp
->nscount
;
1321 if (seconds
<= 0) seconds
= 1;
1323 timeout
= evConsTime(seconds
, 0);
1324 finish
= evAddTime(now
, timeout
);
1325 #endif /* __APPLE__ */
1333 if (notify_token
!= -1)
1336 status
= notify_get_state(notify_token
, &exit_requested
);
1337 if (exit_requested
== ThreadStateExitRequested
)
1339 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
1340 return DNS_RES_STATUS_CANCELLED
;
1348 if ((interrupt_pipe_enabled
!= 0) && (interrupt_pipe
!= NULL
))
1350 if (interrupt_pipe
[0] >= 0)
1352 FD_SET(interrupt_pipe
[0], &dsmask
);
1353 nfds
= MAX(s
, interrupt_pipe
[0]) + 1;
1357 if (evCmpTime(finish
, now
) > 0) timeout
= evSubTime(finish
, now
);
1358 else timeout
= evConsTime(0, 0);
1360 n
= pselect(nfds
, &dsmask
, NULL
, NULL
, &timeout
, NULL
);
1363 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; timeout\n"));
1365 return DNS_RES_STATUS_TIMEOUT
;
1370 if (errno
== EINTR
) goto wait
;
1371 Perror(statp
, stderr
, "select", errno
);
1373 return DNS_RES_STATUS_SYSTEM_ERROR
;
1376 /* socket s and/or interrupt pipe got data */
1377 if ((interrupt_pipe_enabled
!= 0) && (interrupt_pipe
!= NULL
) && ((interrupt_pipe
[0] < 0) || (FD_ISSET(interrupt_pipe
[0], &dsmask
))))
1379 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; cancelled\n"));
1380 return DNS_RES_STATUS_CANCELLED
;
1385 resplen
= internal_recvfrom(s
, (char *)ans
, *anssiz
, from
, fromlen
, &iface
);
1388 Perror(statp
, stderr
, "recvfrom", errno
);
1390 return DNS_RES_STATUS_CONNECTION_FAILED
;
1393 if (nsap
->sa_family
== AF_INET
) memcpy(((struct sockaddr_in
*)from
)->sin_zero
, &iface
, 4);
1394 else if (nsap
->sa_family
== AF_INET6
) ((struct sockaddr_in6
*)from
)->sin6_scope_id
= iface
;
1397 if (resplen
< NS_HFIXEDSZ
)
1400 * Undersized message.
1402 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; undersized: %d\n", resplen
));
1405 return DNS_RES_STATUS_INVALID_REPLY
;
1408 if (hp
->id
!= anhp
->id
)
1411 * response from old query, ignore it.
1412 * XXX - potential security hazard could
1415 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, ";; old answer:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1422 #endif /* MULTICAST */
1424 if (!(statp
->options
& RES_INSECURE1
) && !res_ourserver_p(statp
, from
))
1427 * response from wrong server? ignore it.
1428 * XXX - potential security hazard could
1431 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, ";; not our server:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1437 #endif /* MULTICAST */
1439 #ifdef RES_USE_EDNS0
1440 if (anhp
->rcode
== ns_r_formerr
&& (statp
->options
& RES_USE_EDNS0
) != 0)
1443 * Do not retry if the server do not understand EDNS0.
1444 * The case has to be captured here, as FORMERR packet do not
1445 * carry query section, hence res_queriesmatch() returns 0.
1447 DprintQ(statp
->options
& RES_DEBUG
, (stdout
, "server rejected query with EDNS0:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1448 /* record the error */
1449 statp
->_flags
|= RES_F_EDNS0ERR
;
1451 return DNS_RES_STATUS_CONNECTION_REFUSED
;
1455 if (!(statp
->options
& RES_INSECURE2
) && !res_queriesmatch(buf
, buf
+ buflen
, ans
, ans
+ *anssiz
))
1458 * response contains wrong query? ignore it.
1459 * XXX - potential security hazard could
1462 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_REPLY
), (stdout
, ";; wrong query name:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1464 return DNS_RES_STATUS_INVALID_REPLY
;
1467 if (anhp
->rcode
== ns_r_servfail
|| anhp
->rcode
== ns_r_notimpl
|| anhp
->rcode
== ns_r_refused
)
1469 DprintQ(statp
->options
& RES_DEBUG
, (stdout
, "server rejected query:\n"), ans
, (resplen
> *anssiz
) ? *anssiz
: resplen
);
1471 /* don't retry if called from dig */
1472 if (!statp
->pfcode
) return anhp
->rcode
;
1475 if (!(statp
->options
& RES_IGNTC
) && anhp
->tc
)
1478 * To get the rest of answer,
1479 * use TCP with same server.
1481 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; truncated answer\n"));
1484 return ns_r_noerror
;
1488 * All is well, or the error is fatal. Signal that the
1489 * next nameserver ought not be tried.
1492 return ns_r_noerror
;
1496 Aerror(const res_state statp
, FILE *file
, const char *string
, int error
, const struct sockaddr
*address
, int alen
)
1499 char hbuf
[NI_MAXHOST
];
1500 char sbuf
[NI_MAXSERV
];
1504 if ((statp
->options
& RES_DEBUG
) != 0)
1506 if (getnameinfo(address
, alen
, hbuf
, sizeof(hbuf
), sbuf
, sizeof(sbuf
), niflags
))
1508 strncpy(hbuf
, "?", sizeof(hbuf
) - 1);
1509 hbuf
[sizeof(hbuf
) - 1] = '\0';
1510 strncpy(sbuf
, "?", sizeof(sbuf
) - 1);
1511 sbuf
[sizeof(sbuf
) - 1] = '\0';
1514 fprintf(file
, "res_send: %s ([%s].%s): %s\n", string
, hbuf
, sbuf
, strerror(error
));
1521 Perror(const res_state statp
, FILE *file
, const char *string
, int error
)
1525 if ((statp
->options
& RES_DEBUG
) != 0) fprintf(file
, "res_send: %s: %s\n", string
, strerror(error
));
1530 sock_eq(struct sockaddr
*a
, struct sockaddr
*b
)
1532 struct sockaddr_in
*a4
, *b4
;
1533 struct sockaddr_in6
*a6
, *b6
;
1535 if (a
->sa_family
!= b
->sa_family
) return 0;
1537 switch (a
->sa_family
)
1540 a4
= (struct sockaddr_in
*)a
;
1541 b4
= (struct sockaddr_in
*)b
;
1542 return a4
->sin_port
== b4
->sin_port
&& a4
->sin_addr
.s_addr
== b4
->sin_addr
.s_addr
;
1544 a6
= (struct sockaddr_in6
*)a
;
1545 b6
= (struct sockaddr_in6
*)b
;
1546 return a6
->sin6_port
== b6
->sin6_port
&&
1547 #ifdef HAVE_SIN6_SCOPE_ID
1548 a6
->sin6_scope_id
== b6
->sin6_scope_id
&&
1550 IN6_ARE_ADDR_EQUAL(&a6
->sin6_addr
, &b6
->sin6_addr
);
1557 /* XXX needs to move to the porting library. */
1559 pselect(int nfds
, void *rfds
, void *wfds
, void *efds
, struct timespec
*tsp
, const sigset_t
*sigmask
)
1561 struct timeval tv
, *tvp
= NULL
;
1568 tv
= evTimeVal(*tsp
);
1571 if (sigmask
) sigprocmask(SIG_SETMASK
, sigmask
, &sigs
);
1572 n
= select(nfds
, rfds
, wfds
, efds
, tvp
);
1573 if (sigmask
) sigprocmask(SIG_SETMASK
, &sigs
, NULL
);
1574 if (tsp
) *tsp
= evTimeSpec(tv
);