xref: /csrg-svn/lib/libc/net/res_send.c (revision 18144)
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