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

📄 res_send.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef lintstatic	char	*sccsid = "@(#)res_send.c	4.3	(ULTRIX)	2/14/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1987 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Copyright (c) 1985 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. *static char sccsid[] = "@(#)res_send.c	6.18 (Berkeley) 11/7/87"; *//* * Modification History: * * 11-Aug-89	sue *	Changed buffer sizes from PACKETSZ to HES_BUFMAX.  Moved  *	assignment of cred[ns].v_circuit into the retry if. * *//* * Send query to name server and wait for reply. */#include <sys/param.h>#include <sys/time.h>#include <sys/socket.h>#include <sys/uio.h>#include <netinet/in.h>#include <stdio.h>#include <errno.h>#include <arpa/nameser.h>#include <resolv.h>#include <hesiod.h>#ifdef AUTHEN#include <krb.h>#endif AUTHEN#if defined(lint) && !defined(DEBUG)#define DEBUG#endifextern int errno;cred_st cred[MAXNS];  #ifdef AUTHENstruct sockaddr_in authen_from;int fromlen = sizeof(struct sockaddr_in);#endif AUTHENstatic int sd = -1;	/* socket used for virtual circuit communications */static int sv = -1;	/* socket used for datagram communications */static 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#define KEEPOPEN (RES_USEVC|RES_STAYOPEN)res_send(buf, buflen, answer, anslen)	char *buf;	int buflen;	char *answer;	int anslen;{	register int n;	int retry, v_circuit, resplen, ns;	int gotsomewhere = 0, connected = 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];	char *sendbuf;	int sendbuflen;#ifdef AUTHEN	char *qb;        char dname[MAXDNAME];	int msgtype;	int msgclass;	int authtype;	int authversion;	CREDENTIALS krbcred_st;	char *dnptr;	char *krbnameptr;	extern char *res_dotname_head();#endif AUTHEN#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 > HES_BUFMAX;	id = hp->id;	/*	 * Send request, RETRY times, or until successful	 */	for (retry = _res.retry; retry > 0; retry--) {	   for (ns = 0; ns < _res.nscount; ns++) {#ifdef AUTHEN	        if (hp->opcode == AQUERY && retry == _res.retry) {			bcopy(buf, cred[ns].buf, buflen);			qb = cred[ns].buf + sizeof(HEADER);			if ((n = dn_expand((char *)cred[ns].buf,					   cred[ns].buf + buflen,					   qb, dname, MAXDNAME)) < 0) {				return (-1);			}			dnptr = dname;			res_dotname_rmhead(&dnptr);			qb += n;			msgtype = _getshort(qb);			qb += sizeof(u_short);			msgclass = _getshort(qb);			qb += sizeof(u_short);			authtype = _getshort(qb);			qb += sizeof(u_short);			authversion = _getshort(qb);			qb += sizeof(u_short);						krbnameptr = res_dotname_head((_res.ns_list + ns)->dname);			if (authtype == AUTH_KRB && authversion == ONE) {				if((cred[ns].len_ar = res_mkl_krbcred(ONE,						     "named",						     krbnameptr,						     &krbcred_st,						     cred[ns].buf,						     cred[ns].buf + buflen,						     HES_BUFMAX - buflen,						     dnptr, msgtype, msgclass))				   < RET_OK) {#ifdef DEBUG					if (_res.options & RES_DEBUG)						perror("bad krb cred call %d",						       cred[ns].len_ar);#endif DEBUG										free(krbnameptr);					return(-1);				}				free(krbnameptr);		        }			else if(authtype == AUTH_NONE) {				cred[ns].len_ar = 0;			} else {				/* authtype != AUTH_NONE */#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("bad auth type");#endif DEBUG				return(-1);			}			sendbuf = cred[ns].buf;			sendbuflen = cred[ns].len_ar + buflen;		} else {#endif AUTHEN		        if (retry == _res.retry) {				cred[ns].v_circuit = (_res.options & RES_USEVC) || (sendbuflen) > HES_BUFMAX;		                cred[ns].len_ar = 0;		                sendbuf = buf;		                sendbuflen = buflen;			      }#ifdef AUTHEN		      }#endif AUTHEN#ifdef DEBUG		if (_res.options & RES_DEBUG)			printf("Querying server (# %d) address = %s\n", ns+1,			      inet_ntoa(_res.ns_list[ns].addr.sin_addr));#endif DEBUG		if (cred[ns].v_circuit) {			int truncated = 0;			/*			 * Use virtual circuit.			 */			if (sv < 0) {				sv = socket(AF_INET, SOCK_STREAM, 0);				if (sv < 0) {					terrno = errno;#ifdef DEBUG					if (_res.options & RES_DEBUG)					    perror("socket failed");#endif DEBUG					continue;				}				if (connect(sv, &(_res.ns_list[ns].addr),				   sizeof(struct sockaddr)) < 0) {					terrno = errno;#ifdef DEBUG					if (_res.options & RES_DEBUG)					    perror("connect failed");#endif DEBUG					(void) close(sv);					sv = -1;					continue;				}			}			/*			 * Send length & message			 */			len = htons((u_short)sendbuflen);			iov[0].iov_base = (caddr_t)&len;			iov[0].iov_len = sizeof(len);			iov[1].iov_base = sendbuf;			iov[1].iov_len = sendbuflen;			if (writev(sv, iov, 2) != sizeof(len) + sendbuflen) {				terrno = errno;#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("write failed");#endif DEBUG				(void) close(sv);				sv = -1;				continue;			}			/*			 * Receive length & response			 */			cp = answer;			len = sizeof(short);			while (len != 0 &&			    (n = read(sv, (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(sv);				sv = -1;				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(sv, (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(sv);				sv = -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(sv, junk, n)) > 0)						len -= n;					else						break;				}			}#ifdef AUTHEN			authen_from = _res.ns_list[ns].addr;#endif AUTHEN		} else {			/*			 * Use datagrams.			 */			if (sd < 0)				sd = socket(AF_INET, SOCK_DGRAM, 0);#if	BSD >= 43			if (_res.nscount == 1 || retry == _res.retry) {				/*				 * Don't use connect if we might				 * still receive a response				 * from another server.				 */				if (connected == 0) {					if (connect(sd, &_res.ns_list[ns].addr,					    sizeof(struct sockaddr)) < 0) {#ifdef DEBUG						if (_res.options & RES_DEBUG)							perror("connect");#endif DEBUG						continue;					}					connected = 1;				}				if (send(sd, sendbuf, sendbuflen, 0)				    != sendbuflen) {#ifdef DEBUG					if (_res.options & RES_DEBUG)						perror("send");#endif DEBUG					continue;				}			} else#endif BSD				if (sendto(sd, sendbuf, sendbuflen, 0,					   &_res.ns_list[ns].addr,					   sizeof(struct sockaddr))				    != sendbuflen) {#ifdef DEBUG					if (_res.options & RES_DEBUG)						perror("sendto");#endif DEBUG					continue;				}			/*			 * Wait for reply			 */			timeout.tv_sec = (_res.retrans << (_res.retry - retry))				/ _res.nscount;			if (timeout.tv_sec <= 0)				timeout.tv_sec = 1;			timeout.tv_usec = 0;wait:			FD_ZERO(&dsmask);			FD_SET(sd, &dsmask);			n = select(sd+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				/*				 * Disconnect if we want to listen				 * for responses from more than one server.				 */				if (_res.nscount > 1 && connected) {					(void) connect(sd, &no_addr,					    sizeof(no_addr));					connected = 0;				}				gotsomewhere = 1;				continue;			}#ifdef AUTHEN			if ((resplen = recvfrom(sd, answer, anslen, 0,						&authen_from, &fromlen)) <= 0) {#else /* AUTHEN */			if ((resplen = recv(sd, answer, anslen, 0)) <= 0) {#endif AUTHEN#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 DEBUG				if (_res.options & RES_DEBUG) {					printf("old answer:\n");					p_query(answer);				}#endif DEBUG				goto wait;			}			if (!(_res.options & RES_IGNTC) && anhp->tc) {				/*				 * get rest of answer				 */#ifdef DEBUG				if (_res.options & RES_DEBUG)					printf("truncated answer\n");#endif DEBUG				(void) close(sd);				sd = -1;				/*				 * retry decremented on continue				 * to desired starting value				 */				retry = _res.retry + 1;				cred[ns].v_circuit = 1;				ns--;				continue;			}		}#ifdef DEBUG		if (_res.options & RES_DEBUG) {			printf("got answer:\n");			p_query(answer);		}#endif DEBUG		errno = 0;		/*		 * We are going to 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 ((_res.options & KEEPOPEN) == KEEPOPEN && ns == 0) {			return (resplen);		} else {		        if (sv >= 0) {			        (void) close(sv);			        sv = -1;		        }			if (sd >= 0) {			        (void) close(sd);			        sd = -1;			}		  return (resplen);		}	   }	}	if (sv >= 0) {		(void) close(sv);		sv = -1;	}	if (sd >= 0) {		(void) close(sd);		sd = -1;	}	if (v_circuit == 0)		if (gotsomewhere == 0)			errno = ECONNREFUSED;		else			errno = ETIMEDOUT;	else		errno = terrno;	return (-1);}/* * This routine is for closing the socket if a virtual circuit is used and * the program wants to close it.  This provides support for endhostent() * which expects to close the socket. * * This routine is not expected to be user visible. */_res_close(){	if (sd != -1) {		(void) close(sd);		sd = -1;	}	if (sv != -1) {		(void) close(sv);		sv = -1;	}}

⌨️ 快捷键说明

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