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