1 #ifndef lint 2 static char sccsid[] = "@(#)res_send.c 4.4 (Berkeley) 04/01/85"; 3 #endif 4 5 /* 6 * Copyright (c) 1985 Regents of the University of California 7 * All Rights Reserved 8 */ 9 10 /* 11 * Send query to name server and wait for reply. 12 */ 13 14 #include <sys/types.h> 15 #include <sys/time.h> 16 #include <sys/socket.h> 17 #include <netinet/in.h> 18 #include <stdio.h> 19 #include <errno.h> 20 #include <nameser.h> 21 #include <resolv.h> 22 23 extern int errno; 24 25 res_send(buf, buflen, answer, anslen) 26 char *buf; 27 int buflen; 28 char *answer; 29 int anslen; 30 { 31 register int n; 32 int s, retry, v_circuit, resplen; 33 u_short id, len; 34 char *cp; 35 int dsmask; 36 struct timeval timeout; 37 HEADER *hp = (HEADER *) buf; 38 HEADER *anhp = (HEADER *) answer; 39 40 if (_res.options & RES_DEBUG) { 41 printf("res_send()\n"); 42 p_query(buf); 43 } 44 if (!(_res.options & RES_INIT)) 45 res_init(); 46 s = -1; 47 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 48 id = hp->id; 49 /* 50 * Send request, RETRY times, or until successful 51 */ 52 for (retry = _res.retry; --retry >= 0; ) { 53 if (v_circuit) { 54 /* 55 * Use virtual circuit. 56 */ 57 if (s < 0) 58 s = socket(AF_INET, SOCK_STREAM, 0); 59 if (connect(s, &_res.nsaddr, sizeof(_res.nsaddr)) < 0) { 60 if (_res.options & RES_DEBUG) 61 printf("connect failed %d\n", errno); 62 (void) close(s); 63 s = -1; 64 continue; 65 } 66 /* 67 * Send length & message 68 */ 69 len = htons(buflen); 70 if (write(s, &len, sizeof(len)) != sizeof(len) || 71 write(s, buf, buflen) != buflen) { 72 if (_res.options & RES_DEBUG) 73 printf("write failed %d\n", errno); 74 (void) close(s); 75 s = -1; 76 continue; 77 } 78 /* 79 * Receive length & response 80 */ 81 cp = answer; 82 len = sizeof(short); 83 while (len > 0 && (n = read(s, cp, len)) > 0) { 84 cp += n; 85 len -= n; 86 } 87 if (n <= 0) { 88 if (_res.options & RES_DEBUG) 89 printf("read failed %d\n", errno); 90 (void) close(s); 91 s = -1; 92 continue; 93 } 94 cp = answer; 95 resplen = len = ntohs(*(short *)cp); 96 while (len > 0 && (n = read(s, cp, len)) > 0) { 97 cp += n; 98 len -= n; 99 } 100 if (n <= 0) { 101 if (_res.options & RES_DEBUG) 102 printf("read failed %d\n", errno); 103 (void) close(s); 104 s = -1; 105 continue; 106 } 107 } else { 108 /* 109 * Use datagrams. 110 */ 111 if (s < 0) 112 s = socket(AF_INET, SOCK_DGRAM, 0); 113 if (sendto(s, buf, buflen, 0, &_res.nsaddr, 114 sizeof(_res.nsaddr)) != buflen) { 115 if (_res.options & RES_DEBUG) 116 printf("sendto errno = %d\n", errno); 117 } 118 /* 119 * Wait for reply 120 */ 121 timeout.tv_sec = _res.retrans; 122 timeout.tv_usec = 0; 123 dsmask = 1 << s; 124 n = select(s+1, &dsmask, 0, 0, &timeout); 125 if (n < 0) { 126 if (_res.options & RES_DEBUG) 127 printf("select errno = %d\n", errno); 128 continue; 129 } 130 if (n == 0) { 131 /* 132 * timeout 133 */ 134 if (_res.options & RES_DEBUG) 135 printf("timeout\n"); 136 continue; 137 } 138 if ((resplen = recvfrom(s, answer, anslen, 139 0, 0, 0)) <= 0) { 140 if (_res.options & RES_DEBUG) 141 printf("recvfrom, errno=%d\n", errno); 142 continue; 143 } 144 if (id != anhp->id) { 145 /* 146 * response from old query, ignore it 147 */ 148 if (_res.options & RES_DEBUG) { 149 printf("old answer:\n"); 150 p_query(answer); 151 } 152 continue; 153 } 154 if (!(_res.options & RES_IGNTC) && anhp->tc) { 155 /* 156 * get rest of answer 157 */ 158 if (_res.options & RES_DEBUG) 159 printf("truncated answer\n"); 160 (void) close(s); 161 s = -1; 162 retry = _res.retry; 163 v_circuit = 1; 164 continue; 165 } 166 } 167 if (_res.options & RES_DEBUG) { 168 printf("got answer:\n"); 169 p_query(answer); 170 } 171 return (resplen); 172 } 173 return (-1); 174 } 175