118144Sralph #ifndef lint 2*18531Sralph static char sccsid[] = "@(#)res_send.c 4.3 (Berkeley) 03/28/85"; 318144Sralph #endif 418144Sralph 518144Sralph /* 618144Sralph * Send query to name server and wait for reply. 718144Sralph */ 818144Sralph 918144Sralph #include <sys/types.h> 1018144Sralph #include <sys/time.h> 1118144Sralph #include <sys/socket.h> 1218144Sralph #include <netinet/in.h> 1318144Sralph #include <stdio.h> 1418144Sralph #include <errno.h> 1518144Sralph #include <nameser.h> 1618144Sralph #include <resolv.h> 1718144Sralph 1818144Sralph extern int errno; 1918144Sralph 20*18531Sralph res_send(buf, buflen, answer, anslen) 2118144Sralph char *buf; 2218144Sralph int buflen; 2318144Sralph char *answer; 2418144Sralph int anslen; 2518144Sralph { 2618144Sralph register int n; 2718144Sralph int s, retry, v_circuit, resplen; 2818144Sralph u_short id, len; 2918144Sralph char *cp; 3018144Sralph int dsmask; 3118144Sralph struct timeval timeout; 3218144Sralph HEADER *hp = (HEADER *) buf; 3318144Sralph HEADER *anhp = (HEADER *) answer; 3418144Sralph 3518144Sralph if (_res.options & RES_DEBUG) { 36*18531Sralph printf("res_send()\n"); 3718144Sralph p_query(buf); 3818144Sralph } 39*18531Sralph if (!(_res.options & RES_INIT)) 40*18531Sralph res_init(); 4118144Sralph s = -1; 4218144Sralph v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 4318144Sralph id = hp->id; 4418144Sralph /* 4518144Sralph * Send request, RETRY times, or until successful 4618144Sralph */ 4718144Sralph for (retry = _res.retry; --retry >= 0; ) { 4818144Sralph if (v_circuit) { 4918144Sralph /* 5018144Sralph * Use virtual circuit. 5118144Sralph */ 5218144Sralph if (s < 0) 5318144Sralph s = socket(AF_INET, SOCK_STREAM, 0); 5418144Sralph if (connect(s, &_res.nsaddr, sizeof(_res.nsaddr)) < 0) { 5518144Sralph if (_res.options & RES_DEBUG) 5618144Sralph printf("connect failed %d\n", errno); 5718144Sralph (void) close(s); 5818144Sralph s = -1; 5918144Sralph continue; 6018144Sralph } 6118144Sralph /* 6218144Sralph * Send length & message 6318144Sralph */ 6418144Sralph len = htons(buflen); 6518144Sralph if (write(s, &len, sizeof(len)) != sizeof(len) || 6618144Sralph write(s, buf, buflen) != buflen) { 6718144Sralph if (_res.options & RES_DEBUG) 6818144Sralph printf("write failed %d\n", errno); 6918144Sralph (void) close(s); 7018144Sralph s = -1; 7118144Sralph continue; 7218144Sralph } 7318144Sralph /* 7418144Sralph * Receive length & response 7518144Sralph */ 7618144Sralph cp = answer; 7718144Sralph len = sizeof(short); 7818144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 7918144Sralph cp += n; 8018144Sralph len -= n; 8118144Sralph } 8218144Sralph if (n <= 0) { 8318144Sralph if (_res.options & RES_DEBUG) 8418144Sralph printf("read failed %d\n", errno); 8518144Sralph (void) close(s); 8618144Sralph s = -1; 8718144Sralph continue; 8818144Sralph } 8918144Sralph cp = answer; 9018144Sralph resplen = len = ntohs(*(short *)cp); 9118144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 9218144Sralph cp += n; 9318144Sralph len -= n; 9418144Sralph } 9518144Sralph if (n <= 0) { 9618144Sralph if (_res.options & RES_DEBUG) 9718144Sralph printf("read failed %d\n", errno); 9818144Sralph (void) close(s); 9918144Sralph s = -1; 10018144Sralph continue; 10118144Sralph } 10218144Sralph } else { 10318144Sralph /* 10418144Sralph * Use datagrams. 10518144Sralph */ 10618144Sralph if (s < 0) 10718144Sralph s = socket(AF_INET, SOCK_DGRAM, 0); 10818144Sralph if (sendto(s, buf, buflen, 0, &_res.nsaddr, 10918144Sralph sizeof(_res.nsaddr)) != buflen) { 11018144Sralph if (_res.options & RES_DEBUG) 11118144Sralph printf("sendto errno = %d\n", errno); 11218144Sralph } 11318144Sralph /* 11418144Sralph * Wait for reply 11518144Sralph */ 11618144Sralph timeout.tv_sec = _res.retrans; 11718144Sralph timeout.tv_usec = 0; 11818144Sralph dsmask = 1 << s; 11918144Sralph n = select(s+1, &dsmask, 0, 0, &timeout); 12018144Sralph if (n < 0) { 12118144Sralph if (_res.options & RES_DEBUG) 12218144Sralph printf("select errno = %d\n", errno); 12318144Sralph continue; 12418144Sralph } 12518144Sralph if (n == 0) { 12618144Sralph /* 12718144Sralph * timeout 12818144Sralph */ 12918144Sralph if (_res.options & RES_DEBUG) 13018144Sralph printf("timeout\n"); 13118144Sralph continue; 13218144Sralph } 13318144Sralph if ((resplen = recvfrom(s, answer, anslen, 13418144Sralph 0, 0, 0)) <= 0) { 13518144Sralph if (_res.options & RES_DEBUG) 13618144Sralph printf("recvfrom, errno=%d\n", errno); 13718144Sralph continue; 13818144Sralph } 13918144Sralph if (id != anhp->id) { 14018144Sralph /* 14118144Sralph * response from old query, ignore it 14218144Sralph */ 14318144Sralph if (_res.options & RES_DEBUG) { 14418144Sralph printf("old answer:\n"); 14518144Sralph p_query(answer); 14618144Sralph } 14718144Sralph continue; 14818144Sralph } 14918144Sralph if (!(_res.options & RES_IGNTC) && anhp->tc) { 15018144Sralph /* 15118144Sralph * get rest of answer 15218144Sralph */ 15318144Sralph if (_res.options & RES_DEBUG) 15418144Sralph printf("truncated answer\n"); 15518144Sralph (void) close(s); 15618144Sralph s = -1; 15718144Sralph retry = _res.retry; 15818144Sralph v_circuit = 1; 15918144Sralph continue; 16018144Sralph } 16118144Sralph } 16218144Sralph if (_res.options & RES_DEBUG) { 16318144Sralph printf("got answer:\n"); 16418144Sralph p_query(answer); 16518144Sralph } 16618144Sralph return (resplen); 16718144Sralph } 16818144Sralph return (-1); 16918144Sralph } 170