projects
/
unix-history
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
tags
|
clone url
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
change retry loop to test before decrementing
[unix-history]
/
usr
/
src
/
lib
/
libc
/
net
/
res_send.c
diff --git
a/usr/src/lib/libc/net/res_send.c
b/usr/src/lib/libc/net/res_send.c
index
2aca83f
..
6ecde76
100644
(file)
--- a/
usr/src/lib/libc/net/res_send.c
+++ b/
usr/src/lib/libc/net/res_send.c
@@
-5,25
+5,29
@@
* specifies the terms and conditions for redistribution.
*/
* specifies the terms and conditions for redistribution.
*/
-#if
ndef lint
-static char sccsid[] = "@(#)res_send.c
5.6
(Berkeley) %G%";
-#endif not lint
+#if
defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_send.c
6.11
(Berkeley) %G%";
+#endif
LIBC_SCCS and
not lint
/*
* Send query to name server and wait for reply.
*/
/*
* Send query to name server and wait for reply.
*/
-#include <sys/
types
.h>
+#include <sys/
param
.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <arpa/nameser.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <arpa/nameser.h>
-#include <
arpa/
resolv.h>
+#include <resolv.h>
extern int errno;
extern int errno;
+static int s = -1; /* socket used for communications */
+
+#define KEEPOPEN (RES_USEVC|RES_STAYOPEN)
+
res_send(buf, buflen, answer, anslen)
char *buf;
int buflen;
res_send(buf, buflen, answer, anslen)
char *buf;
int buflen;
@@
-31,7
+35,8
@@
res_send(buf, buflen, answer, anslen)
int anslen;
{
register int n;
int anslen;
{
register int n;
- int s, retry, v_circuit, resplen, ns;
+ int retry, v_circuit, resplen, ns;
+ int gotsomewhere = 0;
u_short id, len;
char *cp;
int dsmask;
u_short id, len;
char *cp;
int dsmask;
@@
-49,44
+54,51
@@
res_send(buf, buflen, answer, anslen)
if (res_init() == -1) {
return(-1);
}
if (res_init() == -1) {
return(-1);
}
- s = -1;
v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
id = hp->id;
/*
* Send request, RETRY times, or until successful
*/
v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
id = hp->id;
/*
* Send request, RETRY times, or until successful
*/
- for (retry = _res.retry;
--retry >= 0;
) {
+ for (retry = _res.retry;
retry > 0; retry--
) {
for (ns = 0; ns < _res.nscount; ns++) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("Querying server (# %d) address = %s\n", ns+1,
for (ns = 0; ns < _res.nscount; ns++) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("Querying server (# %d) address = %s\n", ns+1,
- inet_ntoa(_res.nsaddr_list[ns].sin_addr.s_addr));
+ inet_ntoa(_res.nsaddr_list[ns].sin_addr.s_addr));
#endif DEBUG
if (v_circuit) {
/*
* Use virtual circuit.
*/
#endif DEBUG
if (v_circuit) {
/*
* Use virtual circuit.
*/
- if (s < 0)
+ if (s < 0)
{
s = socket(AF_INET, SOCK_STREAM, 0);
s = socket(AF_INET, SOCK_STREAM, 0);
- if (connect(s, &(_res.nsaddr_list[ns]),
- sizeof(struct sockaddr)) < 0) {
+ if (s < 0) {
#ifdef DEBUG
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
-
printf("connect failed %d\n", errno
);
+
if (_res.options & RES_DEBUG)
+
perror("socket failed"
);
#endif DEBUG
#endif DEBUG
- (void) close(s);
- s = -1;
- continue;
+ continue;
+ }
+ if (connect(s, &(_res.nsaddr_list[ns]),
+ sizeof(struct sockaddr)) < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ perror("connect failed");
+#endif DEBUG
+ (void) close(s);
+ s = -1;
+ continue;
+ }
}
/*
* Send length & message
*/
}
/*
* Send length & message
*/
- len = htons(buflen);
- if (write(s,
&len, sizeof(len)) != sizeof(len)
||
-
write(s, buf, buflen) != buflen) {
+ len = htons(
(u_short)
buflen);
+ if (write(s,
(char *)&len, sizeof(len)) != sizeof(len)
||
+ write(s, buf, buflen) != buflen) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
#ifdef DEBUG
if (_res.options & RES_DEBUG)
- p
rintf("write failed %d\n", errno
);
+ p
error("write failed"
);
#endif DEBUG
(void) close(s);
s = -1;
#endif DEBUG
(void) close(s);
s = -1;
@@
-97,29
+109,31
@@
res_send(buf, buflen, answer, anslen)
*/
cp = answer;
len = sizeof(short);
*/
cp = answer;
len = sizeof(short);
- while (len > 0 && (n = read(s, cp, len)) > 0) {
+ while (len > 0 &&
+ (n = read(s, (char *)cp, (int)len)) > 0) {
cp += n;
len -= n;
}
if (n <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
cp += n;
len -= n;
}
if (n <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
- p
rintf("read failed %d\n", errno
);
+ p
error("read failed"
);
#endif DEBUG
(void) close(s);
s = -1;
continue;
}
cp = answer;
#endif DEBUG
(void) close(s);
s = -1;
continue;
}
cp = answer;
- resplen = len = ntohs(*(short *)cp);
- while (len > 0 && (n = read(s, cp, len)) > 0) {
+ resplen = len = ntohs(*(u_short *)cp);
+ while (len > 0 &&
+ (n = read(s, (char *)cp, (int)len)) > 0) {
cp += n;
len -= n;
}
if (n <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
cp += n;
len -= n;
}
if (n <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
- p
rintf("read failed %d\n", errno
);
+ p
error("read failed"
);
#endif DEBUG
(void) close(s);
s = -1;
#endif DEBUG
(void) close(s);
s = -1;
@@
-131,25
+145,41
@@
res_send(buf, buflen, answer, anslen)
*/
if (s < 0)
s = socket(AF_INET, SOCK_DGRAM, 0);
*/
if (s < 0)
s = socket(AF_INET, SOCK_DGRAM, 0);
+#if BSD >= 43
+ if (connect(s, &_res.nsaddr_list[ns],
+ sizeof(struct sockaddr)) < 0 ||
+ send(s, buf, buflen, 0) != buflen) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ perror("connect");
+#endif DEBUG
+ continue;
+ }
+#else BSD
if (sendto(s, buf, buflen, 0, &_res.nsaddr_list[ns],
sizeof(struct sockaddr)) != buflen) {
#ifdef DEBUG
if (sendto(s, buf, buflen, 0, &_res.nsaddr_list[ns],
sizeof(struct sockaddr)) != buflen) {
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- p
rintf("sendto errno = %d\n", errno
);
+ if (_res.options & RES_DEBUG)
+ p
error("sendto"
);
#endif DEBUG
#endif DEBUG
+ continue;
}
}
+#endif BSD
/*
/*
- * Wait for reply
+ * Wait for reply
*/
*/
- timeout.tv_sec =
- ((_res.retrans * _res.retry) / _res.nscount);
+ timeout.tv_sec = (_res.retrans << (_res.retry - retry))
+ / _res.nscount;
+ if (timeout.tv_sec <= 0)
+ timeout.tv_sec = 1;
timeout.tv_usec = 0;
timeout.tv_usec = 0;
+wait:
dsmask = 1 << s;
n = select(s+1, &dsmask, 0, 0, &timeout);
if (n < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
dsmask = 1 << s;
n = select(s+1, &dsmask, 0, 0, &timeout);
if (n < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
- p
rintf("select errno = %d\n", errno
);
+ p
error("select"
);
#endif DEBUG
continue;
}
#endif DEBUG
continue;
}
@@
-161,16
+191,17
@@
res_send(buf, buflen, answer, anslen)
if (_res.options & RES_DEBUG)
printf("timeout\n");
#endif DEBUG
if (_res.options & RES_DEBUG)
printf("timeout\n");
#endif DEBUG
+ gotsomewhere = 1;
continue;
}
continue;
}
- if ((resplen = recvfrom(s, answer, anslen,
- 0, 0, 0)) <= 0) {
+ if ((resplen = recv(s, answer, anslen, 0)) <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
#ifdef DEBUG
if (_res.options & RES_DEBUG)
- p
rintf("recvfrom, errno=%d\n", errno
);
+ p
error("recvfrom"
);
#endif DEBUG
continue;
}
#endif DEBUG
continue;
}
+ gotsomewhere = 1;
if (id != anhp->id) {
/*
* response from old query, ignore it
if (id != anhp->id) {
/*
* response from old query, ignore it
@@
-181,7
+212,7
@@
res_send(buf, buflen, answer, anslen)
p_query(answer);
}
#endif DEBUG
p_query(answer);
}
#endif DEBUG
-
continue
;
+
goto wait
;
}
if (!(_res.options & RES_IGNTC) && anhp->tc) {
/*
}
if (!(_res.options & RES_IGNTC) && anhp->tc) {
/*
@@
-193,7
+224,11
@@
res_send(buf, buflen, answer, anslen)
#endif DEBUG
(void) close(s);
s = -1;
#endif DEBUG
(void) close(s);
s = -1;
- retry = _res.retry;
+ /*
+ * retry decremented on continue
+ * to desired starting value
+ */
+ retry = _res.retry + 1;
v_circuit = 1;
continue;
}
v_circuit = 1;
continue;
}
@@
-204,11
+239,40
@@
res_send(buf, buflen, answer, anslen)
p_query(answer);
}
#endif DEBUG
p_query(answer);
}
#endif DEBUG
- (void) close(s);
- return (resplen);
+ /*
+ * We are going to assume that the first server is preferred
+ * over the rest (i.e. it is on the local machine) and only
+ * keep that one open.
+ */
+ if ((_res.options & KEEPOPEN) == KEEPOPEN && ns == 0) {
+ return (resplen);
+ } else {
+ (void) close(s);
+ s = -1;
+ return (resplen);
+ }
}
}
(void) close(s);
}
}
(void) close(s);
- errno = ETIMEDOUT;
+ s = -1;
+ if (v_circuit == 0 && gotsomewhere == 0)
+ errno = ECONNREFUSED;
+ else
+ errno = ETIMEDOUT;
return (-1);
}
return (-1);
}
+
+/*
+ * 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.
+ */
+_res_close()
+{
+ if (s != -1) {
+ (void) close(s);
+ s = -1;
+ }
+}