1: 
   2: /*
   3:  * Copyright (c) 1985 Regents of the University of California.
   4:  * All rights reserved.  The Berkeley software License Agreement
   5:  * specifies the terms and conditions for redistribution.
   6:  */
   7: 
   8: #if defined(LIBC_SCCS) && !defined(lint)
   9: static char sccsid[] = "@(#)res_send.c	6.13 (Berkeley) 5/7/86";
  10: #endif LIBC_SCCS and not lint
  11: 
  12: /*
  13:  * Send query to name server and wait for reply.
  14:  */
  15: 
  16: #include <sys/param.h>
  17: #include <sys/time.h>
  18: #include <sys/socket.h>
  19: #include <sys/uio.h>
  20: #include <netinet/in.h>
  21: #include <stdio.h>
  22: #include <errno.h>
  23: #include <arpa/nameser.h>
  24: #include <resolv.h>
  25: 
  26: extern int errno;
  27: 
  28: static int s = -1;  /* socket used for communications */
  29: 
  30: #define KEEPOPEN (RES_USEVC|RES_STAYOPEN)
  31: 
  32: res_send(buf, buflen, answer, anslen)
  33:     char *buf;
  34:     int buflen;
  35:     char *answer;
  36:     int anslen;
  37: {
  38:     register int n;
  39:     int retry, v_circuit, resplen, ns;
  40:     int gotsomewhere = 0;
  41:     u_short id, len;
  42:     char *cp;
  43:     fd_set dsmask;
  44:     struct timeval timeout;
  45:     HEADER *hp = (HEADER *) buf;
  46:     HEADER *anhp = (HEADER *) answer;
  47:     struct iovec iov[2];
  48: 
  49: #ifdef DEBUG
  50:     if (_res.options & RES_DEBUG) {
  51:         printf("res_send()\n");
  52:         p_query(buf);
  53:     }
  54: #endif DEBUG
  55:     if (!(_res.options & RES_INIT))
  56:         if (res_init() == -1) {
  57:             return(-1);
  58:         }
  59:     v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
  60:     id = hp->id;
  61:     /*
  62: 	 * Send request, RETRY times, or until successful
  63: 	 */
  64:     for (retry = _res.retry; retry > 0; retry--) {
  65:        for (ns = 0; ns < _res.nscount; ns++) {
  66: #ifdef DEBUG
  67:         if (_res.options & RES_DEBUG)
  68:             printf("Querying server (# %d) address = %s\n", ns+1,
  69:                   inet_ntoa(_res.nsaddr_list[ns].sin_addr.s_addr));
  70: #endif DEBUG
  71:         if (v_circuit) {
  72:             /*
  73: 			 * Use virtual circuit.
  74: 			 */
  75:             if (s < 0) {
  76:                 s = socket(AF_INET, SOCK_STREAM, 0);
  77:                 if (s < 0) {
  78: #ifdef DEBUG
  79:                     if (_res.options & RES_DEBUG)
  80:                         perror("socket failed");
  81: #endif DEBUG
  82:                     continue;
  83:                 }
  84:                 if (connect(s, &(_res.nsaddr_list[ns]),
  85:                    sizeof(struct sockaddr)) < 0) {
  86: #ifdef DEBUG
  87:                     if (_res.options & RES_DEBUG)
  88:                         perror("connect failed");
  89: #endif DEBUG
  90:                     (void) close(s);
  91:                     s = -1;
  92:                     continue;
  93:                 }
  94:             }
  95:             /*
  96: 			 * Send length & message
  97: 			 */
  98:             len = htons((u_short)buflen);
  99:             iov[0].iov_base = (caddr_t)&len;
 100:             iov[0].iov_len = sizeof(len);
 101:             iov[1].iov_base = buf;
 102:             iov[1].iov_len = buflen;
 103:             if (writev(s, iov, 2) != sizeof(len) + buflen) {
 104: #ifdef DEBUG
 105:                 if (_res.options & RES_DEBUG)
 106:                     perror("write failed");
 107: #endif DEBUG
 108:                 (void) close(s);
 109:                 s = -1;
 110:                 continue;
 111:             }
 112:             /*
 113: 			 * Receive length & response
 114: 			 */
 115:             cp = answer;
 116:             len = sizeof(short);
 117:             while (len != 0 &&
 118:                 (n = read(s, (char *)cp, (int)len)) > 0) {
 119:                 cp += n;
 120:                 len -= n;
 121:             }
 122:             if (n <= 0) {
 123: #ifdef DEBUG
 124:                 if (_res.options & RES_DEBUG)
 125:                     perror("read failed");
 126: #endif DEBUG
 127:                 (void) close(s);
 128:                 s = -1;
 129:                 continue;
 130:             }
 131:             cp = answer;
 132:             resplen = len = ntohs(*(u_short *)cp);
 133:             while (len != 0 &&
 134:                (n = read(s, (char *)cp, (int)len)) > 0) {
 135:                 cp += n;
 136:                 len -= n;
 137:             }
 138:             if (n <= 0) {
 139: #ifdef DEBUG
 140:                 if (_res.options & RES_DEBUG)
 141:                     perror("read failed");
 142: #endif DEBUG
 143:                 (void) close(s);
 144:                 s = -1;
 145:                 continue;
 146:             }
 147:         } else {
 148:             /*
 149: 			 * Use datagrams.
 150: 			 */
 151:             if (s < 0)
 152:                 s = socket(AF_INET, SOCK_DGRAM, 0);
 153: #if BSD >= 43
 154:             if (connect(s, &_res.nsaddr_list[ns],
 155:                 sizeof(struct sockaddr)) < 0 ||
 156:                 send(s, buf, buflen, 0) != buflen) {
 157: #ifdef DEBUG
 158:                 if (_res.options & RES_DEBUG)
 159:                     perror("connect");
 160: #endif DEBUG
 161:                 continue;
 162:             }
 163: #else BSD
 164:             if (sendto(s, buf, buflen, 0, &_res.nsaddr_list[ns],
 165:                 sizeof(struct sockaddr)) != buflen) {
 166: #ifdef DEBUG
 167:                 if (_res.options & RES_DEBUG)
 168:                     perror("sendto");
 169: #endif DEBUG
 170:                 continue;
 171:             }
 172: #endif BSD
 173:             /*
 174: 			 * Wait for reply
 175: 			 */
 176:             timeout.tv_sec = (_res.retrans << (_res.retry - retry))
 177:                 / _res.nscount;
 178:             if (timeout.tv_sec <= 0)
 179:                 timeout.tv_sec = 1;
 180:             timeout.tv_usec = 0;
 181: wait:
 182:             FD_ZERO(&dsmask);
 183:             FD_SET(s, &dsmask);
 184:             n = select(s+1, &dsmask, (fd_set *)NULL,
 185:                 (fd_set *)NULL, &timeout);
 186:             if (n < 0) {
 187: #ifdef DEBUG
 188:                 if (_res.options & RES_DEBUG)
 189:                     perror("select");
 190: #endif DEBUG
 191:                 continue;
 192:             }
 193:             if (n == 0) {
 194:                 /*
 195: 				 * timeout
 196: 				 */
 197: #ifdef DEBUG
 198:                 if (_res.options & RES_DEBUG)
 199:                     printf("timeout\n");
 200: #endif DEBUG
 201:                 gotsomewhere = 1;
 202:                 continue;
 203:             }
 204:             if ((resplen = recv(s, answer, anslen, 0)) <= 0) {
 205: #ifdef DEBUG
 206:                 if (_res.options & RES_DEBUG)
 207:                     perror("recvfrom");
 208: #endif DEBUG
 209:                 continue;
 210:             }
 211:             gotsomewhere = 1;
 212:             if (id != anhp->id) {
 213:                 /*
 214: 				 * response from old query, ignore it
 215: 				 */
 216: #ifdef DEBUG
 217:                 if (_res.options & RES_DEBUG) {
 218:                     printf("old answer:\n");
 219:                     p_query(answer);
 220:                 }
 221: #endif DEBUG
 222:                 goto wait;
 223:             }
 224:             if (!(_res.options & RES_IGNTC) && anhp->tc) {
 225:                 /*
 226: 				 * get rest of answer
 227: 				 */
 228: #ifdef DEBUG
 229:                 if (_res.options & RES_DEBUG)
 230:                     printf("truncated answer\n");
 231: #endif DEBUG
 232:                 (void) close(s);
 233:                 s = -1;
 234:                 /*
 235: 				 * retry decremented on continue
 236: 				 * to desired starting value
 237: 				 */
 238:                 retry = _res.retry + 1;
 239:                 v_circuit = 1;
 240:                 continue;
 241:             }
 242:         }
 243: #ifdef DEBUG
 244:         if (_res.options & RES_DEBUG) {
 245:             printf("got answer:\n");
 246:             p_query(answer);
 247:         }
 248: #endif DEBUG
 249:         /*
 250: 		 * We are going to assume that the first server is preferred
 251: 		 * over the rest (i.e. it is on the local machine) and only
 252: 		 * keep that one open.
 253: 		 */
 254:         if ((_res.options & KEEPOPEN) == KEEPOPEN && ns == 0) {
 255:             return (resplen);
 256:         } else {
 257:             (void) close(s);
 258:             s = -1;
 259:             return (resplen);
 260:         }
 261:        }
 262:     }
 263:     (void) close(s);
 264:     s = -1;
 265:     if (v_circuit == 0 && gotsomewhere == 0)
 266:         errno = ECONNREFUSED;
 267:     else
 268:         errno = ETIMEDOUT;
 269:     return (-1);
 270: }
 271: 
 272: /*
 273:  * This routine is for closing the socket if a virtual circuit is used and
 274:  * the program wants to close it.  This provides support for endhostent()
 275:  * which expects to close the socket.
 276:  *
 277:  * This routine is not expected to be user visible.
 278:  */
 279: _res_close()
 280: {
 281:     if (s != -1) {
 282:         (void) close(s);
 283:         s = -1;
 284:     }
 285: }

Defined functions

_res_close defined in line 279; used 1 times

Defined variables

s defined in line 28; used 32 times
sccsid defined in line 9; never used

Defined macros

KEEPOPEN defined in line 30; used 2 times
  • in line 254(2)
Last modified: 1986-05-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1216
Valid CSS Valid XHTML 1.0 Strict