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