1*18144Sralph #ifndef lint 2*18144Sralph static char sccsid[] = "@(#)res_send.c 4.1 (Berkeley) 03/01/85"; 3*18144Sralph #endif 4*18144Sralph 5*18144Sralph /* 6*18144Sralph * Send query to name server and wait for reply. 7*18144Sralph */ 8*18144Sralph 9*18144Sralph #include <sys/types.h> 10*18144Sralph #include <sys/time.h> 11*18144Sralph #include <sys/socket.h> 12*18144Sralph #include <netinet/in.h> 13*18144Sralph #include <stdio.h> 14*18144Sralph #include <errno.h> 15*18144Sralph #include <nameser.h> 16*18144Sralph #include <resolv.h> 17*18144Sralph 18*18144Sralph extern int errno; 19*18144Sralph 20*18144Sralph sendquery(buf, buflen, answer, anslen) 21*18144Sralph char *buf; 22*18144Sralph int buflen; 23*18144Sralph char *answer; 24*18144Sralph int anslen; 25*18144Sralph { 26*18144Sralph register int n; 27*18144Sralph int s, retry, v_circuit, resplen; 28*18144Sralph u_short id, len; 29*18144Sralph char *cp; 30*18144Sralph int dsmask; 31*18144Sralph struct timeval timeout; 32*18144Sralph HEADER *hp = (HEADER *) buf; 33*18144Sralph HEADER *anhp = (HEADER *) answer; 34*18144Sralph 35*18144Sralph if (_res.options & RES_DEBUG) { 36*18144Sralph printf("sendquery()\n"); 37*18144Sralph p_query(buf); 38*18144Sralph } 39*18144Sralph if (!(_res.options & RES_INIT)) { 40*18144Sralph if (!res_init()) 41*18144Sralph return (-1); 42*18144Sralph } 43*18144Sralph s = -1; 44*18144Sralph v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 45*18144Sralph id = hp->id; 46*18144Sralph /* 47*18144Sralph * Send request, RETRY times, or until successful 48*18144Sralph */ 49*18144Sralph for (retry = _res.retry; --retry >= 0; ) { 50*18144Sralph if (v_circuit) { 51*18144Sralph /* 52*18144Sralph * Use virtual circuit. 53*18144Sralph */ 54*18144Sralph if (s < 0) 55*18144Sralph s = socket(AF_INET, SOCK_STREAM, 0); 56*18144Sralph if (connect(s, &_res.nsaddr, sizeof(_res.nsaddr)) < 0) { 57*18144Sralph if (_res.options & RES_DEBUG) 58*18144Sralph printf("connect failed %d\n", errno); 59*18144Sralph (void) close(s); 60*18144Sralph s = -1; 61*18144Sralph continue; 62*18144Sralph } 63*18144Sralph /* 64*18144Sralph * Send length & message 65*18144Sralph */ 66*18144Sralph len = htons(buflen); 67*18144Sralph if (write(s, &len, sizeof(len)) != sizeof(len) || 68*18144Sralph write(s, buf, buflen) != buflen) { 69*18144Sralph if (_res.options & RES_DEBUG) 70*18144Sralph printf("write failed %d\n", errno); 71*18144Sralph (void) close(s); 72*18144Sralph s = -1; 73*18144Sralph continue; 74*18144Sralph } 75*18144Sralph /* 76*18144Sralph * Receive length & response 77*18144Sralph */ 78*18144Sralph cp = answer; 79*18144Sralph len = sizeof(short); 80*18144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 81*18144Sralph cp += n; 82*18144Sralph len -= n; 83*18144Sralph } 84*18144Sralph if (n <= 0) { 85*18144Sralph if (_res.options & RES_DEBUG) 86*18144Sralph printf("read failed %d\n", errno); 87*18144Sralph (void) close(s); 88*18144Sralph s = -1; 89*18144Sralph continue; 90*18144Sralph } 91*18144Sralph cp = answer; 92*18144Sralph resplen = len = ntohs(*(short *)cp); 93*18144Sralph while (len > 0 && (n = read(s, cp, len)) > 0) { 94*18144Sralph cp += n; 95*18144Sralph len -= n; 96*18144Sralph } 97*18144Sralph if (n <= 0) { 98*18144Sralph if (_res.options & RES_DEBUG) 99*18144Sralph printf("read failed %d\n", errno); 100*18144Sralph (void) close(s); 101*18144Sralph s = -1; 102*18144Sralph continue; 103*18144Sralph } 104*18144Sralph } else { 105*18144Sralph /* 106*18144Sralph * Use datagrams. 107*18144Sralph */ 108*18144Sralph if (s < 0) 109*18144Sralph s = socket(AF_INET, SOCK_DGRAM, 0); 110*18144Sralph if (sendto(s, buf, buflen, 0, &_res.nsaddr, 111*18144Sralph sizeof(_res.nsaddr)) != buflen) { 112*18144Sralph if (_res.options & RES_DEBUG) 113*18144Sralph printf("sendto errno = %d\n", errno); 114*18144Sralph } 115*18144Sralph /* 116*18144Sralph * Wait for reply 117*18144Sralph */ 118*18144Sralph timeout.tv_sec = _res.retrans; 119*18144Sralph timeout.tv_usec = 0; 120*18144Sralph dsmask = 1 << s; 121*18144Sralph n = select(s+1, &dsmask, 0, 0, &timeout); 122*18144Sralph if (n < 0) { 123*18144Sralph if (_res.options & RES_DEBUG) 124*18144Sralph printf("select errno = %d\n", errno); 125*18144Sralph continue; 126*18144Sralph } 127*18144Sralph if (n == 0) { 128*18144Sralph /* 129*18144Sralph * timeout 130*18144Sralph */ 131*18144Sralph if (_res.options & RES_DEBUG) 132*18144Sralph printf("timeout\n"); 133*18144Sralph continue; 134*18144Sralph } 135*18144Sralph if ((resplen = recvfrom(s, answer, anslen, 136*18144Sralph 0, 0, 0)) <= 0) { 137*18144Sralph if (_res.options & RES_DEBUG) 138*18144Sralph printf("recvfrom, errno=%d\n", errno); 139*18144Sralph continue; 140*18144Sralph } 141*18144Sralph if (id != anhp->id) { 142*18144Sralph /* 143*18144Sralph * response from old query, ignore it 144*18144Sralph */ 145*18144Sralph if (_res.options & RES_DEBUG) { 146*18144Sralph int f; 147*18144Sralph 148*18144Sralph printf("old answer:\n"); 149*18144Sralph f = creat("ro", 0644); 150*18144Sralph write(f, answer, resplen); 151*18144Sralph close(f); 152*18144Sralph p_query(answer); 153*18144Sralph } 154*18144Sralph continue; 155*18144Sralph } 156*18144Sralph if (!(_res.options & RES_IGNTC) && anhp->tc) { 157*18144Sralph /* 158*18144Sralph * get rest of answer 159*18144Sralph */ 160*18144Sralph if (_res.options & RES_DEBUG) 161*18144Sralph printf("truncated answer\n"); 162*18144Sralph (void) close(s); 163*18144Sralph s = -1; 164*18144Sralph retry = _res.retry; 165*18144Sralph v_circuit = 1; 166*18144Sralph continue; 167*18144Sralph } 168*18144Sralph } 169*18144Sralph if (_res.options & RES_DEBUG) { 170*18144Sralph printf("got answer:\n"); 171*18144Sralph p_query(answer); 172*18144Sralph } 173*18144Sralph return (resplen); 174*18144Sralph } 175*18144Sralph return (-1); 176*18144Sralph } 177