* Copyright (c) 1985 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)res_send.c 6.12 (Berkeley) %G%";
#endif LIBC_SCCS and not lint
* Send query to name server and wait for reply.
#include <arpa/nameser.h>
static int s
= -1; /* socket used for communications */
#define KEEPOPEN (RES_USEVC|RES_STAYOPEN)
res_send(buf
, buflen
, answer
, anslen
)
int retry
, v_circuit
, resplen
, ns
;
HEADER
*hp
= (HEADER
*) buf
;
HEADER
*anhp
= (HEADER
*) answer
;
if (_res
.options
& RES_DEBUG
) {
if (!(_res
.options
& RES_INIT
))
v_circuit
= (_res
.options
& RES_USEVC
) || buflen
> PACKETSZ
;
* Send request, RETRY times, or until successful
for (retry
= _res
.retry
; retry
> 0; retry
--) {
for (ns
= 0; ns
< _res
.nscount
; ns
++) {
if (_res
.options
& RES_DEBUG
)
printf("Querying server (# %d) address = %s\n", ns
+1,
inet_ntoa(_res
.nsaddr_list
[ns
].sin_addr
.s_addr
));
s
= socket(AF_INET
, SOCK_STREAM
, 0);
if (_res
.options
& RES_DEBUG
)
if (connect(s
, &(_res
.nsaddr_list
[ns
]),
sizeof(struct sockaddr
)) < 0) {
if (_res
.options
& RES_DEBUG
)
perror("connect failed");
len
= htons((u_short
)buflen
);
iov
[0].iov_base
= (caddr_t
)&len
;
iov
[0].iov_len
= sizeof(len
);
if (writev(s
, iov
, 2) != sizeof(len
) + buflen
) {
if (_res
.options
& RES_DEBUG
)
* Receive length & response
(n
= read(s
, (char *)cp
, (int)len
)) > 0) {
if (_res
.options
& RES_DEBUG
)
resplen
= len
= ntohs(*(u_short
*)cp
);
(n
= read(s
, (char *)cp
, (int)len
)) > 0) {
if (_res
.options
& RES_DEBUG
)
s
= socket(AF_INET
, SOCK_DGRAM
, 0);
if (connect(s
, &_res
.nsaddr_list
[ns
],
sizeof(struct sockaddr
)) < 0 ||
send(s
, buf
, buflen
, 0) != buflen
) {
if (_res
.options
& RES_DEBUG
)
if (sendto(s
, buf
, buflen
, 0, &_res
.nsaddr_list
[ns
],
sizeof(struct sockaddr
)) != buflen
) {
if (_res
.options
& RES_DEBUG
)
timeout
.tv_sec
= (_res
.retrans
<< (_res
.retry
- retry
))
n
= select(s
+1, &dsmask
, (fd_set
*)NULL
,
(fd_set
*)NULL
, &timeout
);
if (_res
.options
& RES_DEBUG
)
if (_res
.options
& RES_DEBUG
)
if ((resplen
= recv(s
, answer
, anslen
, 0)) <= 0) {
if (_res
.options
& RES_DEBUG
)
* response from old query, ignore it
if (_res
.options
& RES_DEBUG
) {
if (!(_res
.options
& RES_IGNTC
) && anhp
->tc
) {
if (_res
.options
& RES_DEBUG
)
printf("truncated answer\n");
* retry decremented on continue
* to desired starting value
if (_res
.options
& RES_DEBUG
) {
* We are going to assume that the first server is preferred
* over the rest (i.e. it is on the local machine) and only
if ((_res
.options
& KEEPOPEN
) == KEEPOPEN
&& ns
== 0) {
if (v_circuit
== 0 && gotsomewhere
== 0)
* This routine is for closing the socket if a virtual circuit is used and
* the program wants to close it. This provides support for endhostent()
* which expects to close the socket.
* This routine is not expected to be user visible.