X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/31f0ead099bf5fb6c06e677ee52e1854c725ab7c..87b12937b3e4fb2610b90d5bb568a497f1d91a34:/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 2d9fb404e7..9e3709043d 100644 --- a/usr/src/lib/libc/net/res_send.c +++ b/usr/src/lib/libc/net/res_send.c @@ -1,6 +1,13 @@ + +/* + * Copyright (c) 1985 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + #ifndef lint -static char sccsid[] = "@(#)res_send.c 4.3 (Berkeley) %G%"; -#endif +static char sccsid[] = "@(#)res_send.c 6.3 (Berkeley) %G%"; +#endif not lint /* * Send query to name server and wait for reply. @@ -12,11 +19,13 @@ static char sccsid[] = "@(#)res_send.c 4.3 (Berkeley) %G%"; #include #include #include -#include -#include +#include +#include extern int errno; +#define KEEPOPEN (RES_USEVC|RES_STAYOPEN) + res_send(buf, buflen, answer, anslen) char *buf; int buflen; @@ -24,7 +33,8 @@ res_send(buf, buflen, answer, anslen) int anslen; { register int n; - int s, retry, v_circuit, resplen; + int retry, v_circuit, resplen, ns; + static int s = -1; u_short id, len; char *cp; int dsmask; @@ -32,40 +42,55 @@ res_send(buf, buflen, answer, anslen) HEADER *hp = (HEADER *) buf; HEADER *anhp = (HEADER *) answer; +#ifdef DEBUG if (_res.options & RES_DEBUG) { printf("res_send()\n"); p_query(buf); } +#endif DEBUG if (!(_res.options & RES_INIT)) - res_init(); - s = -1; + if (res_init() == -1) { + return(-1); + } 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 (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)); +#endif DEBUG if (v_circuit) { /* * Use virtual circuit. */ - if (s < 0) + if (s < 0) { s = socket(AF_INET, SOCK_STREAM, 0); - if (connect(s, &_res.nsaddr, sizeof(_res.nsaddr)) < 0) { - if (_res.options & RES_DEBUG) - printf("connect failed %d\n", errno); - (void) close(s); - s = -1; - continue; + if (connect(s, &(_res.nsaddr_list[ns]), + sizeof(struct sockaddr)) < 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf("connect failed %d\n",errno); +#endif DEBUG + (void) close(s); + s = -1; + continue; + } } /* * Send length & message */ len = htons(buflen); if (write(s, &len, sizeof(len)) != sizeof(len) || - write(s, buf, buflen) != buflen) { + write(s, buf, buflen) != buflen) { +#ifdef DEBUG if (_res.options & RES_DEBUG) printf("write failed %d\n", errno); +#endif DEBUG (void) close(s); s = -1; continue; @@ -80,8 +105,10 @@ res_send(buf, buflen, answer, anslen) len -= n; } if (n <= 0) { +#ifdef DEBUG if (_res.options & RES_DEBUG) printf("read failed %d\n", errno); +#endif DEBUG (void) close(s); s = -1; continue; @@ -93,8 +120,10 @@ res_send(buf, buflen, answer, anslen) len -= n; } if (n <= 0) { +#ifdef DEBUG if (_res.options & RES_DEBUG) printf("read failed %d\n", errno); +#endif DEBUG (void) close(s); s = -1; continue; @@ -105,53 +134,68 @@ res_send(buf, buflen, answer, anslen) */ if (s < 0) s = socket(AF_INET, SOCK_DGRAM, 0); - if (sendto(s, buf, buflen, 0, &_res.nsaddr, - sizeof(_res.nsaddr)) != buflen) { - if (_res.options & RES_DEBUG) - printf("sendto errno = %d\n", errno); + if (connect(s, &_res.nsaddr_list[ns], + sizeof(struct sockaddr)) < 0 || + send(s, buf, buflen, 0) != buflen) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf("connect/send errno = %d\n", + errno); +#endif DEBUG } /* * Wait for reply */ - timeout.tv_sec = _res.retrans; + timeout.tv_sec = + ((_res.retrans * _res.retry) / _res.nscount); 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) printf("select errno = %d\n", errno); +#endif DEBUG continue; } if (n == 0) { /* * timeout */ +#ifdef DEBUG if (_res.options & RES_DEBUG) printf("timeout\n"); +#endif DEBUG 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) printf("recvfrom, errno=%d\n", errno); +#endif DEBUG continue; } if (id != anhp->id) { /* * response from old query, ignore it */ +#ifdef DEBUG if (_res.options & RES_DEBUG) { printf("old answer:\n"); p_query(answer); } - continue; +#endif DEBUG + goto wait; } if (!(_res.options & RES_IGNTC) && anhp->tc) { /* * get rest of answer */ +#ifdef DEBUG if (_res.options & RES_DEBUG) printf("truncated answer\n"); +#endif DEBUG (void) close(s); s = -1; retry = _res.retry; @@ -159,11 +203,27 @@ res_send(buf, buflen, answer, anslen) continue; } } +#ifdef DEBUG if (_res.options & RES_DEBUG) { printf("got answer:\n"); p_query(answer); } - return (resplen); +#endif 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 + * keep that one open. + */ + if ((_res.options & KEEPOPEN) == KEEPOPEN && ns == 0) { + return (resplen); + } else { + (void) close(s); + s = -1; + return (resplen); + } + } } + (void) close(s); + errno = ETIMEDOUT; return (-1); }