118144Sralph /* 221388Sdist * Copyright (c) 1985 Regents of the University of California. 321388Sdist * All rights reserved. The Berkeley software License Agreement 421388Sdist * specifies the terms and conditions for redistribution. 518548Sralph */ 618548Sralph 721388Sdist #ifndef lint 8*24734Sbloom static char sccsid[] = "@(#)res_send.c 5.5 (Berkeley) 09/14/85"; 921388Sdist #endif not lint 1021388Sdist 1118548Sralph /* 1218144Sralph * Send query to name server and wait for reply. 1318144Sralph */ 1418144Sralph 1518144Sralph #include <sys/types.h> 1618144Sralph #include <sys/time.h> 1718144Sralph #include <sys/socket.h> 1818144Sralph #include <netinet/in.h> 1918144Sralph #include <stdio.h> 2018144Sralph #include <errno.h> 2124083Skjd #include <arpa/nameser.h> 2224083Skjd #include <arpa/resolv.h> 2318144Sralph 2418144Sralph extern int errno; 2518144Sralph 2618531Sralph res_send(buf, buflen, answer, anslen) 2718144Sralph char *buf; 2818144Sralph int buflen; 2918144Sralph char *answer; 3018144Sralph int anslen; 3118144Sralph { 3218144Sralph register int n; 3318144Sralph int s, retry, v_circuit, resplen; 3418144Sralph u_short id, len; 3518144Sralph char *cp; 3618144Sralph int dsmask; 3718144Sralph struct timeval timeout; 3818144Sralph HEADER *hp = (HEADER *) buf; 3918144Sralph HEADER *anhp = (HEADER *) answer; 4018144Sralph 41*24734Sbloom #ifdef DEBUG 4218144Sralph if (_res.options & RES_DEBUG) { 4318531Sralph printf("res_send()\n"); 4418144Sralph p_query(buf); 4518144Sralph } 46*24734Sbloom #endif 4718531Sralph if (!(_res.options & RES_INIT)) 48*24734Sbloom if (res_init() == -1) { 49*24734Sbloom return(-1); 50*24734Sbloom } 5118144Sralph s = -1; 5218144Sralph v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 5318144Sralph id = hp->id; 5418144Sralph /* 5518144Sralph * Send request, RETRY times, or until successful 5618144Sralph */ 5718144Sralph for (retry = _res.retry; --retry >= 0; ) { 5818144Sralph if (v_circuit) { 5918144Sralph /* 6018144Sralph * Use virtual circuit. 6118144Sralph */ 6218144Sralph if (s < 0) 6318144Sralph s = socket(AF_INET, SOCK_STREAM, 0); 6418144Sralph if (connect(s, &_res.nsaddr, sizeof(_res.nsaddr)) < 0) { 65*24734Sbloom #ifdef DEBUG 6618144Sralph if (_res.options & RES_DEBUG) 6718144Sralph printf("connect failed %d\n", errno); 68*24734Sbloom #endif 6918144Sralph (void) close(s); 7018144Sralph s = -1; 7118144Sralph continue; 7218144Sralph } 7318144Sralph /* 7418144Sralph * Send length & message 7518144Sralph */ 7618144Sralph len = htons(buflen); 7718144Sralph if (write(s, &len, sizeof(len)) != sizeof(len) || 7818144Sralph write(s, buf, buflen) != buflen) { 79*24734Sbloom #ifdef DEBUG 8018144Sralph if (_res.options & RES_DEBUG) 8118144Sralph printf("write failed %d\n", errno); 82*24734Sbloom #endif 8318144Sralph (void) close(s); 8418144Sralph s = -1; 8518144Sralph continue; 8618144Sralph } 8718144Sralph /* 8818144Sralph * Receive length & response 8918144Sralph */ 9018144Sralph cp = answer; 9118144Sralph len = sizeof(short); 9218144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 9318144Sralph cp += n; 9418144Sralph len -= n; 9518144Sralph } 9618144Sralph if (n <= 0) { 97*24734Sbloom #ifdef DEBUG 9818144Sralph if (_res.options & RES_DEBUG) 9918144Sralph printf("read failed %d\n", errno); 100*24734Sbloom #endif 10118144Sralph (void) close(s); 10218144Sralph s = -1; 10318144Sralph continue; 10418144Sralph } 10518144Sralph cp = answer; 10618144Sralph resplen = len = ntohs(*(short *)cp); 10718144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 10818144Sralph cp += n; 10918144Sralph len -= n; 11018144Sralph } 11118144Sralph if (n <= 0) { 112*24734Sbloom #ifdef DEBUG 11318144Sralph if (_res.options & RES_DEBUG) 11418144Sralph printf("read failed %d\n", errno); 115*24734Sbloom #endif 11618144Sralph (void) close(s); 11718144Sralph s = -1; 11818144Sralph continue; 11918144Sralph } 12018144Sralph } else { 12118144Sralph /* 12218144Sralph * Use datagrams. 12318144Sralph */ 12418144Sralph if (s < 0) 12518144Sralph s = socket(AF_INET, SOCK_DGRAM, 0); 12618144Sralph if (sendto(s, buf, buflen, 0, &_res.nsaddr, 12718144Sralph sizeof(_res.nsaddr)) != buflen) { 128*24734Sbloom #ifdef DEBUG 12918144Sralph if (_res.options & RES_DEBUG) 13018144Sralph printf("sendto errno = %d\n", errno); 131*24734Sbloom #endif 13218144Sralph } 13318144Sralph /* 13418144Sralph * Wait for reply 13518144Sralph */ 13618144Sralph timeout.tv_sec = _res.retrans; 13718144Sralph timeout.tv_usec = 0; 13818144Sralph dsmask = 1 << s; 13918144Sralph n = select(s+1, &dsmask, 0, 0, &timeout); 14018144Sralph if (n < 0) { 141*24734Sbloom #ifdef DEBUG 14218144Sralph if (_res.options & RES_DEBUG) 14318144Sralph printf("select errno = %d\n", errno); 144*24734Sbloom #endif 14518144Sralph continue; 14618144Sralph } 14718144Sralph if (n == 0) { 14818144Sralph /* 14918144Sralph * timeout 15018144Sralph */ 151*24734Sbloom #ifdef DEBUG 15218144Sralph if (_res.options & RES_DEBUG) 15318144Sralph printf("timeout\n"); 154*24734Sbloom #endif 15518144Sralph continue; 15618144Sralph } 15718144Sralph if ((resplen = recvfrom(s, answer, anslen, 15818144Sralph 0, 0, 0)) <= 0) { 159*24734Sbloom #ifdef DEBUG 16018144Sralph if (_res.options & RES_DEBUG) 16118144Sralph printf("recvfrom, errno=%d\n", errno); 162*24734Sbloom #endif 16318144Sralph continue; 16418144Sralph } 16518144Sralph if (id != anhp->id) { 16618144Sralph /* 16718144Sralph * response from old query, ignore it 16818144Sralph */ 169*24734Sbloom #ifdef DEBUG 17018144Sralph if (_res.options & RES_DEBUG) { 17118144Sralph printf("old answer:\n"); 17218144Sralph p_query(answer); 17318144Sralph } 174*24734Sbloom #endif 17518144Sralph continue; 17618144Sralph } 17718144Sralph if (!(_res.options & RES_IGNTC) && anhp->tc) { 17818144Sralph /* 17918144Sralph * get rest of answer 18018144Sralph */ 181*24734Sbloom #ifdef DEBUG 18218144Sralph if (_res.options & RES_DEBUG) 18318144Sralph printf("truncated answer\n"); 184*24734Sbloom #endif 18518144Sralph (void) close(s); 18618144Sralph s = -1; 18718144Sralph retry = _res.retry; 18818144Sralph v_circuit = 1; 18918144Sralph continue; 19018144Sralph } 19118144Sralph } 192*24734Sbloom #ifdef DEBUG 19318144Sralph if (_res.options & RES_DEBUG) { 19418144Sralph printf("got answer:\n"); 19518144Sralph p_query(answer); 19618144Sralph } 197*24734Sbloom #endif 19823873Skjd (void) close(s); 19918144Sralph return (resplen); 20018144Sralph } 20123873Skjd (void) close(s); 20224032Skjd errno = ETIMEDOUT; 20318144Sralph return (-1); 20418144Sralph } 205