2 * ++Copyright++ 1985, 1989
4 * Copyright (c) 1985, 1989 Regents of the University of California.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * 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
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid
[] = "@(#)res_send.c 6.27 (Berkeley) 2/24/91";
58 static char rcsid
[] = "$Id$";
59 #endif /* LIBC_SCCS and not lint */
62 * Send query to name server and wait for reply.
65 #include <sys/param.h>
67 #include <sys/socket.h>
69 #include <netinet/in.h>
70 #include <arpa/nameser.h>
71 #include <arpa/inet.h>
75 #include "../conf/portability.h"
77 static int s
= -1; /* socket used for communications */
78 static struct sockaddr no_addr
;
83 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
84 #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
85 #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
86 #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
89 res_send(buf
, buflen
, answer
, anslen
)
96 int try, v_circuit
, resplen
, ns
;
97 int gotsomewhere
= 0, connected
= 0;
102 struct timeval timeout
;
103 HEADER
*hp
= (HEADER
*) buf
;
104 HEADER
*anhp
= (HEADER
*) answer
;
105 u_int badns
; /* XXX NSMAX can't exceed #/bits per this */
107 int terrno
= ETIMEDOUT
;
111 if ((_res
.options
& RES_DEBUG
) || (_res
.pfcode
& RES_PRF_QUERY
)) {
112 printf(";; res_send()\n");
116 if (!(_res
.options
& RES_INIT
))
117 if (res_init() == -1) {
120 v_circuit
= (_res
.options
& RES_USEVC
) || buflen
> PACKETSZ
;
124 * Send request, RETRY times, or until successful
126 for (try = 0; try < _res
.retry
; try++) {
127 for (ns
= 0; ns
< _res
.nscount
; ns
++) {
131 if (_res
.options
& RES_DEBUG
)
132 printf(";; Querying server (# %d) address = %s\n",
134 inet_ntoa(_res
.nsaddr_list
[ns
].sin_addr
));
141 * Use virtual circuit;
142 * at most one attempt per server.
146 s
= socket(AF_INET
, SOCK_STREAM
, 0);
150 if (_res
.options
& RES_DEBUG
)
151 perror("socket (vc) failed");
156 (struct sockaddr
*)&(_res
.nsaddr_list
[ns
]),
157 sizeof(struct sockaddr
)) < 0) {
160 if (_res
.options
& RES_DEBUG
)
161 perror("connect failed");
169 * Send length & message
171 len
= htons((u_short
)buflen
);
172 iov
[0].iov_base
= (caddr_t
)&len
;
173 iov
[0].iov_len
= sizeof(len
);
174 iov
[1].iov_base
= (char *)buf
;
175 iov
[1].iov_len
= buflen
;
176 if (writev(s
, iov
, 2) != sizeof(len
) + buflen
) {
179 if (_res
.options
& RES_DEBUG
)
180 perror("write failed");
187 * Receive length & response
192 (n
= read(s
, (char *)cp
, (int)len
)) > 0) {
199 if (_res
.options
& RES_DEBUG
)
200 perror("read failed");
205 * A long running process might get its TCP
206 * connection reset if the remote server was
207 * restarted. Requery the server instead of
208 * trying a new one. When there is only one
209 * server, this means that a query might work
210 * instead of failing. We only allow one reset
211 * per query to prevent looping.
213 if (terrno
== ECONNRESET
&& !connreset
) {
220 if ((resplen
= ntohs(*(u_short
*)cp
)) > anslen
) {
222 if (_res
.options
& RES_DEBUG
)
224 ";; response truncated\n");
231 (n
= read(s
, (char *)cp
, (int)len
)) > 0) {
238 if (_res
.options
& RES_DEBUG
)
239 perror("read failed");
247 * Flush rest of answer
248 * so connection stays in synch.
251 len
= resplen
- anslen
;
253 n
= (len
> sizeof(junk
) ?
255 if ((n
= read(s
, junk
, n
)) > 0)
266 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
270 if (_res
.options
& RES_DEBUG
)
271 perror("socket (dg) failed");
278 * I'm tired of answering this question, so:
279 * On a 4.3BSD+ machine (client and server,
280 * actually), sending to a nameserver datagram
281 * port with no nameserver will cause an
282 * ICMP port unreachable message to be returned.
283 * If our datagram socket is "connected" to the
284 * server, we get an ECONNREFUSED error on the next
285 * socket operation, and select returns if the
286 * error message is received. We can thus detect
287 * the absence of a nameserver without timing out.
288 * If we have sent queries to at least two servers,
289 * however, we don't want to remain connected,
290 * as we wish to receive answers from the first
293 if (_res
.nscount
== 1 || (try == 0 && ns
== 0)) {
295 * Don't use connect if we might
296 * still receive a response
297 * from another server.
299 if (connected
== 0) {
302 &_res
.nsaddr_list
[ns
],
303 sizeof(struct sockaddr
)
306 if (_res
.options
& RES_DEBUG
)
313 if (send(s
, buf
, buflen
, 0) != buflen
) {
315 if (_res
.options
& RES_DEBUG
)
322 * Disconnect if we want to listen
323 * for responses from more than one server.
326 (void) connect(s
, &no_addr
,
331 if (sendto(s
, buf
, buflen
, 0,
332 (struct sockaddr
*)&_res
.nsaddr_list
[ns
],
333 sizeof(struct sockaddr
)) != buflen
) {
335 if (_res
.options
& RES_DEBUG
)
347 timeout
.tv_sec
= (_res
.retrans
<< try);
349 timeout
.tv_sec
/= _res
.nscount
;
350 if ((long) timeout
.tv_sec
<= 0)
356 n
= select(s
+1, &dsmask
, (fd_set
*)NULL
,
357 (fd_set
*)NULL
, &timeout
);
360 if (_res
.options
& RES_DEBUG
)
370 if (_res
.options
& RES_DEBUG
)
371 printf(";; timeout\n");
378 if ((resplen
= recv(s
, answer
, anslen
, 0)) <= 0) {
380 if (_res
.options
& RES_DEBUG
)
386 if (id
!= anhp
->id
) {
388 * response from old query, ignore it
391 if ((_res
.options
& RES_DEBUG
) ||
392 (_res
.pfcode
& RES_PRF_REPLY
)) {
393 printf(";; old answer:\n");
399 if (anhp
->rcode
== SERVFAIL
400 || anhp
->rcode
== NOTIMP
401 || anhp
->rcode
== REFUSED
) {
403 if (_res
.options
& RES_DEBUG
) {
404 printf("server rejected query:\n");
411 if (!(_res
.options
& RES_IGNTC
) && anhp
->tc
) {
413 * get rest of answer;
414 * use TCP with same server.
417 if (_res
.options
& RES_DEBUG
)
418 printf(";; truncated answer\n");
427 if (_res
.options
& RES_DEBUG
)
428 printf(";; got answer:\n");
429 if ((_res
.options
& RES_DEBUG
)
430 || (_res
.pfcode
& RES_PRF_REPLY
)) {
435 * If using virtual circuits, we assume that the first server
436 * is preferred * over the rest (i.e. it is on the local
437 * machine) and only keep that one open.
438 * If we have temporarily opened a virtual circuit,
439 * or if we haven't been asked to keep a socket open,
443 ((_res
.options
& RES_USEVC
) == 0 || ns
!= 0)) ||
444 (_res
.options
& RES_STAYOPEN
) == 0) {
456 if (gotsomewhere
== 0)
457 errno
= ECONNREFUSED
; /* no nameservers found */
459 errno
= ETIMEDOUT
; /* no answer obtained */
466 * This routine is for closing the socket if a virtual circuit is used and
467 * the program wants to close it. This provides support for endhostent()
468 * which expects to close the socket.
470 * This routine is not expected to be user visible.