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