xref: /csrg-svn/lib/libc/net/res_send.c (revision 18548)
118144Sralph #ifndef lint
2*18548Sralph static char sccsid[] = "@(#)res_send.c	4.4 (Berkeley) 04/01/85";
318144Sralph #endif
418144Sralph 
518144Sralph /*
6*18548Sralph  * Copyright (c) 1985 Regents of the University of California
7*18548Sralph  *	All Rights Reserved
8*18548Sralph  */
9*18548Sralph 
10*18548Sralph /*
1118144Sralph  * Send query to name server and wait for reply.
1218144Sralph  */
1318144Sralph 
1418144Sralph #include <sys/types.h>
1518144Sralph #include <sys/time.h>
1618144Sralph #include <sys/socket.h>
1718144Sralph #include <netinet/in.h>
1818144Sralph #include <stdio.h>
1918144Sralph #include <errno.h>
2018144Sralph #include <nameser.h>
2118144Sralph #include <resolv.h>
2218144Sralph 
2318144Sralph extern int errno;
2418144Sralph 
2518531Sralph res_send(buf, buflen, answer, anslen)
2618144Sralph 	char *buf;
2718144Sralph 	int buflen;
2818144Sralph 	char *answer;
2918144Sralph 	int anslen;
3018144Sralph {
3118144Sralph 	register int n;
3218144Sralph 	int s, retry, v_circuit, resplen;
3318144Sralph 	u_short id, len;
3418144Sralph 	char *cp;
3518144Sralph 	int dsmask;
3618144Sralph 	struct timeval timeout;
3718144Sralph 	HEADER *hp = (HEADER *) buf;
3818144Sralph 	HEADER *anhp = (HEADER *) answer;
3918144Sralph 
4018144Sralph 	if (_res.options & RES_DEBUG) {
4118531Sralph 		printf("res_send()\n");
4218144Sralph 		p_query(buf);
4318144Sralph 	}
4418531Sralph 	if (!(_res.options & RES_INIT))
4518531Sralph 		res_init();
4618144Sralph 	s = -1;
4718144Sralph 	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
4818144Sralph 	id = hp->id;
4918144Sralph 	/*
5018144Sralph 	 * Send request, RETRY times, or until successful
5118144Sralph 	 */
5218144Sralph 	for (retry = _res.retry; --retry >= 0; ) {
5318144Sralph 		if (v_circuit) {
5418144Sralph 			/*
5518144Sralph 			 * Use virtual circuit.
5618144Sralph 			 */
5718144Sralph 			if (s < 0)
5818144Sralph 				s = socket(AF_INET, SOCK_STREAM, 0);
5918144Sralph 			if (connect(s, &_res.nsaddr, sizeof(_res.nsaddr)) < 0) {
6018144Sralph 				if (_res.options & RES_DEBUG)
6118144Sralph 					printf("connect failed %d\n", errno);
6218144Sralph 				(void) close(s);
6318144Sralph 				s = -1;
6418144Sralph 				continue;
6518144Sralph 			}
6618144Sralph 			/*
6718144Sralph 			 * Send length & message
6818144Sralph 			 */
6918144Sralph 			len = htons(buflen);
7018144Sralph 			if (write(s, &len, sizeof(len)) != sizeof(len) ||
7118144Sralph 			    write(s, buf, buflen) != buflen) {
7218144Sralph 				if (_res.options & RES_DEBUG)
7318144Sralph 					printf("write failed %d\n", errno);
7418144Sralph 				(void) close(s);
7518144Sralph 				s = -1;
7618144Sralph 				continue;
7718144Sralph 			}
7818144Sralph 			/*
7918144Sralph 			 * Receive length & response
8018144Sralph 			 */
8118144Sralph 			cp = answer;
8218144Sralph 			len = sizeof(short);
8318144Sralph 			while (len > 0 && (n = read(s, cp, len)) > 0) {
8418144Sralph 				cp += n;
8518144Sralph 				len -= n;
8618144Sralph 			}
8718144Sralph 			if (n <= 0) {
8818144Sralph 				if (_res.options & RES_DEBUG)
8918144Sralph 					printf("read failed %d\n", errno);
9018144Sralph 				(void) close(s);
9118144Sralph 				s = -1;
9218144Sralph 				continue;
9318144Sralph 			}
9418144Sralph 			cp = answer;
9518144Sralph 			resplen = len = ntohs(*(short *)cp);
9618144Sralph 			while (len > 0 && (n = read(s, cp, len)) > 0) {
9718144Sralph 				cp += n;
9818144Sralph 				len -= n;
9918144Sralph 			}
10018144Sralph 			if (n <= 0) {
10118144Sralph 				if (_res.options & RES_DEBUG)
10218144Sralph 					printf("read failed %d\n", errno);
10318144Sralph 				(void) close(s);
10418144Sralph 				s = -1;
10518144Sralph 				continue;
10618144Sralph 			}
10718144Sralph 		} else {
10818144Sralph 			/*
10918144Sralph 			 * Use datagrams.
11018144Sralph 			 */
11118144Sralph 			if (s < 0)
11218144Sralph 				s = socket(AF_INET, SOCK_DGRAM, 0);
11318144Sralph 			if (sendto(s, buf, buflen, 0, &_res.nsaddr,
11418144Sralph 			    sizeof(_res.nsaddr)) != buflen) {
11518144Sralph 				if (_res.options & RES_DEBUG)
11618144Sralph 					printf("sendto errno = %d\n", errno);
11718144Sralph 			}
11818144Sralph 			/*
11918144Sralph 			 * Wait for reply
12018144Sralph 			 */
12118144Sralph 			timeout.tv_sec = _res.retrans;
12218144Sralph 			timeout.tv_usec = 0;
12318144Sralph 			dsmask = 1 << s;
12418144Sralph 			n = select(s+1, &dsmask, 0, 0, &timeout);
12518144Sralph 			if (n < 0) {
12618144Sralph 				if (_res.options & RES_DEBUG)
12718144Sralph 					printf("select errno = %d\n", errno);
12818144Sralph 				continue;
12918144Sralph 			}
13018144Sralph 			if (n == 0) {
13118144Sralph 				/*
13218144Sralph 				 * timeout
13318144Sralph 				 */
13418144Sralph 				if (_res.options & RES_DEBUG)
13518144Sralph 					printf("timeout\n");
13618144Sralph 				continue;
13718144Sralph 			}
13818144Sralph 			if ((resplen = recvfrom(s, answer, anslen,
13918144Sralph 			    0, 0, 0)) <= 0) {
14018144Sralph 				if (_res.options & RES_DEBUG)
14118144Sralph 					printf("recvfrom, errno=%d\n", errno);
14218144Sralph 				continue;
14318144Sralph 			}
14418144Sralph 			if (id != anhp->id) {
14518144Sralph 				/*
14618144Sralph 				 * response from old query, ignore it
14718144Sralph 				 */
14818144Sralph 				if (_res.options & RES_DEBUG) {
14918144Sralph 					printf("old answer:\n");
15018144Sralph 					p_query(answer);
15118144Sralph 				}
15218144Sralph 				continue;
15318144Sralph 			}
15418144Sralph 			if (!(_res.options & RES_IGNTC) && anhp->tc) {
15518144Sralph 				/*
15618144Sralph 				 * get rest of answer
15718144Sralph 				 */
15818144Sralph 				if (_res.options & RES_DEBUG)
15918144Sralph 					printf("truncated answer\n");
16018144Sralph 				(void) close(s);
16118144Sralph 				s = -1;
16218144Sralph 				retry = _res.retry;
16318144Sralph 				v_circuit = 1;
16418144Sralph 				continue;
16518144Sralph 			}
16618144Sralph 		}
16718144Sralph 		if (_res.options & RES_DEBUG) {
16818144Sralph 			printf("got answer:\n");
16918144Sralph 			p_query(answer);
17018144Sralph 		}
17118144Sralph 		return (resplen);
17218144Sralph 	}
17318144Sralph 	return (-1);
17418144Sralph }
175