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

📄 res_send.c

📁 vxworks source code, used for develop vxworks system.
💻 C
字号:
/* res_send.c - *//* Copyright 1984-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * 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. *//*modification history--------------------01c,05nov01,vvv fixed compilation warning; cleaned up use of register01b,04sep01,vvv fixed to correctly query multiple servers (SPR #67238);                fixed compilation warnings01a,13dec96,jag Cleaned up.  Added resolv prefix. Man pages can be found in                files resolvLib.c.  Added code for pdnsDebugFunc.*//* * Send query to name server and wait for reply. */#include <sys/times.h>#include <resolvLib.h>#include <sockLib.h>#include <net/uio.h>#include <unistd.h>#include <string.h>#include "ioLib.h"extern FUNCPTR pdnsDebugFunc;#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)))#endifint resolvSend(buf, buflen, answer, anslen)	const char *buf;	int buflen;	char *answer;	int anslen;{	int n = 0;	int try, v_circuit, resplen, ns;	int gotsomewhere = 0, connected = 0;	int connreset = 0;	u_short id, len;	char *cp;	fd_set dsmask;	struct timeval timeout;	HEADER *hp = (HEADER *) buf;	HEADER *anhp = (HEADER *) answer;	struct iovec iov[2];	int terrno = ETIMEDOUT;	char junk[512];	int start;      /* pointer to server we start querying with */        int s = -1;	/* socket used for communications */        struct sockaddr no_addr;        bzero ((char*) &no_addr, sizeof no_addr);#ifdef ORG_RESOLVER#ifdef DEBUG	if (_res.options & RES_DEBUG) {		printf("resSend()\n");		__p_query(buf);	}#endif /* DEBUG */#else	if (pdnsDebugFunc != (FUNCPTR) NULL)	    {	    printf("resolvSend()\n");	    (*pdnsDebugFunc)(buf);	    }#endif /* ORG_RESOLVER */#ifdef ORG_RESOLVER	/* Unecessary test under VxWorks */	if (!(_res.options & RES_INIT))		if (res_init() == -1) {			return(ERROR);		}#endif /* ORG_RESOLVER */	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;	id = hp->id;	/*	 * Send request, RETRY times, or until successful	 */	for (try = 0; try < _res.retry; try++) {	   start = MAXDNSLUS;	   for (ns = 0; ns < _res.nscount; ns++) {		/*		 * Only query servers marked active or appearing after		 * a server marked as active. This prevents this loop		 * from rescanning the entire array every time resolvSend 	         * is called		 */		if ((_res.lookups [ns] != 'a') && (ns < start))		    continue;		if (ns > start)		    _res.lookups [ns] = 'd';  /* mark as 'done' */		start = ns;#ifdef DEBUG		if (_res.options & RES_DEBUG)			printf("Querying server (# %d) address = %s\n", ns+1,			      inet_ntoa(_res.nsaddr_list[ns].sin_addr));#endif /* DEBUG */	usevc:		if (v_circuit) {			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 {			/*			 * 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,			 * actually), sending to a nameserver datagram			 * port with no nameserver will cause an			 * ICMP port unreachable message to be returned.			 * If our datagram socket is "connected" to the			 * server, we get an ECONNREFUSED error on the next			 * socket operation, and select returns if the			 * error message is received.  We can thus detect			 * the absence of a nameserver without timing out.			 * If we have sent queries to at least two servers,			 * however, we don't want to remain connected,			 * as we wish to receive answers from the first			 * server to respond.			 */			if (_res.nscount == 1 || (try == 0 && ns == 0)) {				/*				 * Don't use connect if we might				 * still receive a response				 * from another server.				 */				if (connected == 0) {			if (connect(s, (struct sockaddr *)&_res.nsaddr_list[ns],					    sizeof(struct sockaddr)) < 0) {#ifdef DEBUG						if (_res.options & RES_DEBUG)							perror("connect");#endif /* DEBUG */						continue;					}					connected = 1;				}				if (send(s, buf, buflen, 0) != buflen) {#ifdef DEBUG					if (_res.options & RES_DEBUG)						perror("send");#endif /* DEBUG */					continue;				}			} else {				/*				 * Disconnect if we want to listen				 * for responses from more than one server.				 */				if (connected) {					(void) connect(s, &no_addr,					    sizeof(no_addr));					connected = 0;				}#endif /* BSD */				if (sendto(s, (char *) buf, buflen, 0,				    (struct sockaddr *)&_res.nsaddr_list[ns],				    sizeof(struct sockaddr)) != buflen) {#ifdef DEBUG					if (_res.options & RES_DEBUG)						perror("sendto");#endif /* DEBUG */					continue;				}#if	BSD >= 43			}#endif			/*			 * Wait for reply			 */			timeout.tv_sec = (_res.retrans << try);			if (try > 0)				timeout.tv_sec /= _res.nscount;			if (timeout.tv_sec <= 0)				timeout.tv_sec = 1;			timeout.tv_usec = 0;wait:			FD_ZERO(&dsmask);			FD_SET(s, &dsmask);			n = select(s+1, &dsmask, (fd_set *)NULL,				(fd_set *)NULL, &timeout);			if (n < 0) {#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("select");#endif /* DEBUG */				continue;			}			if (n == 0) {				/*				 * timeout				 */#ifdef DEBUG				if (_res.options & RES_DEBUG)					printf("timeout\n");#endif /* DEBUG */#if BSD >= 43				gotsomewhere = 1;#endif				continue;			}			if ((resplen = recv(s, answer, anslen, 0)) <= 0) {#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("recvfrom");#endif /* DEBUG */				continue;			}			gotsomewhere = 1;			if (id != anhp->id) {				/*				 * response from old query, ignore it				 */#ifdef ORG_RESOLVER#ifdef DEBUG				if (_res.options & RES_DEBUG) {					printf("old answer:\n");					__p_query(answer);				}#endif /* DEBUG */#else				if (pdnsDebugFunc != (FUNCPTR) NULL)				    {				    printf("old answer:\n");				    (*pdnsDebugFunc)(answer);				    }#endif /* ORG_RESOLVER */				goto wait;			}			if (!(_res.options & RES_IGNTC) && anhp->tc) {				/*				 * get rest of answer;				 * use TCP with same server.				 */#ifdef DEBUG				if (_res.options & RES_DEBUG)					printf("truncated answer\n");#endif /* DEBUG */				(void) close(s);				s = -1;				v_circuit = 1;				goto usevc;			}		}#ifdef ORG_RESOLVER#ifdef DEBUG		if (_res.options & RES_DEBUG) {			printf("got answer:\n");			__p_query(answer);		}#endif /* DEBUG */#else		if (pdnsDebugFunc != (FUNCPTR) NULL)		    {		    printf("got answer:\n");		    (*pdnsDebugFunc)(answer);		    }#endif /* ORG_RESOLVER */		/*		 * If using virtual circuits, we assume that the first server		 * is preferred * over the rest (i.e. it is on the local		 * machine) and only keep that one open.		 * If we have temporarily opened a virtual circuit,		 * or if we haven't been asked to keep a socket open,		 * close the socket.		 */		if ((v_circuit &&		    ((_res.options & RES_USEVC) == 0 || ns != 0)) ||		    (_res.options & RES_STAYOPEN) == 0) {			(void) close(s);			s = -1;		}		return (resplen);	   }	}	if (s >= 0) {		(void) close(s);		s = -1;	}	if (v_circuit == 0)		if (gotsomewhere == 0)			errno = ECONNREFUSED;	/* no nameservers found */		else			errno = ETIMEDOUT;	/* no answer obtained */	else		errno = terrno;	return (ERROR);}

⌨️ 快捷键说明

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