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
73 #if defined(LIBC_SCCS) && !defined(lint)
74 static const char sccsid
[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
75 static const char rcsid
[] = "Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp";
76 #endif /* LIBC_SCCS and not lint */
80 * Send query to name server and wait for reply.
83 #include "port_before.h"
84 #include "fd_setsize.h"
86 #include <sys/types.h>
87 #include <sys/param.h>
89 #include <sys/socket.h>
92 #include <netinet/in.h>
93 #include <arpa/nameser.h>
94 #include <arpa/inet.h>
105 #include <isc/eventlib.h>
107 #include "port_after.h"
110 #ifdef HAVE_STROPTS_H
114 #endif /* USE_POLL */
116 /* Options. Leave them on. */
118 #include "res_debug.h"
119 #include "res_private.h"
121 #define EXT(res) ((res)->_u._ext)
124 static const int highestFD
= FD_SETSIZE
- 1;
126 static int highestFD
= 0;
131 static int get_salen
__P((const struct sockaddr
*));
132 static struct sockaddr
* get_nsaddr
__P((res_state
, size_t));
133 static int send_vc(res_state
, const u_char
*, int,
134 u_char
*, int, int *, int);
135 static int send_dg(res_state
, const u_char
*, int,
136 u_char
*, int, int *, int, int,
138 static void Aerror(const res_state
, FILE *, const char *, int,
139 const struct sockaddr
*, int);
140 static void Perror(const res_state
, FILE *, const char *, int);
141 static int sock_eq(struct sockaddr
*, struct sockaddr
*);
142 #if defined(NEED_PSELECT) && !defined(USE_POLL)
143 static int pselect(int, void *, void *, void *,
147 void res_pquery(const res_state
, const u_char
*, int, FILE *);
149 static const int niflags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
154 * looks up "ina" in _res.ns_addr_list[]
161 *\li paul vixie, 29may94
164 res_ourserver_p(const res_state statp
, const struct sockaddr
*sa
) {
165 const struct sockaddr_in
*inp
, *srv
;
166 const struct sockaddr_in6
*in6p
, *srv6
;
169 switch (sa
->sa_family
) {
171 inp
= (const struct sockaddr_in
*)sa
;
172 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
173 srv
= (struct sockaddr_in
*)get_nsaddr(statp
, ns
);
174 if (srv
->sin_family
== inp
->sin_family
&&
175 srv
->sin_port
== inp
->sin_port
&&
176 (srv
->sin_addr
.s_addr
== INADDR_ANY
||
177 srv
->sin_addr
.s_addr
== inp
->sin_addr
.s_addr
))
182 if (EXT(statp
).ext
== NULL
)
184 in6p
= (const struct sockaddr_in6
*)sa
;
185 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
186 srv6
= (struct sockaddr_in6
*)get_nsaddr(statp
, ns
);
187 if (srv6
->sin6_family
== in6p
->sin6_family
&&
188 srv6
->sin6_port
== in6p
->sin6_port
&&
189 #ifdef HAVE_SIN6_SCOPE_ID
190 (srv6
->sin6_scope_id
== 0 ||
191 srv6
->sin6_scope_id
== in6p
->sin6_scope_id
) &&
193 (IN6_IS_ADDR_UNSPECIFIED(&srv6
->sin6_addr
) ||
194 IN6_ARE_ADDR_EQUAL(&srv6
->sin6_addr
, &in6p
->sin6_addr
)))
205 * look for (name,type,class) in the query section of packet (buf,eom)
208 *\li buf + HFIXEDSZ <= eom
211 *\li -1 : format error
216 *\li paul vixie, 29may94
219 res_nameinquery(const char *name
, int type
, int class,
220 const u_char
*buf
, const u_char
*eom
)
222 const u_char
*cp
= buf
+ HFIXEDSZ
;
223 int qdcount
= ntohs(((const HEADER
*)buf
)->qdcount
);
225 while (qdcount
-- > 0) {
226 char tname
[MAXDNAME
+1];
227 int n
, ttype
, tclass
;
229 n
= dn_expand(buf
, eom
, cp
, tname
, sizeof tname
);
233 if (cp
+ 2 * INT16SZ
> eom
)
235 ttype
= ns_get16(cp
); cp
+= INT16SZ
;
236 tclass
= ns_get16(cp
); cp
+= INT16SZ
;
237 if (ttype
== type
&& tclass
== class &&
238 ns_samename(tname
, name
) == 1)
245 * is there a 1:1 mapping of (name,type,class)
246 * in (buf1,eom1) and (buf2,eom2)?
249 *\li -1 : format error
250 *\li 0 : not a 1:1 mapping
251 *\li >0 : is a 1:1 mapping
254 *\li paul vixie, 29may94
257 res_queriesmatch(const u_char
*buf1
, const u_char
*eom1
,
258 const u_char
*buf2
, const u_char
*eom2
)
260 const u_char
*cp
= buf1
+ HFIXEDSZ
;
261 int qdcount
= ntohs(((const HEADER
*)buf1
)->qdcount
);
263 if (buf1
+ HFIXEDSZ
> eom1
|| buf2
+ HFIXEDSZ
> eom2
)
267 * Only header section present in replies to
268 * dynamic update packets.
270 if ((((const HEADER
*)buf1
)->opcode
== ns_o_update
) &&
271 (((const HEADER
*)buf2
)->opcode
== ns_o_update
))
274 if (qdcount
!= ntohs(((const HEADER
*)buf2
)->qdcount
))
276 while (qdcount
-- > 0) {
277 char tname
[MAXDNAME
+1];
278 int n
, ttype
, tclass
;
280 n
= dn_expand(buf1
, eom1
, cp
, tname
, sizeof tname
);
284 if (cp
+ 2 * INT16SZ
> eom1
)
286 ttype
= ns_get16(cp
); cp
+= INT16SZ
;
287 tclass
= ns_get16(cp
); cp
+= INT16SZ
;
288 if (!res_nameinquery(tname
, ttype
, tclass
, buf2
, eom2
))
295 res_nsend(res_state statp
,
296 const u_char
*buf
, int buflen
, u_char
*ans
, int anssiz
)
298 int gotsomewhere
, terrno
, tries
, v_circuit
, resplen
, ns
, n
;
299 char abuf
[NI_MAXHOST
];
302 highestFD
= sysconf(_SC_OPEN_MAX
) - 1;
305 /* No name servers or res_init() failure */
306 if (statp
->nscount
== 0 || EXT(statp
).ext
== NULL
) {
310 if (anssiz
< HFIXEDSZ
) {
314 DprintQ((statp
->options
& RES_DEBUG
) || (statp
->pfcode
& RES_PRF_QUERY
),
315 (stdout
, ";; res_send()\n"), buf
, buflen
);
316 v_circuit
= (statp
->options
& RES_USEVC
) || buflen
> PACKETSZ
;
321 * If the ns_addr_list in the resolver context has changed, then
322 * invalidate our cached copy and the associated timing data.
324 if (EXT(statp
).nscount
!= 0) {
326 struct sockaddr_storage peer
;
327 ISC_SOCKLEN_T peerlen
;
329 if (EXT(statp
).nscount
!= statp
->nscount
)
332 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
333 if (statp
->nsaddr_list
[ns
].sin_family
&&
334 !sock_eq((struct sockaddr
*)&statp
->nsaddr_list
[ns
],
335 (struct sockaddr
*)&EXT(statp
).ext
->nsaddrs
[ns
])) {
340 if (EXT(statp
).nssocks
[ns
] == -1)
342 peerlen
= sizeof(peer
);
343 if (getpeername(EXT(statp
).nssocks
[ns
],
344 (struct sockaddr
*)&peer
, &peerlen
) < 0) {
348 if (!sock_eq((struct sockaddr
*)&peer
,
349 get_nsaddr(statp
, ns
))) {
356 EXT(statp
).nscount
= 0;
361 * Maybe initialize our private copy of the ns_addr_list.
363 if (EXT(statp
).nscount
== 0) {
364 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
365 EXT(statp
).nstimes
[ns
] = RES_MAXTIME
;
366 EXT(statp
).nssocks
[ns
] = -1;
367 if (!statp
->nsaddr_list
[ns
].sin_family
)
369 EXT(statp
).ext
->nsaddrs
[ns
].sin
=
370 statp
->nsaddr_list
[ns
];
372 EXT(statp
).nscount
= statp
->nscount
;
376 * Some resolvers want to even out the load on their nameservers.
377 * Note that RES_BLAST overrides RES_ROTATE.
379 if ((statp
->options
& RES_ROTATE
) != 0U &&
380 (statp
->options
& RES_BLAST
) == 0U) {
381 union res_sockaddr_union inu
;
382 struct sockaddr_in ina
;
383 int lastns
= statp
->nscount
- 1;
387 if (EXT(statp
).ext
!= NULL
)
388 inu
= EXT(statp
).ext
->nsaddrs
[0];
389 ina
= statp
->nsaddr_list
[0];
390 fd
= EXT(statp
).nssocks
[0];
391 nstime
= EXT(statp
).nstimes
[0];
392 for (ns
= 0; ns
< lastns
; ns
++) {
393 if (EXT(statp
).ext
!= NULL
)
394 EXT(statp
).ext
->nsaddrs
[ns
] =
395 EXT(statp
).ext
->nsaddrs
[ns
+ 1];
396 statp
->nsaddr_list
[ns
] = statp
->nsaddr_list
[ns
+ 1];
397 EXT(statp
).nssocks
[ns
] = EXT(statp
).nssocks
[ns
+ 1];
398 EXT(statp
).nstimes
[ns
] = EXT(statp
).nstimes
[ns
+ 1];
400 if (EXT(statp
).ext
!= NULL
)
401 EXT(statp
).ext
->nsaddrs
[lastns
] = inu
;
402 statp
->nsaddr_list
[lastns
] = ina
;
403 EXT(statp
).nssocks
[lastns
] = fd
;
404 EXT(statp
).nstimes
[lastns
] = nstime
;
408 * Send request, RETRY times, or until successful.
410 for (tries
= 0; tries
< statp
->retry
; tries
++) {
411 for (ns
= 0; ns
< statp
->nscount
; ns
++) {
412 struct sockaddr
*nsap
;
414 nsap
= get_nsaddr(statp
, ns
);
415 nsaplen
= get_salen(nsap
);
416 statp
->_flags
&= ~RES_F_LASTMASK
;
417 statp
->_flags
|= (ns
<< RES_F_LASTSHIFT
);
420 int done
= 0, loops
= 0;
425 act
= (*statp
->qhook
)(&nsap
, &buf
, &buflen
,
426 ans
, anssiz
, &resplen
);
437 /* give the hook another try */
438 if (++loops
< 42) /*doug adams*/
449 Dprint(((statp
->options
& RES_DEBUG
) &&
450 getnameinfo(nsap
, nsaplen
, abuf
, sizeof(abuf
),
451 NULL
, 0, niflags
) == 0),
452 (stdout
, ";; Querying server (# %d) address = %s\n",
457 /* Use VC; at most one attempt per server. */
458 tries
= statp
->retry
;
459 n
= send_vc(statp
, buf
, buflen
, ans
, anssiz
, &terrno
,
468 n
= send_dg(statp
, buf
, buflen
, ans
, anssiz
, &terrno
,
469 ns
, tries
, &v_circuit
, &gotsomewhere
);
479 Dprint((statp
->options
& RES_DEBUG
) ||
480 ((statp
->pfcode
& RES_PRF_REPLY
) &&
481 (statp
->pfcode
& RES_PRF_HEAD1
)),
482 (stdout
, ";; got answer:\n"));
484 DprintQ((statp
->options
& RES_DEBUG
) ||
485 (statp
->pfcode
& RES_PRF_REPLY
),
487 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
490 * If we have temporarily opened a virtual circuit,
491 * or if we haven't been asked to keep a socket open,
494 if ((v_circuit
&& (statp
->options
& RES_USEVC
) == 0U) ||
495 (statp
->options
& RES_STAYOPEN
) == 0U) {
499 int done
= 0, loops
= 0;
504 act
= (*statp
->rhook
)(nsap
, buf
, buflen
,
505 ans
, anssiz
, &resplen
);
515 /* give the hook another try */
516 if (++loops
< 42) /*doug adams*/
534 errno
= ECONNREFUSED
; /*%< no nameservers found */
536 errno
= ETIMEDOUT
; /*%< no answer obtained */
549 const struct sockaddr
*sa
;
553 /* There are people do not set sa_len. Be forgiving to them. */
558 if (sa
->sa_family
== AF_INET
)
559 return (sizeof(struct sockaddr_in
));
560 else if (sa
->sa_family
== AF_INET6
)
561 return (sizeof(struct sockaddr_in6
));
563 return (0); /*%< unknown, die on connect */
567 * pick appropriate nsaddr_list for use. see res_init() for initialization.
569 static struct sockaddr
*
575 if (!statp
->nsaddr_list
[n
].sin_family
&& EXT(statp
).ext
) {
577 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
578 * than struct sockaddr, and
579 * - user code did not update statp->nsaddr_list[n].
581 return (struct sockaddr
*)(void *)&EXT(statp
).ext
->nsaddrs
[n
];
584 * - user code updated statp->nsaddr_list[n], or
585 * - statp->nsaddr_list[n] has the same content as
586 * EXT(statp).ext->nsaddrs[n].
588 return (struct sockaddr
*)(void *)&statp
->nsaddr_list
[n
];
593 send_vc(res_state statp
,
594 const u_char
*buf
, int buflen
, u_char
*ans
, int anssiz
,
597 const HEADER
*hp
= (const HEADER
*) buf
;
598 HEADER
*anhp
= (HEADER
*) ans
;
599 struct sockaddr
*nsap
;
601 int truncating
, connreset
, resplen
, n
;
610 nsap
= get_nsaddr(statp
, ns
);
611 nsaplen
= get_salen(nsap
);
617 /* Are we still talking to whom we want to talk to? */
618 if (statp
->_vcsock
>= 0 && (statp
->_flags
& RES_F_VC
) != 0) {
619 struct sockaddr_storage peer
;
620 ISC_SOCKLEN_T size
= sizeof peer
;
622 if (getpeername(statp
->_vcsock
,
623 (struct sockaddr
*)&peer
, &size
) < 0 ||
624 !sock_eq((struct sockaddr
*)&peer
, nsap
)) {
626 statp
->_flags
&= ~RES_F_VC
;
630 if (statp
->_vcsock
< 0 || (statp
->_flags
& RES_F_VC
) == 0) {
631 if (statp
->_vcsock
>= 0)
634 statp
->_vcsock
= socket(nsap
->sa_family
, SOCK_STREAM
, 0);
635 if (statp
->_vcsock
> highestFD
) {
639 if (statp
->_vcsock
< 0) {
641 case EPROTONOSUPPORT
:
646 Perror(statp
, stderr
, "socket(vc)", errno
);
650 Perror(statp
, stderr
, "socket(vc)", errno
);
656 * Disable generation of SIGPIPE when writing to a closed
657 * socket. Write should return -1 and set errno to EPIPE
660 * Push on even if setsockopt(SO_NOSIGPIPE) fails.
662 (void)setsockopt(statp
->_vcsock
, SOL_SOCKET
, SO_NOSIGPIPE
, &on
,
666 if (connect(statp
->_vcsock
, nsap
, nsaplen
) < 0) {
668 Aerror(statp
, stderr
, "connect/vc", errno
, nsap
,
673 statp
->_flags
|= RES_F_VC
;
677 * Send length & message
679 ns_put16((u_short
)buflen
, (u_char
*)&len
);
680 iov
[0] = evConsIovec(&len
, INT16SZ
);
682 iov
[1] = evConsIovec(tmp
, buflen
);
683 if (writev(statp
->_vcsock
, iov
, 2) != (INT16SZ
+ buflen
)) {
685 Perror(statp
, stderr
, "write failed", errno
);
690 * Receive length & response
695 while ((n
= read(statp
->_vcsock
, (char *)cp
, (int)len
)) > 0) {
702 Perror(statp
, stderr
, "read failed", errno
);
705 * A long running process might get its TCP
706 * connection reset if the remote server was
707 * restarted. Requery the server instead of
708 * trying a new one. When there is only one
709 * server, this means that a query might work
710 * instead of failing. We only allow one reset
711 * per query to prevent looping.
713 if (*terrno
== ECONNRESET
&& !connreset
) {
721 resplen
= ns_get16(ans
);
722 if (resplen
> anssiz
) {
723 Dprint(statp
->options
& RES_DEBUG
,
724 (stdout
, ";; response truncated\n")
730 if (len
< HFIXEDSZ
) {
732 * Undersized message.
734 Dprint(statp
->options
& RES_DEBUG
,
735 (stdout
, ";; undersized: %d\n", len
));
741 while (len
!= 0 && (n
= read(statp
->_vcsock
, (char *)cp
, (int)len
)) > 0){
747 Perror(statp
, stderr
, "read(vc)", errno
);
753 * Flush rest of answer so connection stays in synch.
756 len
= resplen
- anssiz
;
760 n
= read(statp
->_vcsock
, junk
,
761 (len
> sizeof junk
) ? sizeof junk
: len
);
769 * If the calling applicating has bailed out of
770 * a previous call and failed to arrange to have
771 * the circuit closed or the server has got
772 * itself confused, then drop the packet and
773 * wait for the correct one.
775 if (hp
->id
!= anhp
->id
) {
776 DprintQ((statp
->options
& RES_DEBUG
) ||
777 (statp
->pfcode
& RES_PRF_REPLY
),
778 (stdout
, ";; old answer (unexpected):\n"),
779 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
784 * All is well, or the error is fatal. Signal that the
785 * next nameserver ought not be tried.
791 send_dg(res_state statp
, const u_char
*buf
, int buflen
, u_char
*ans
,
792 int anssiz
, int *terrno
, int ns
, int tries
, int *v_circuit
,
795 const HEADER
*hp
= (const HEADER
*) buf
;
796 HEADER
*anhp
= (HEADER
*) ans
;
797 const struct sockaddr
*nsap
;
799 struct timespec now
, timeout
, finish
;
800 struct sockaddr_storage from
;
801 ISC_SOCKLEN_T fromlen
;
802 int resplen
, seconds
, n
, s
;
805 struct pollfd pollfd
;
810 nsap
= get_nsaddr(statp
, ns
);
811 nsaplen
= get_salen(nsap
);
812 if (EXT(statp
).nssocks
[ns
] == -1) {
813 EXT(statp
).nssocks
[ns
] = socket(nsap
->sa_family
, SOCK_DGRAM
, 0);
814 if (EXT(statp
).nssocks
[ns
] > highestFD
) {
818 if (EXT(statp
).nssocks
[ns
] < 0) {
820 case EPROTONOSUPPORT
:
825 Perror(statp
, stderr
, "socket(dg)", errno
);
829 Perror(statp
, stderr
, "socket(dg)", errno
);
833 #ifndef CANNOT_CONNECT_DGRAM
835 * On a 4.3BSD+ machine (client and server,
836 * actually), sending to a nameserver datagram
837 * port with no nameserver will cause an
838 * ICMP port unreachable message to be returned.
839 * If our datagram socket is "connected" to the
840 * server, we get an ECONNREFUSED error on the next
841 * socket operation, and select returns if the
842 * error message is received. We can thus detect
843 * the absence of a nameserver without timing out.
845 if (connect(EXT(statp
).nssocks
[ns
], nsap
, nsaplen
) < 0) {
846 Aerror(statp
, stderr
, "connect(dg)", errno
, nsap
,
851 #endif /* !CANNOT_CONNECT_DGRAM */
852 Dprint(statp
->options
& RES_DEBUG
,
853 (stdout
, ";; new DG socket\n"))
855 s
= EXT(statp
).nssocks
[ns
];
856 #ifndef CANNOT_CONNECT_DGRAM
857 if (send(s
, (const char*)buf
, buflen
, 0) != buflen
) {
858 Perror(statp
, stderr
, "send", errno
);
862 #else /* !CANNOT_CONNECT_DGRAM */
863 if (sendto(s
, (const char*)buf
, buflen
, 0, nsap
, nsaplen
) != buflen
)
865 Aerror(statp
, stderr
, "sendto", errno
, nsap
, nsaplen
);
869 #endif /* !CANNOT_CONNECT_DGRAM */
874 seconds
= (statp
->retrans
<< tries
);
876 seconds
/= statp
->nscount
;
880 timeout
= evConsTime(seconds
, 0);
881 finish
= evAddTime(now
, timeout
);
889 if (evCmpTime(finish
, now
) > 0)
890 timeout
= evSubTime(finish
, now
);
892 timeout
= evConsTime(0, 0);
893 n
= pselect(s
+ 1, &dsmask
, NULL
, NULL
, &timeout
, NULL
);
895 timeout
= evSubTime(finish
, now
);
896 if (timeout
.tv_sec
< 0)
897 timeout
= evConsTime(0, 0);
898 polltimeout
= 1000*timeout
.tv_sec
+
899 timeout
.tv_nsec
/1000000;
901 pollfd
.events
= POLLRDNORM
;
902 n
= poll(&pollfd
, 1, polltimeout
);
903 #endif /* USE_POLL */
906 Dprint(statp
->options
& RES_DEBUG
, (stdout
, ";; timeout\n"));
914 Perror(statp
, stderr
, "select", errno
);
916 Perror(statp
, stderr
, "poll", errno
);
917 #endif /* USE_POLL */
922 fromlen
= sizeof(from
);
923 resplen
= recvfrom(s
, (char*)ans
, anssiz
,0,
924 (struct sockaddr
*)&from
, &fromlen
);
926 Perror(statp
, stderr
, "recvfrom", errno
);
931 if (resplen
< HFIXEDSZ
) {
933 * Undersized message.
935 Dprint(statp
->options
& RES_DEBUG
,
936 (stdout
, ";; undersized: %d\n",
942 if (hp
->id
!= anhp
->id
) {
944 * response from old query, ignore it.
945 * XXX - potential security hazard could
948 DprintQ((statp
->options
& RES_DEBUG
) ||
949 (statp
->pfcode
& RES_PRF_REPLY
),
950 (stdout
, ";; old answer:\n"),
951 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
954 if (!(statp
->options
& RES_INSECURE1
) &&
955 !res_ourserver_p(statp
, (struct sockaddr
*)&from
)) {
957 * response from wrong server? ignore it.
958 * XXX - potential security hazard could
961 DprintQ((statp
->options
& RES_DEBUG
) ||
962 (statp
->pfcode
& RES_PRF_REPLY
),
963 (stdout
, ";; not our server:\n"),
964 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
968 if (anhp
->rcode
== FORMERR
&& (statp
->options
& RES_USE_EDNS0
) != 0U) {
970 * Do not retry if the server do not understand EDNS0.
971 * The case has to be captured here, as FORMERR packet do not
972 * carry query section, hence res_queriesmatch() returns 0.
974 DprintQ(statp
->options
& RES_DEBUG
,
975 (stdout
, "server rejected query with EDNS0:\n"),
976 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
977 /* record the error */
978 statp
->_flags
|= RES_F_EDNS0ERR
;
983 if (!(statp
->options
& RES_INSECURE2
) &&
984 !res_queriesmatch(buf
, buf
+ buflen
,
985 ans
, ans
+ anssiz
)) {
987 * response contains wrong query? ignore it.
988 * XXX - potential security hazard could
991 DprintQ((statp
->options
& RES_DEBUG
) ||
992 (statp
->pfcode
& RES_PRF_REPLY
),
993 (stdout
, ";; wrong query name:\n"),
994 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
997 if (anhp
->rcode
== SERVFAIL
||
998 anhp
->rcode
== NOTIMP
||
999 anhp
->rcode
== REFUSED
) {
1000 DprintQ(statp
->options
& RES_DEBUG
,
1001 (stdout
, "server rejected query:\n"),
1002 ans
, (resplen
> anssiz
) ? anssiz
: resplen
);
1004 /* don't retry if called from dig */
1008 if (!(statp
->options
& RES_IGNTC
) && anhp
->tc
) {
1010 * To get the rest of answer,
1011 * use TCP with same server.
1013 Dprint(statp
->options
& RES_DEBUG
,
1014 (stdout
, ";; truncated answer\n"));
1020 * All is well, or the error is fatal. Signal that the
1021 * next nameserver ought not be tried.
1027 Aerror(const res_state statp
, FILE *file
, const char *string
, int error
,
1028 const struct sockaddr
*address
, int alen
)
1031 char hbuf
[NI_MAXHOST
];
1032 char sbuf
[NI_MAXSERV
];
1036 if ((statp
->options
& RES_DEBUG
) != 0U) {
1037 if (getnameinfo(address
, alen
, hbuf
, sizeof(hbuf
),
1038 sbuf
, sizeof(sbuf
), niflags
)) {
1039 strncpy(hbuf
, "?", sizeof(hbuf
) - 1);
1040 hbuf
[sizeof(hbuf
) - 1] = '\0';
1041 strncpy(sbuf
, "?", sizeof(sbuf
) - 1);
1042 sbuf
[sizeof(sbuf
) - 1] = '\0';
1044 fprintf(file
, "res_send: %s ([%s].%s): %s\n",
1045 string
, hbuf
, sbuf
, strerror(error
));
1051 Perror(const res_state statp
, FILE *file
, const char *string
, int error
) {
1054 if ((statp
->options
& RES_DEBUG
) != 0U)
1055 fprintf(file
, "res_send: %s: %s\n",
1056 string
, strerror(error
));
1061 sock_eq(struct sockaddr
*a
, struct sockaddr
*b
) {
1062 struct sockaddr_in
*a4
, *b4
;
1063 struct sockaddr_in6
*a6
, *b6
;
1065 if (a
->sa_family
!= b
->sa_family
)
1067 switch (a
->sa_family
) {
1069 a4
= (struct sockaddr_in
*)a
;
1070 b4
= (struct sockaddr_in
*)b
;
1071 return a4
->sin_port
== b4
->sin_port
&&
1072 a4
->sin_addr
.s_addr
== b4
->sin_addr
.s_addr
;
1074 a6
= (struct sockaddr_in6
*)a
;
1075 b6
= (struct sockaddr_in6
*)b
;
1076 return a6
->sin6_port
== b6
->sin6_port
&&
1077 #ifdef HAVE_SIN6_SCOPE_ID
1078 a6
->sin6_scope_id
== b6
->sin6_scope_id
&&
1080 IN6_ARE_ADDR_EQUAL(&a6
->sin6_addr
, &b6
->sin6_addr
);
1086 #if defined(NEED_PSELECT) && !defined(USE_POLL)
1087 /* XXX needs to move to the porting library. */
1089 pselect(int nfds
, void *rfds
, void *wfds
, void *efds
,
1090 struct timespec
*tsp
, const sigset_t
*sigmask
)
1092 struct timeval tv
, *tvp
;
1098 tv
= evTimeVal(*tsp
);
1102 sigprocmask(SIG_SETMASK
, sigmask
, &sigs
);
1103 n
= select(nfds
, rfds
, wfds
, efds
, tvp
);
1105 sigprocmask(SIG_SETMASK
, &sigs
, NULL
);
1107 *tsp
= evTimeSpec(tv
);