1*25243Skjd 218144Sralph /* 321388Sdist * Copyright (c) 1985 Regents of the University of California. 421388Sdist * All rights reserved. The Berkeley software License Agreement 521388Sdist * specifies the terms and conditions for redistribution. 618548Sralph */ 718548Sralph 821388Sdist #ifndef lint 9*25243Skjd static char sccsid[] = "@(#)res_send.c 5.6 (Berkeley) 10/21/85"; 1021388Sdist #endif not lint 1121388Sdist 1218548Sralph /* 1318144Sralph * Send query to name server and wait for reply. 1418144Sralph */ 1518144Sralph 1618144Sralph #include <sys/types.h> 1718144Sralph #include <sys/time.h> 1818144Sralph #include <sys/socket.h> 1918144Sralph #include <netinet/in.h> 2018144Sralph #include <stdio.h> 2118144Sralph #include <errno.h> 2224083Skjd #include <arpa/nameser.h> 2324083Skjd #include <arpa/resolv.h> 2418144Sralph 2518144Sralph extern int errno; 2618144Sralph 2718531Sralph res_send(buf, buflen, answer, anslen) 2818144Sralph char *buf; 2918144Sralph int buflen; 3018144Sralph char *answer; 3118144Sralph int anslen; 3218144Sralph { 3318144Sralph register int n; 34*25243Skjd int s, retry, v_circuit, resplen, ns; 3518144Sralph u_short id, len; 3618144Sralph char *cp; 3718144Sralph int dsmask; 3818144Sralph struct timeval timeout; 3918144Sralph HEADER *hp = (HEADER *) buf; 4018144Sralph HEADER *anhp = (HEADER *) answer; 4118144Sralph 4224734Sbloom #ifdef DEBUG 4318144Sralph if (_res.options & RES_DEBUG) { 4418531Sralph printf("res_send()\n"); 4518144Sralph p_query(buf); 4618144Sralph } 47*25243Skjd #endif DEBUG 4818531Sralph if (!(_res.options & RES_INIT)) 4924734Sbloom if (res_init() == -1) { 5024734Sbloom return(-1); 5124734Sbloom } 5218144Sralph s = -1; 5318144Sralph v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 5418144Sralph id = hp->id; 5518144Sralph /* 5618144Sralph * Send request, RETRY times, or until successful 5718144Sralph */ 5818144Sralph for (retry = _res.retry; --retry >= 0; ) { 59*25243Skjd for (ns = 0; ns < _res.nscount; ns++) { 60*25243Skjd #ifdef DEBUG 61*25243Skjd if (_res.options & RES_DEBUG) 62*25243Skjd printf("Querying server (# %d) address = %s\n", ns+1, 63*25243Skjd inet_ntoa(_res.nsaddr_list[ns].sin_addr.s_addr)); 64*25243Skjd #endif DEBUG 6518144Sralph if (v_circuit) { 6618144Sralph /* 6718144Sralph * Use virtual circuit. 6818144Sralph */ 6918144Sralph if (s < 0) 7018144Sralph s = socket(AF_INET, SOCK_STREAM, 0); 71*25243Skjd if (connect(s, &(_res.nsaddr_list[ns]), 72*25243Skjd sizeof(struct sockaddr)) < 0) { 7324734Sbloom #ifdef DEBUG 7418144Sralph if (_res.options & RES_DEBUG) 7518144Sralph printf("connect failed %d\n", errno); 76*25243Skjd #endif DEBUG 7718144Sralph (void) close(s); 7818144Sralph s = -1; 7918144Sralph continue; 8018144Sralph } 8118144Sralph /* 8218144Sralph * Send length & message 8318144Sralph */ 8418144Sralph len = htons(buflen); 8518144Sralph if (write(s, &len, sizeof(len)) != sizeof(len) || 86*25243Skjd write(s, buf, buflen) != buflen) { 8724734Sbloom #ifdef DEBUG 8818144Sralph if (_res.options & RES_DEBUG) 8918144Sralph printf("write failed %d\n", errno); 90*25243Skjd #endif DEBUG 9118144Sralph (void) close(s); 9218144Sralph s = -1; 9318144Sralph continue; 9418144Sralph } 9518144Sralph /* 9618144Sralph * Receive length & response 9718144Sralph */ 9818144Sralph cp = answer; 9918144Sralph len = sizeof(short); 10018144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 10118144Sralph cp += n; 10218144Sralph len -= n; 10318144Sralph } 10418144Sralph if (n <= 0) { 10524734Sbloom #ifdef DEBUG 10618144Sralph if (_res.options & RES_DEBUG) 10718144Sralph printf("read failed %d\n", errno); 108*25243Skjd #endif DEBUG 10918144Sralph (void) close(s); 11018144Sralph s = -1; 11118144Sralph continue; 11218144Sralph } 11318144Sralph cp = answer; 11418144Sralph resplen = len = ntohs(*(short *)cp); 11518144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 11618144Sralph cp += n; 11718144Sralph len -= n; 11818144Sralph } 11918144Sralph if (n <= 0) { 12024734Sbloom #ifdef DEBUG 12118144Sralph if (_res.options & RES_DEBUG) 12218144Sralph printf("read failed %d\n", errno); 123*25243Skjd #endif DEBUG 12418144Sralph (void) close(s); 12518144Sralph s = -1; 12618144Sralph continue; 12718144Sralph } 12818144Sralph } else { 12918144Sralph /* 13018144Sralph * Use datagrams. 13118144Sralph */ 13218144Sralph if (s < 0) 13318144Sralph s = socket(AF_INET, SOCK_DGRAM, 0); 134*25243Skjd if (sendto(s, buf, buflen, 0, &_res.nsaddr_list[ns], 135*25243Skjd sizeof(struct sockaddr)) != buflen) { 13624734Sbloom #ifdef DEBUG 137*25243Skjd if (_res.options & RES_DEBUG) 13818144Sralph printf("sendto errno = %d\n", errno); 139*25243Skjd #endif DEBUG 14018144Sralph } 14118144Sralph /* 14218144Sralph * Wait for reply 14318144Sralph */ 144*25243Skjd timeout.tv_sec = 145*25243Skjd ((_res.retrans * _res.retry) / _res.nscount); 14618144Sralph timeout.tv_usec = 0; 14718144Sralph dsmask = 1 << s; 14818144Sralph n = select(s+1, &dsmask, 0, 0, &timeout); 14918144Sralph if (n < 0) { 15024734Sbloom #ifdef DEBUG 15118144Sralph if (_res.options & RES_DEBUG) 15218144Sralph printf("select errno = %d\n", errno); 153*25243Skjd #endif DEBUG 15418144Sralph continue; 15518144Sralph } 15618144Sralph if (n == 0) { 15718144Sralph /* 15818144Sralph * timeout 15918144Sralph */ 16024734Sbloom #ifdef DEBUG 16118144Sralph if (_res.options & RES_DEBUG) 16218144Sralph printf("timeout\n"); 163*25243Skjd #endif DEBUG 16418144Sralph continue; 16518144Sralph } 16618144Sralph if ((resplen = recvfrom(s, answer, anslen, 16718144Sralph 0, 0, 0)) <= 0) { 16824734Sbloom #ifdef DEBUG 16918144Sralph if (_res.options & RES_DEBUG) 17018144Sralph printf("recvfrom, errno=%d\n", errno); 171*25243Skjd #endif DEBUG 17218144Sralph continue; 17318144Sralph } 17418144Sralph if (id != anhp->id) { 17518144Sralph /* 17618144Sralph * response from old query, ignore it 17718144Sralph */ 17824734Sbloom #ifdef DEBUG 17918144Sralph if (_res.options & RES_DEBUG) { 18018144Sralph printf("old answer:\n"); 18118144Sralph p_query(answer); 18218144Sralph } 183*25243Skjd #endif DEBUG 18418144Sralph continue; 18518144Sralph } 18618144Sralph if (!(_res.options & RES_IGNTC) && anhp->tc) { 18718144Sralph /* 18818144Sralph * get rest of answer 18918144Sralph */ 19024734Sbloom #ifdef DEBUG 19118144Sralph if (_res.options & RES_DEBUG) 19218144Sralph printf("truncated answer\n"); 193*25243Skjd #endif DEBUG 19418144Sralph (void) close(s); 19518144Sralph s = -1; 19618144Sralph retry = _res.retry; 19718144Sralph v_circuit = 1; 19818144Sralph continue; 19918144Sralph } 20018144Sralph } 20124734Sbloom #ifdef DEBUG 20218144Sralph if (_res.options & RES_DEBUG) { 20318144Sralph printf("got answer:\n"); 20418144Sralph p_query(answer); 20518144Sralph } 206*25243Skjd #endif DEBUG 20723873Skjd (void) close(s); 20818144Sralph return (resplen); 209*25243Skjd } 21018144Sralph } 21123873Skjd (void) close(s); 21224032Skjd errno = ETIMEDOUT; 21318144Sralph return (-1); 21418144Sralph } 215