118144Sralph /* 2*21388Sdist * Copyright (c) 1985 Regents of the University of California. 3*21388Sdist * All rights reserved. The Berkeley software License Agreement 4*21388Sdist * specifies the terms and conditions for redistribution. 518548Sralph */ 618548Sralph 7*21388Sdist #ifndef lint 8*21388Sdist static char sccsid[] = "@(#)res_send.c 5.1 (Berkeley) 05/30/85"; 9*21388Sdist #endif not lint 10*21388Sdist 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> 2118144Sralph #include <nameser.h> 2218144Sralph #include <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 4118144Sralph if (_res.options & RES_DEBUG) { 4218531Sralph printf("res_send()\n"); 4318144Sralph p_query(buf); 4418144Sralph } 4518531Sralph if (!(_res.options & RES_INIT)) 4618531Sralph res_init(); 4718144Sralph s = -1; 4818144Sralph v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 4918144Sralph id = hp->id; 5018144Sralph /* 5118144Sralph * Send request, RETRY times, or until successful 5218144Sralph */ 5318144Sralph for (retry = _res.retry; --retry >= 0; ) { 5418144Sralph if (v_circuit) { 5518144Sralph /* 5618144Sralph * Use virtual circuit. 5718144Sralph */ 5818144Sralph if (s < 0) 5918144Sralph s = socket(AF_INET, SOCK_STREAM, 0); 6018144Sralph if (connect(s, &_res.nsaddr, sizeof(_res.nsaddr)) < 0) { 6118144Sralph if (_res.options & RES_DEBUG) 6218144Sralph printf("connect failed %d\n", errno); 6318144Sralph (void) close(s); 6418144Sralph s = -1; 6518144Sralph continue; 6618144Sralph } 6718144Sralph /* 6818144Sralph * Send length & message 6918144Sralph */ 7018144Sralph len = htons(buflen); 7118144Sralph if (write(s, &len, sizeof(len)) != sizeof(len) || 7218144Sralph write(s, buf, buflen) != buflen) { 7318144Sralph if (_res.options & RES_DEBUG) 7418144Sralph printf("write failed %d\n", errno); 7518144Sralph (void) close(s); 7618144Sralph s = -1; 7718144Sralph continue; 7818144Sralph } 7918144Sralph /* 8018144Sralph * Receive length & response 8118144Sralph */ 8218144Sralph cp = answer; 8318144Sralph len = sizeof(short); 8418144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 8518144Sralph cp += n; 8618144Sralph len -= n; 8718144Sralph } 8818144Sralph if (n <= 0) { 8918144Sralph if (_res.options & RES_DEBUG) 9018144Sralph printf("read failed %d\n", errno); 9118144Sralph (void) close(s); 9218144Sralph s = -1; 9318144Sralph continue; 9418144Sralph } 9518144Sralph cp = answer; 9618144Sralph resplen = len = ntohs(*(short *)cp); 9718144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 9818144Sralph cp += n; 9918144Sralph len -= n; 10018144Sralph } 10118144Sralph if (n <= 0) { 10218144Sralph if (_res.options & RES_DEBUG) 10318144Sralph printf("read failed %d\n", errno); 10418144Sralph (void) close(s); 10518144Sralph s = -1; 10618144Sralph continue; 10718144Sralph } 10818144Sralph } else { 10918144Sralph /* 11018144Sralph * Use datagrams. 11118144Sralph */ 11218144Sralph if (s < 0) 11318144Sralph s = socket(AF_INET, SOCK_DGRAM, 0); 11418144Sralph if (sendto(s, buf, buflen, 0, &_res.nsaddr, 11518144Sralph sizeof(_res.nsaddr)) != buflen) { 11618144Sralph if (_res.options & RES_DEBUG) 11718144Sralph printf("sendto errno = %d\n", errno); 11818144Sralph } 11918144Sralph /* 12018144Sralph * Wait for reply 12118144Sralph */ 12218144Sralph timeout.tv_sec = _res.retrans; 12318144Sralph timeout.tv_usec = 0; 12418144Sralph dsmask = 1 << s; 12518144Sralph n = select(s+1, &dsmask, 0, 0, &timeout); 12618144Sralph if (n < 0) { 12718144Sralph if (_res.options & RES_DEBUG) 12818144Sralph printf("select errno = %d\n", errno); 12918144Sralph continue; 13018144Sralph } 13118144Sralph if (n == 0) { 13218144Sralph /* 13318144Sralph * timeout 13418144Sralph */ 13518144Sralph if (_res.options & RES_DEBUG) 13618144Sralph printf("timeout\n"); 13718144Sralph continue; 13818144Sralph } 13918144Sralph if ((resplen = recvfrom(s, answer, anslen, 14018144Sralph 0, 0, 0)) <= 0) { 14118144Sralph if (_res.options & RES_DEBUG) 14218144Sralph printf("recvfrom, errno=%d\n", errno); 14318144Sralph continue; 14418144Sralph } 14518144Sralph if (id != anhp->id) { 14618144Sralph /* 14718144Sralph * response from old query, ignore it 14818144Sralph */ 14918144Sralph if (_res.options & RES_DEBUG) { 15018144Sralph printf("old answer:\n"); 15118144Sralph p_query(answer); 15218144Sralph } 15318144Sralph continue; 15418144Sralph } 15518144Sralph if (!(_res.options & RES_IGNTC) && anhp->tc) { 15618144Sralph /* 15718144Sralph * get rest of answer 15818144Sralph */ 15918144Sralph if (_res.options & RES_DEBUG) 16018144Sralph printf("truncated answer\n"); 16118144Sralph (void) close(s); 16218144Sralph s = -1; 16318144Sralph retry = _res.retry; 16418144Sralph v_circuit = 1; 16518144Sralph continue; 16618144Sralph } 16718144Sralph } 16818144Sralph if (_res.options & RES_DEBUG) { 16918144Sralph printf("got answer:\n"); 17018144Sralph p_query(answer); 17118144Sralph } 17218144Sralph return (resplen); 17318144Sralph } 17418144Sralph return (-1); 17518144Sralph } 176