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