1 /* $NetBSD: res_send.c,v 1.20 2009/10/24 17:24:01 christos Exp $ */
4 * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1996-2003 Internet Software Consortium.
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.
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.
21 * Copyright (c) 1985, 1989, 1993
22 * The Regents of the University of California. All rights reserved.
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
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.
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
54 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
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.
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
74 * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC")
75 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
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.
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.
90 #include <sys/cdefs.h>
91 #if defined(LIBC_SCCS) && !defined(lint)
93 static const char sccsid
[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
94 static const char rcsid
[] = "Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp";
96 __RCSID("$NetBSD: res_send.c,v 1.20 2009/10/24 17:24:01 christos Exp $");
98 #endif /* LIBC_SCCS and not lint */
102 * Send query to name server and wait for reply.
105 #include "namespace.h"
106 #include "port_before.h"
107 #include "fd_setsize.h"
109 #include <sys/types.h>
110 #include <sys/param.h>
111 #include <sys/time.h>
112 #include <sys/socket.h>
115 #include <netinet/in.h>
116 #include <arpa/nameser.h>
117 #include <arpa/inet.h>
128 #include <isc/eventlib.h>
130 #include "port_after.h"
134 __weak_alias(res_ourserver_p
,__res_ourserver_p
)
135 __weak_alias(res_nameinquery
,__res_nameinquery
)
136 __weak_alias(res_queriesmatch
,__res_queriesmatch
)
137 __weak_alias(res_nsend
,__res_nsend
)
143 #ifdef HAVE_STROPTS_H
147 #endif /* USE_POLL */
149 /* Options. Leave them on. */
153 #include "res_debug.h"
154 #include "res_private.h"
156 #define EXT(res) ((res)->_u._ext)
159 static const int highestFD
= FD_SETSIZE
- 1;
161 static int highestFD
= 0;
166 static int get_salen
__P((const struct sockaddr
*));
167 static struct sockaddr
* get_nsaddr
__P((res_state
, size_t));
168 static int send_vc(res_state
, const u_char
*, int,
169 u_char
*, int, int *, int);
170 static int send_dg(res_state
, const u_char
*, int,
171 u_char
*, int, int *, int, int,
173 static void Aerror(const res_state
, FILE *, const char *, int,
174 const struct sockaddr
*, int);
175 static void Perror(const res_state
, FILE *, const char *, int);
176 static int sock_eq(struct sockaddr
*, struct sockaddr
*);
177 #if defined(NEED_PSELECT) && !defined(USE_POLL)
178 static int pselect(int, void *, void *, void *,
182 void res_pquery(const res_state
, const u_char
*, int, FILE *);
184 static const int niflags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
189 * looks up "ina" in _res.ns_addr_list[]
196 *\li paul vixie, 29may94
199 res_ourserver_p(const res_state statp
, const struct sockaddr
*sa
) {
200 const struct sockaddr_in
*inp
, *srv
;
201 const struct sockaddr_in6
*in6p
, *srv6
;
204 switch (sa
->sa_family
) {
206 inp
= (const struct sockaddr_in
*)(const void *)sa
;
207 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
208 srv
= (struct sockaddr_in
*)(void *)get_nsaddr(statp
, (size_t)ns
);
209 if (srv
->sin_family
== inp
->sin_family
&&
210 srv
->sin_port
== inp
->sin_port
&&
211 (srv
->sin_addr
.s_addr
== INADDR_ANY
||
212 srv
->sin_addr
.s_addr
== inp
->sin_addr
.s_addr
))
217 if (EXT(statp
).ext
== NULL
)
219 in6p
= (const struct sockaddr_in6
*)(const void *)sa
;
220 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
221 srv6
= (struct sockaddr_in6
*)(void *)get_nsaddr(statp
, (size_t)ns
);
222 if (srv6
->sin6_family
== in6p
->sin6_family
&&
223 srv6
->sin6_port
== in6p
->sin6_port
&&
224 #ifdef HAVE_SIN6_SCOPE_ID
225 (srv6
->sin6_scope_id
== 0 ||
226 srv6
->sin6_scope_id
== in6p
->sin6_scope_id
) &&
228 (IN6_IS_ADDR_UNSPECIFIED(&srv6
->sin6_addr
) ||
229 IN6_ARE_ADDR_EQUAL(&srv6
->sin6_addr
, &in6p
->sin6_addr
)))
240 * look for (name,type,class) in the query section of packet (buf,eom)
243 *\li buf + HFIXEDSZ <= eom
246 *\li -1 : format error
251 *\li paul vixie, 29may94
254 res_nameinquery(const char *name
, int type
, int class,
255 const u_char
*buf
, const u_char
*eom
)
257 const u_char
*cp
= buf
+ HFIXEDSZ
;
258 int qdcount
= ntohs(((const HEADER
*)(const void *)buf
)->qdcount
);
260 while (qdcount
-- > 0) {
261 char tname
[MAXDNAME
+1];
262 int n
, ttype
, tclass
;
264 n
= dn_expand(buf
, eom
, cp
, tname
, sizeof tname
);
268 if (cp
+ 2 * INT16SZ
> eom
)
270 ttype
= ns_get16(cp
); cp
+= INT16SZ
;
271 tclass
= ns_get16(cp
); cp
+= INT16SZ
;
272 if (ttype
== type
&& tclass
== class &&
273 ns_samename(tname
, name
) == 1)
280 * is there a 1:1 mapping of (name,type,class)
281 * in (buf1,eom1) and (buf2,eom2)?
284 *\li -1 : format error
285 *\li 0 : not a 1:1 mapping
286 *\li >0 : is a 1:1 mapping
289 *\li paul vixie, 29may94
292 res_queriesmatch(const u_char
*buf1
, const u_char
*eom1
,
293 const u_char
*buf2
, const u_char
*eom2
)
295 const u_char
*cp
= buf1
+ HFIXEDSZ
;
296 int qdcount
= ntohs(((const HEADER
*)(const void *)buf1
)->qdcount
);
298 if (buf1
+ HFIXEDSZ
> eom1
|| buf2
+ HFIXEDSZ
> eom2
)
302 * Only header section present in replies to
303 * dynamic update packets.
305 if ((((const HEADER
*)(const void *)buf1
)->opcode
== ns_o_update
) &&
306 (((const HEADER
*)(const void *)buf2
)->opcode
== ns_o_update
))
309 if (qdcount
!= ntohs(((const HEADER
*)(const void *)buf2
)->qdcount
))
311 while (qdcount
-- > 0) {
312 char tname
[MAXDNAME
+1];
313 int n
, ttype
, tclass
;
315 n
= dn_expand(buf1
, eom1
, cp
, tname
, sizeof tname
);
319 if (cp
+ 2 * INT16SZ
> eom1
)
321 ttype
= ns_get16(cp
); cp
+= INT16SZ
;
322 tclass
= ns_get16(cp
); cp
+= INT16SZ
;
323 if (!res_nameinquery(tname
, ttype
, tclass
, buf2
, eom2
))
330 res_nsend(res_state statp
,
331 const u_char
*buf
, int buflen
, u_char
*ans
, int anssiz
)
333 int gotsomewhere
, terrno
, tries
, v_circuit
, resplen
, ns
, n
;
334 char abuf
[NI_MAXHOST
];
337 highestFD
= sysconf(_SC_OPEN_MAX
) - 1;
340 (void)res_check(statp
, NULL
);
342 /* No name servers or res_init() failure */
343 if (statp
->nscount
== 0 || EXT(statp
).ext
== NULL
) {
347 if (anssiz
< HFIXEDSZ
) {
351 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_QUERY
),
352 (stdout
, ";; res_send()\n"), buf
, buflen
);
353 v_circuit
= (statp
->options
& RES_USEVC
) || buflen
> PACKETSZ
;
358 * If the ns_addr_list in the resolver context has changed, then
359 * invalidate our cached copy and the associated timing data.
361 if (EXT(statp
).nscount
!= 0) {
363 struct sockaddr_storage peer
;
364 ISC_SOCKLEN_T peerlen
;
366 if (EXT(statp
).nscount
!= statp
->nscount
)
369 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
370 if (statp
->nsaddr_list
[ns
].sin_family
&&
371 !sock_eq((struct sockaddr
*)(void *)&statp
->nsaddr_list
[ns
],
372 (struct sockaddr
*)(void *)&EXT(statp
).ext
->nsaddrs
[ns
])) {
377 if (EXT(statp
).nssocks
[ns
] == -1)
379 peerlen
= sizeof(peer
);
380 if (getpeername(EXT(statp
).nssocks
[ns
],
381 (struct sockaddr
*)(void *)&peer
, &peerlen
) < 0) {
385 if (!sock_eq((struct sockaddr
*)(void *)&peer
,
386 get_nsaddr(statp
, (size_t)ns
))) {
393 EXT(statp
).nscount
= 0;
398 * Maybe initialize our private copy of the ns_addr_list.
400 if (EXT(statp
).nscount
== 0) {
401 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
402 EXT(statp
).nstimes
[ns
] = RES_MAXTIME
;
403 EXT(statp
).nssocks
[ns
] = -1;
404 if (!statp
->nsaddr_list
[ns
].sin_family
)
406 EXT(statp
).ext
->nsaddrs
[ns
].sin
=
407 statp
->nsaddr_list
[ns
];
409 EXT(statp
).nscount
= statp
->nscount
;
413 * Some resolvers want to even out the load on their nameservers.
414 * Note that RES_BLAST overrides RES_ROTATE.
416 if ((statp
->options
& RES_ROTATE
) != 0U &&
417 (statp
->options
& RES_BLAST
) == 0U) {
418 union res_sockaddr_union inu
;
419 struct sockaddr_in ina
;
420 int lastns
= statp
->nscount
- 1;
424 if (EXT(statp
).ext
!= NULL
)
425 inu
= EXT(statp
).ext
->nsaddrs
[0];
426 ina
= statp
->nsaddr_list
[0];
427 fd
= EXT(statp
).nssocks
[0];
428 nstime
= EXT(statp
).nstimes
[0];
429 for (ns
= 0; ns
< lastns
; ns
++) {
430 if (EXT(statp
).ext
!= NULL
)
431 EXT(statp
).ext
->nsaddrs
[ns
] =
432 EXT(statp
).ext
->nsaddrs
[ns
+ 1];
433 statp
->nsaddr_list
[ns
] = statp
->nsaddr_list
[ns
+ 1];
434 EXT(statp
).nssocks
[ns
] = EXT(statp
).nssocks
[ns
+ 1];
435 EXT(statp
).nstimes
[ns
] = EXT(statp
).nstimes
[ns
+ 1];
437 if (EXT(statp
).ext
!= NULL
)
438 EXT(statp
).ext
->nsaddrs
[lastns
] = inu
;
439 statp
->nsaddr_list
[lastns
] = ina
;
440 EXT(statp
).nssocks
[lastns
] = fd
;
441 EXT(statp
).nstimes
[lastns
] = nstime
;
445 * Send request, RETRY times, or until successful.
447 for (tries
= 0; tries
< statp
->retry
; tries
++) {
448 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
449 struct sockaddr
*nsap
;
451 nsap
= get_nsaddr(statp
, (size_t)ns
);
452 nsaplen
= get_salen(nsap
);
453 statp
->_flags
&= ~RES_F_LASTMASK
;
454 statp
->_flags
|= (ns
<< RES_F_LASTSHIFT
);
457 int done
= 0, loops
= 0;
462 act
= (*statp
->qhook
)(&nsap
, &buf
, &buflen
,
463 ans
, anssiz
, &resplen
);
474 /* give the hook another try */
475 if (++loops
< 42) /*doug adams*/
486 Dprint(((statp
->options
& RES_DEBUG
) &&
487 getnameinfo(nsap
, (socklen_t
)nsaplen
, abuf
, sizeof(abuf
),
488 NULL
, 0, niflags
) == 0),
489 (stdout
, ";; Querying server (# %d) address = %s\n",
494 /* Use VC; at most one attempt per server. */
495 tries
= statp
->retry
;
496 n
= send_vc(statp
, buf
, buflen
, ans
, anssiz
, &terrno
,
505 n
= send_dg(statp
, buf
, buflen
, ans
, anssiz
, &terrno
,
506 ns
, tries
, &v_circuit
, &gotsomewhere
);
516 Dprint((statp
->options
& RES_DEBUG
) ||
517 ((statp
->pfcode
& RES_PRF_REPLY
) &&
518 (statp
->pfcode
& RES_PRF_HEAD1
)),
519 (stdout
, ";; got answer:\n"));
521 DprintQ((statp
->options
& RES_DEBUG
) ||
522 (statp
->pfcode
& RES_PRF_REPLY
),
524 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
527 * If we have temporarily opened a virtual circuit,
528 * or if we haven't been asked to keep a socket open,
531 if ((v_circuit
&& (statp
->options
& RES_USEVC
) == 0U) ||
532 (statp
->options
& RES_STAYOPEN
) == 0U) {
536 int done
= 0, loops
= 0;
541 act
= (*statp
->rhook
)(nsap
, buf
, buflen
,
542 ans
, anssiz
, &resplen
);
552 /* give the hook another try */
553 if (++loops
< 42) /*doug adams*/
571 errno
= ECONNREFUSED
; /*%< no nameservers found */
573 errno
= ETIMEDOUT
; /*%< no answer obtained */
586 const struct sockaddr
*sa
;
590 /* There are people do not set sa_len. Be forgiving to them. */
595 if (sa
->sa_family
== AF_INET
)
596 return (sizeof(struct sockaddr_in
));
597 else if (sa
->sa_family
== AF_INET6
)
598 return (sizeof(struct sockaddr_in6
));
600 return (0); /*%< unknown, die on connect */
604 * pick appropriate nsaddr_list for use. see res_init() for initialization.
606 static struct sockaddr
*
612 if (!statp
->nsaddr_list
[n
].sin_family
&& EXT(statp
).ext
) {
614 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
615 * than struct sockaddr, and
616 * - user code did not update statp->nsaddr_list[n].
618 return (struct sockaddr
*)(void *)&EXT(statp
).ext
->nsaddrs
[n
];
621 * - user code updated statp->nsaddr_list[n], or
622 * - statp->nsaddr_list[n] has the same content as
623 * EXT(statp).ext->nsaddrs[n].
625 return (struct sockaddr
*)(void *)&statp
->nsaddr_list
[n
];
630 send_vc(res_state statp
,
631 const u_char
*buf
, int buflen
, u_char
*ans
, int anssiz
,
634 const HEADER
*hp
= (const HEADER
*)(const void *)buf
;
635 HEADER
*anhp
= (HEADER
*)(void *)ans
;
636 struct sockaddr
*nsap
;
638 int truncating
, connreset
, resplen
, n
;
647 nsap
= get_nsaddr(statp
, (size_t)ns
);
648 nsaplen
= get_salen(nsap
);
654 /* Are we still talking to whom we want to talk to? */
655 if (statp
->_vcsock
>= 0 && (statp
->_flags
& RES_F_VC
) != 0) {
656 struct sockaddr_storage peer
;
657 ISC_SOCKLEN_T size
= sizeof peer
;
659 if (getpeername(statp
->_vcsock
,
660 (struct sockaddr
*)(void *)&peer
, &size
) < 0 ||
661 !sock_eq((struct sockaddr
*)(void *)&peer
, nsap
)) {
663 statp
->_flags
&= ~RES_F_VC
;
667 if (statp
->_vcsock
< 0 || (statp
->_flags
& RES_F_VC
) == 0) {
668 if (statp
->_vcsock
>= 0)
671 statp
->_vcsock
= socket(nsap
->sa_family
, SOCK_STREAM
, 0);
672 if (statp
->_vcsock
> highestFD
) {
676 if (statp
->_vcsock
< 0) {
678 case EPROTONOSUPPORT
:
683 Perror(statp
, stderr
, "socket(vc)", errno
);
687 Perror(statp
, stderr
, "socket(vc)", errno
);
693 * Disable generation of SIGPIPE when writing to a closed
694 * socket. Write should return -1 and set errno to EPIPE
697 * Push on even if setsockopt(SO_NOSIGPIPE) fails.
699 (void)setsockopt(statp
->_vcsock
, SOL_SOCKET
, SO_NOSIGPIPE
, &on
,
703 if (connect(statp
->_vcsock
, nsap
, (socklen_t
)nsaplen
) < 0) {
705 Aerror(statp
, stderr
, "connect/vc", errno
, nsap
,
710 statp
->_flags
|= RES_F_VC
;
714 * Send length & message
716 ns_put16((u_short
)buflen
, (u_char
*)(void *)&len
);
717 iov
[0] = evConsIovec(&len
, INT16SZ
);
719 iov
[1] = evConsIovec(tmp
, (size_t)buflen
);
720 if (writev(statp
->_vcsock
, iov
, 2) != (INT16SZ
+ buflen
)) {
722 Perror(statp
, stderr
, "write failed", errno
);
727 * Receive length & response
732 while ((n
= read(statp
->_vcsock
, (char *)cp
, (size_t)len
)) > 0) {
739 Perror(statp
, stderr
, "read failed", errno
);
742 * A long running process might get its TCP
743 * connection reset if the remote server was
744 * restarted. Requery the server instead of
745 * trying a new one. When there is only one
746 * server, this means that a query might work
747 * instead of failing. We only allow one reset
748 * per query to prevent looping.
750 if (*terrno
== ECONNRESET
&& !connreset
) {
758 resplen
= ns_get16(ans
);
759 if (resplen
> anssiz
) {
760 Dprint(statp
->options
& RES_DEBUG
,
761 (stdout
, ";; response truncated\n")
767 if (len
< HFIXEDSZ
) {
769 * Undersized message.
771 Dprint(statp
->options
& RES_DEBUG
,
772 (stdout
, ";; undersized: %d\n", len
));
778 while (len
!= 0 && (n
= read(statp
->_vcsock
, (char *)cp
, (size_t)len
)) > 0){
784 Perror(statp
, stderr
, "read(vc)", errno
);
790 * Flush rest of answer so connection stays in synch.
793 len
= resplen
- anssiz
;
797 n
= read(statp
->_vcsock
, junk
,
798 (len
> sizeof junk
) ? sizeof junk
: len
);
806 * If the calling applicating has bailed out of
807 * a previous call and failed to arrange to have
808 * the circuit closed or the server has got
809 * itself confused, then drop the packet and
810 * wait for the correct one.
812 if (hp
->id
!= anhp
->id
) {
813 DprintQ((statp
->options
& RES_DEBUG
) ||
814 (statp
->pfcode
& RES_PRF_REPLY
),
815 (stdout
, ";; old answer (unexpected):\n"),
816 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
821 * All is well, or the error is fatal. Signal that the
822 * next nameserver ought not be tried.
828 send_dg(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
,
829 int anssiz
, int *terrno
, int ns
, int tries
, int *v_circuit
,
832 const HEADER
*hp
= (const HEADER
*)(const void *)buf
;
833 HEADER
*anhp
= (HEADER
*)(void *)ans
;
834 const struct sockaddr
*nsap
;
836 struct timespec now
, timeout
, finish
;
837 struct sockaddr_storage from
;
838 ISC_SOCKLEN_T fromlen
;
839 int resplen
, seconds
, n
, s
;
842 struct pollfd pollfd
;
847 nsap
= get_nsaddr(statp
, (size_t)ns
);
848 nsaplen
= get_salen(nsap
);
849 if (EXT(statp
).nssocks
[ns
] == -1) {
850 EXT(statp
).nssocks
[ns
] = socket(nsap
->sa_family
, SOCK_DGRAM
, 0);
851 if (EXT(statp
).nssocks
[ns
] > highestFD
) {
855 if (EXT(statp
).nssocks
[ns
] < 0) {
857 case EPROTONOSUPPORT
:
862 Perror(statp
, stderr
, "socket(dg)", errno
);
866 Perror(statp
, stderr
, "socket(dg)", errno
);
870 #ifndef CANNOT_CONNECT_DGRAM
872 * On a 4.3BSD+ machine (client and server,
873 * actually), sending to a nameserver datagram
874 * port with no nameserver will cause an
875 * ICMP port unreachable message to be returned.
876 * If our datagram socket is "connected" to the
877 * server, we get an ECONNREFUSED error on the next
878 * socket operation, and select returns if the
879 * error message is received. We can thus detect
880 * the absence of a nameserver without timing out.
882 if (connect(EXT(statp
).nssocks
[ns
], nsap
, (socklen_t
)nsaplen
) < 0) {
883 Aerror(statp
, stderr
, "connect(dg)", errno
, nsap
,
888 #endif /* !CANNOT_CONNECT_DGRAM */
889 Dprint(statp
->options
& RES_DEBUG
,
890 (stdout
, ";; new DG socket\n"))
892 s
= EXT(statp
).nssocks
[ns
];
893 #ifndef CANNOT_CONNECT_DGRAM
894 if (send(s
, (const char*)buf
, (size_t)buflen
, 0) != buflen
) {
895 Perror(statp
, stderr
, "send", errno
);
899 #else /* !CANNOT_CONNECT_DGRAM */
900 if (sendto(s
, (const char*)buf
, buflen
, 0, nsap
, nsaplen
) != buflen
)
902 Aerror(statp
, stderr
, "sendto", errno
, nsap
, nsaplen
);
906 #endif /* !CANNOT_CONNECT_DGRAM */
911 seconds
= (statp
->retrans
<< tries
);
913 seconds
/= statp
->nscount
;
917 timeout
= evConsTime((long)seconds
, 0L);
918 finish
= evAddTime(now
, timeout
);
926 if (evCmpTime(finish
, now
) > 0)
927 timeout
= evSubTime(finish
, now
);
929 timeout
= evConsTime(0L, 0L);
930 n
= pselect(s
+ 1, &dsmask
, NULL
, NULL
, &timeout
, NULL
);
932 timeout
= evSubTime(finish
, now
);
933 if (timeout
.tv_sec
< 0)
934 timeout
= evConsTime(0L, 0L);
935 polltimeout
= 1000*(int)timeout
.tv_sec
+
936 (int)timeout
.tv_nsec
/1000000;
938 pollfd
.events
= POLLRDNORM
;
939 n
= poll(&pollfd
, 1, polltimeout
);
940 #endif /* USE_POLL */
943 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; timeout\n"));
951 Perror(statp
, stderr
, "select", errno
);
953 Perror(statp
, stderr
, "poll", errno
);
954 #endif /* USE_POLL */
959 fromlen
= sizeof(from
);
960 resplen
= recvfrom(s
, (char*)ans
, (size_t)anssiz
,0,
961 (struct sockaddr
*)(void *)&from
, &fromlen
);
963 Perror(statp
, stderr
, "recvfrom", errno
);
968 if (resplen
< HFIXEDSZ
) {
970 * Undersized message.
972 Dprint(statp
->options
& RES_DEBUG
,
973 (stdout
, ";; undersized: %d\n",
979 if (hp
->id
!= anhp
->id
) {
981 * response from old query, ignore it.
982 * XXX - potential security hazard could
985 DprintQ((statp
->options
& RES_DEBUG
) ||
986 (statp
->pfcode
& RES_PRF_REPLY
),
987 (stdout
, ";; old answer:\n"),
988 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
991 if (!(statp
->options
& RES_INSECURE1
) &&
992 !res_ourserver_p(statp
, (struct sockaddr
*)(void *)&from
)) {
994 * response from wrong server? ignore it.
995 * XXX - potential security hazard could
998 DprintQ((statp
->options
& RES_DEBUG
) ||
999 (statp
->pfcode
& RES_PRF_REPLY
),
1000 (stdout
, ";; not our server:\n"),
1001 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
1004 #ifdef RES_USE_EDNS0
1005 if (anhp
->rcode
== FORMERR
&& (statp
->options
& RES_USE_EDNS0
) != 0U) {
1007 * Do not retry if the server do not understand EDNS0.
1008 * The case has to be captured here, as FORMERR packet do not
1009 * carry query section, hence res_queriesmatch() returns 0.
1011 DprintQ(statp
->options
& RES_DEBUG
,
1012 (stdout
, "server rejected query with EDNS0:\n"),
1013 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
1014 /* record the error */
1015 statp
->_flags
|= RES_F_EDNS0ERR
;
1020 if (!(statp
->options
& RES_INSECURE2
) &&
1021 !res_queriesmatch(buf
, buf
+ buflen
,
1022 ans
, ans
+ anssiz
)) {
1024 * response contains wrong query? ignore it.
1025 * XXX - potential security hazard could
1028 DprintQ((statp
->options
& RES_DEBUG
) ||
1029 (statp
->pfcode
& RES_PRF_REPLY
),
1030 (stdout
, ";; wrong query name:\n"),
1031 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
1034 if (anhp
->rcode
== SERVFAIL
||
1035 anhp
->rcode
== NOTIMP
||
1036 anhp
->rcode
== REFUSED
) {
1037 DprintQ(statp
->options
& RES_DEBUG
,
1038 (stdout
, "server rejected query:\n"),
1039 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
1041 /* don't retry if called from dig */
1045 if (!(statp
->options
& RES_IGNTC
) && anhp
->tc
) {
1047 * To get the rest of answer,
1048 * use TCP with same server.
1050 Dprint(statp
->options
& RES_DEBUG
,
1051 (stdout
, ";; truncated answer\n"));
1057 * All is well, or the error is fatal. Signal that the
1058 * next nameserver ought not be tried.
1064 Aerror(const res_state statp
, FILE *file
, const char *string
, int error
,
1065 const struct sockaddr
*address
, int alen
)
1068 char hbuf
[NI_MAXHOST
];
1069 char sbuf
[NI_MAXSERV
];
1071 if ((statp
->options
& RES_DEBUG
) != 0U) {
1072 if (getnameinfo(address
, (socklen_t
)alen
, hbuf
, sizeof(hbuf
),
1073 sbuf
, sizeof(sbuf
), niflags
)) {
1074 strncpy(hbuf
, "?", sizeof(hbuf
) - 1);
1075 hbuf
[sizeof(hbuf
) - 1] = '\0';
1076 strncpy(sbuf
, "?", sizeof(sbuf
) - 1);
1077 sbuf
[sizeof(sbuf
) - 1] = '\0';
1079 fprintf(file
, "res_send: %s ([%s].%s): %s\n",
1080 string
, hbuf
, sbuf
, strerror(error
));
1086 Perror(const res_state statp
, FILE *file
, const char *string
, int error
) {
1089 if ((statp
->options
& RES_DEBUG
) != 0U)
1090 fprintf(file
, "res_send: %s: %s\n",
1091 string
, strerror(error
));
1096 sock_eq(struct sockaddr
*a
, struct sockaddr
*b
) {
1097 struct sockaddr_in
*a4
, *b4
;
1098 struct sockaddr_in6
*a6
, *b6
;
1100 if (a
->sa_family
!= b
->sa_family
)
1102 switch (a
->sa_family
) {
1104 a4
= (struct sockaddr_in
*)(void *)a
;
1105 b4
= (struct sockaddr_in
*)(void *)b
;
1106 return a4
->sin_port
== b4
->sin_port
&&
1107 a4
->sin_addr
.s_addr
== b4
->sin_addr
.s_addr
;
1109 a6
= (struct sockaddr_in6
*)(void *)a
;
1110 b6
= (struct sockaddr_in6
*)(void *)b
;
1111 return a6
->sin6_port
== b6
->sin6_port
&&
1112 #ifdef HAVE_SIN6_SCOPE_ID
1113 a6
->sin6_scope_id
== b6
->sin6_scope_id
&&
1115 IN6_ARE_ADDR_EQUAL(&a6
->sin6_addr
, &b6
->sin6_addr
);
1121 #if defined(NEED_PSELECT) && !defined(USE_POLL)
1122 /* XXX needs to move to the porting library. */
1124 pselect(int nfds
, void *rfds
, void *wfds
, void *efds
,
1125 struct timespec
*tsp
, const sigset_t
*sigmask
)
1127 struct timeval tv
, *tvp
;
1133 tv
= evTimeVal(*tsp
);
1137 sigprocmask(SIG_SETMASK
, sigmask
, &sigs
);
1138 n
= select(nfds
, rfds
, wfds
, efds
, tvp
);
1140 sigprocmask(SIG_SETMASK
, &sigs
, NULL
);
1142 *tsp
= evTimeSpec(tv
);