⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 res_send.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1985, 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)res_send.c	6.27 (Berkeley) 2/24/91";#endif /* LIBC_SCCS and not lint *//* * Send query to name server and wait for reply. */#if !_MINIX#include <sys/param.h>#include <sys/time.h>#include <sys/socket.h>#include <sys/uio.h>#include <netinet/in.h>#include <arpa/nameser.h>#include <stdio.h>#include <errno.h>#include <resolv.h>#include <unistd.h>#include <string.h>#else /* _MINIX */#include <sys/types.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <assert.h>#include <errno.h>#include <fcntl.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <net/hton.h>#include <net/netlib.h>#include <net/gen/in.h>#include <net/gen/inet.h>#include <net/gen/netdb.h>#include <net/gen/nameser.h>#include <net/gen/resolv.h>#include <net/gen/tcp.h>#include <net/gen/tcp_io.h>#include <net/gen/udp.h>#include <net/gen/udp_hdr.h>#include <net/gen/udp_io.h>typedef u16_t u_short;static int tcp_connect _ARGS(( ipaddr_t host, Tcpport_t port, int *terrno ));static int tcpip_writeall _ARGS(( int fd, const char *buf, size_t siz ));static int udp_connect _ARGS(( void ));static int udp_sendto _ARGS(( int fd, const char *buf, unsigned buflen,				ipaddr_t addr, Udpport_t port ));static int udp_receive _ARGS(( int fd, char *buf, unsigned buflen,				time_t timeout ));static void alarm_handler _ARGS(( int sig ));#endif /* !_MINIX */static int s = -1;	/* socket used for communications */#if !_MINIXstatic struct sockaddr no_addr;#ifndef FD_SET#define	NFDBITS		32#define	FD_SETSIZE	32#define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))#define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))#define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))#define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))#endif /* FD_SET */#endif /* _MINIX */res_send(buf, buflen, answer, anslen)	const char *buf;	int buflen;	char *answer;	int anslen;{	register int n;	int try, v_circuit, resplen, ns;	int gotsomewhere = 0, connected = 0;	int connreset = 0;#if !_MINIX	u_short id, len;#else /* _MINIX */	u16_t id, len;#endif /* !_MINIX */	char *cp;#if !_MINIX	fd_set dsmask;	struct timeval timeout;	HEADER *hp = (HEADER *) buf;	HEADER *anhp = (HEADER *) answer;	struct iovec iov[2];#else /* _MINIX */	time_t timeout;	dns_hdr_t *hp = (dns_hdr_t *) buf;	dns_hdr_t *anhp = (dns_hdr_t *) answer;#endif /* !_MINIX */	int terrno = ETIMEDOUT;	char junk[512];#ifdef DEBUG	if (_res.options & RES_DEBUG) {		printf("res_send()\n");		__p_query(buf);	}#endif /* DEBUG */	if (!(_res.options & RES_INIT))		if (res_init() == -1) {			return(-1);		}	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;#if !_MINIX	id = hp->id;#else /* _MINIX */	id = hp->dh_id;#endif /* !_MINIX */	/*	 * Send request, RETRY times, or until successful	 */	for (try = 0; try < _res.retry; try++) {	   for (ns = 0; ns < _res.nscount; ns++) {#ifdef DEBUG#if !_MINIX		if (_res.options & RES_DEBUG)			printf("Querying server (# %d) address = %s\n", ns+1,			      inet_ntoa(_res.nsaddr_list[ns].sin_addr));#else /* _MINIX */		if (_res.options & RES_DEBUG)			printf("Querying server (# %d) address = %s\n", ns+1,			      inet_ntoa(_res.nsaddr_list[ns]));#endif /* !_MINIX */#endif /* DEBUG */	usevc:		if (v_circuit) {#if !_MINIX			int truncated = 0;			/*			 * Use virtual circuit;			 * at most one attempt per server.			 */			try = _res.retry;			if (s < 0) {				s = socket(AF_INET, SOCK_STREAM, 0);				if (s < 0) {					terrno = errno;#ifdef DEBUG					if (_res.options & RES_DEBUG)					    perror("socket (vc) failed");#endif /* DEBUG */					continue;				}				if (connect(s,				    (struct sockaddr *)&(_res.nsaddr_list[ns]),				    sizeof(struct sockaddr)) < 0) {					terrno = errno;#ifdef DEBUG					if (_res.options & RES_DEBUG)					    perror("connect failed");#endif /* DEBUG */					(void) close(s);					s = -1;					continue;				}			}			/*			 * Send length & message			 */			len = htons((u_short)buflen);			iov[0].iov_base = (caddr_t)&len;			iov[0].iov_len = sizeof(len);			iov[1].iov_base = (char *)buf;			iov[1].iov_len = buflen;			if (writev(s, iov, 2) != sizeof(len) + buflen) {				terrno = errno;#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("write failed");#endif /* DEBUG */				(void) close(s);				s = -1;				continue;			}			/*			 * Receive length & response			 */			cp = answer;			len = sizeof(short);			while (len != 0 &&			    (n = read(s, (char *)cp, (int)len)) > 0) {				cp += n;				len -= n;			}			if (n <= 0) {				terrno = errno;#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("read failed");#endif /* DEBUG */				(void) close(s);				s = -1;				/*				 * A long running process might get its TCP				 * connection reset if the remote server was				 * restarted.  Requery the server instead of				 * trying a new one.  When there is only one				 * server, this means that a query might work				 * instead of failing.  We only allow one reset				 * per query to prevent looping.				 */				if (terrno == ECONNRESET && !connreset) {					connreset = 1;					ns--;				}				continue;			}			cp = answer;			if ((resplen = ntohs(*(u_short *)cp)) > anslen) {#ifdef DEBUG				if (_res.options & RES_DEBUG)					fprintf(stderr, "response truncated\n");#endif /* DEBUG */				len = anslen;				truncated = 1;			} else				len = resplen;			while (len != 0 &&			   (n = read(s, (char *)cp, (int)len)) > 0) {				cp += n;				len -= n;			}			if (n <= 0) {				terrno = errno;#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("read failed");#endif /* DEBUG */				(void) close(s);				s = -1;				continue;			}			if (truncated) {				/*				 * Flush rest of answer				 * so connection stays in synch.				 */				anhp->tc = 1;				len = resplen - anslen;				while (len != 0) {					n = (len > sizeof(junk) ?					    sizeof(junk) : len);					if ((n = read(s, junk, n)) > 0)						len -= n;					else						break;				}			}#else /* _MINIX */			int truncated = 0;			int nbytes;			/*			 * Use virtual circuit;			 * at most one attempt per server.			 */			try = _res.retry;			if (s < 0) 			{				s= tcp_connect(_res.nsaddr_list[ns],					_res.nsport_list[ns], &terrno);				if (s == -1)					continue;			}			/*			 * Send length & message			 */			len = htons((u_short)buflen);			nbytes= tcpip_writeall(s, (char *)&len, 				sizeof(len));			if (nbytes != sizeof(len))			{				terrno= errno;#ifdef DEBUG				if (_res.options & RES_DEBUG)					fprintf(stderr, "write failed: %s\n",					strerror(terrno));#endif /* DEBUG */				close(s);				s= -1;				continue;			}			nbytes= tcpip_writeall(s, buf, buflen);			if (nbytes != buflen)			{				terrno= errno;#ifdef DEBUG				if (_res.options & RES_DEBUG)					fprintf(stderr, "write failed: %s\n",					strerror(terrno));#endif /* DEBUG */				close(s);				s= -1;				continue;			}			/*			 * Receive length & response			 */			cp = answer;			len = sizeof(short);			while (len != 0)			{				n = read(s, (char *)cp, (int)len);				if (n <= 0)					break;				cp += n;				assert(len >= n);				len -= n;			}			if (len) {				terrno = errno;#ifdef DEBUG				if (_res.options & RES_DEBUG)					fprintf(stderr, "read failed: %s\n",						strerror(terrno));#endif /* DEBUG */				close(s);				s= -1;				/*				 * A long running process might get its TCP				 * connection reset if the remote server was				 * restarted.  Requery the server instead of				 * trying a new one.  When there is only one				 * server, this means that a query might work				 * instead of failing.  We only allow one reset				 * per query to prevent looping.				 */				if (terrno == ECONNRESET && !connreset) {					connreset = 1;					ns--;				}				continue;			}			cp = answer;			if ((resplen = ntohs(*(u_short *)cp)) > anslen) {#ifdef DEBUG				if (_res.options & RES_DEBUG)					fprintf(stderr, "response truncated\n");#endif /* DEBUG */				len = anslen;				truncated = 1;			} else				len = resplen;			while (len != 0)			{				n= read(s, (char *)cp, (int)len);				if (n <= 0)					break;				cp += n;				assert(len >= n);				len -= n;			}			if (len) {				terrno = errno;#ifdef DEBUG				if (_res.options & RES_DEBUG)					fprintf(stderr, "read failed: %s\n",						strerror(terrno));#endif /* DEBUG */				close(s);				s= -1;				continue;			}			if (truncated) {				/*				 * Flush rest of answer				 * so connection stays in synch.				 */				anhp->dh_flag1 |= DHF_TC;				len = resplen - anslen;				while (len != 0) {					n = (len > sizeof(junk) ?					    sizeof(junk) : len);					n = read(s, junk, n);					if (n <= 0)					{						assert(len >= n);						len -= n;					}					else						break;				}			}#endif /* _MINIX */		} else {#if !_MINIX			/*			 * Use datagrams.			 */			if (s < 0) {				s = socket(AF_INET, SOCK_DGRAM, 0);				if (s < 0) {					terrno = errno;#ifdef DEBUG					if (_res.options & RES_DEBUG)					    perror("socket (dg) failed");#endif /* DEBUG */					continue;				}			}#if	BSD >= 43			/*			 * I'm tired of answering this question, so:			 * On a 4.3BSD+ machine (client and server,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -