1 #ifndef lint 2 static char sccsid[] = "@(#)res_send.c 4.1 (Berkeley) 03/01/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 sendquery(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("sendquery()\n"); 37 p_query(buf); 38 } 39 if (!(_res.options & RES_INIT)) { 40 if (!res_init()) 41 return (-1); 42 } 43 s = -1; 44 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 45 id = hp->id; 46 /* 47 * Send request, RETRY times, or until successful 48 */ 49 for (retry = _res.retry; --retry >= 0; ) { 50 if (v_circuit) { 51 /* 52 * Use virtual circuit. 53 */ 54 if (s < 0) 55 s = socket(AF_INET, SOCK_STREAM, 0); 56 if (connect(s, &_res.nsaddr, sizeof(_res.nsaddr)) < 0) { 57 if (_res.options & RES_DEBUG) 58 printf("connect failed %d\n", errno); 59 (void) close(s); 60 s = -1; 61 continue; 62 } 63 /* 64 * Send length & message 65 */ 66 len = htons(buflen); 67 if (write(s, &len, sizeof(len)) != sizeof(len) || 68 write(s, buf, buflen) != buflen) { 69 if (_res.options & RES_DEBUG) 70 printf("write failed %d\n", errno); 71 (void) close(s); 72 s = -1; 73 continue; 74 } 75 /* 76 * Receive length & response 77 */ 78 cp = answer; 79 len = sizeof(short); 80 while (len > 0 && (n = read(s, cp, len)) > 0) { 81 cp += n; 82 len -= n; 83 } 84 if (n <= 0) { 85 if (_res.options & RES_DEBUG) 86 printf("read failed %d\n", errno); 87 (void) close(s); 88 s = -1; 89 continue; 90 } 91 cp = answer; 92 resplen = len = ntohs(*(short *)cp); 93 while (len > 0 && (n = read(s, cp, len)) > 0) { 94 cp += n; 95 len -= n; 96 } 97 if (n <= 0) { 98 if (_res.options & RES_DEBUG) 99 printf("read failed %d\n", errno); 100 (void) close(s); 101 s = -1; 102 continue; 103 } 104 } else { 105 /* 106 * Use datagrams. 107 */ 108 if (s < 0) 109 s = socket(AF_INET, SOCK_DGRAM, 0); 110 if (sendto(s, buf, buflen, 0, &_res.nsaddr, 111 sizeof(_res.nsaddr)) != buflen) { 112 if (_res.options & RES_DEBUG) 113 printf("sendto errno = %d\n", errno); 114 } 115 /* 116 * Wait for reply 117 */ 118 timeout.tv_sec = _res.retrans; 119 timeout.tv_usec = 0; 120 dsmask = 1 << s; 121 n = select(s+1, &dsmask, 0, 0, &timeout); 122 if (n < 0) { 123 if (_res.options & RES_DEBUG) 124 printf("select errno = %d\n", errno); 125 continue; 126 } 127 if (n == 0) { 128 /* 129 * timeout 130 */ 131 if (_res.options & RES_DEBUG) 132 printf("timeout\n"); 133 continue; 134 } 135 if ((resplen = recvfrom(s, answer, anslen, 136 0, 0, 0)) <= 0) { 137 if (_res.options & RES_DEBUG) 138 printf("recvfrom, errno=%d\n", errno); 139 continue; 140 } 141 if (id != anhp->id) { 142 /* 143 * response from old query, ignore it 144 */ 145 if (_res.options & RES_DEBUG) { 146 int f; 147 148 printf("old answer:\n"); 149 f = creat("ro", 0644); 150 write(f, answer, resplen); 151 close(f); 152 p_query(answer); 153 } 154 continue; 155 } 156 if (!(_res.options & RES_IGNTC) && anhp->tc) { 157 /* 158 * get rest of answer 159 */ 160 if (_res.options & RES_DEBUG) 161 printf("truncated answer\n"); 162 (void) close(s); 163 s = -1; 164 retry = _res.retry; 165 v_circuit = 1; 166 continue; 167 } 168 } 169 if (_res.options & RES_DEBUG) { 170 printf("got answer:\n"); 171 p_query(answer); 172 } 173 return (resplen); 174 } 175 return (-1); 176 } 177