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