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

📄 arlib.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * arlib.c (C)opyright 1993 Darren Reed. All rights reserved. * This file may not be distributed without the author's permission in any * shape or form. The author takes no responsibility for any damage or loss * of property which results from the use of this software. */#ifndef lintstatic	char	sccsid[] = "@(#)arlib.c	1.9 6/5/93 (C)opyright 1992 Darren \Reed. ASYNC DNS";#endif#include <stdio.h>#include <fcntl.h>#include <signal.h>#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include "netdb.h"#include "arpa/nameser.h"#include <resolv.h>#include "arlib.h"#include "arplib.h"extern	int	errno, h_errno;static	char	ar_hostbuf[65], ar_domainname[65];static	char	ar_dot[] = ".";static	int	ar_resfd = -1, ar_vc = 0;static	struct	reslist	*ar_last, *ar_first;/* * Statistics structure. */static	struct	resstats {	int	re_errors;	int	re_nu_look;	int	re_na_look;	int	re_replies;	int	re_requests;	int	re_resends;	int	re_sent;	int	re_timeouts;} ar_reinfo;static int do_query_name(/* struct resinfo *, char *, struct reslist * */);static int do_query_number(/* struct resinfo *, char *, struct reslist * */);static int ar_resend_query(/* struct reslist * */);/* * ar_init * * Initializes the various ARLIB internal varilables and related DNS * options for res_init(). * * Returns 0 or the socket opened for use with talking to name servers * if 0 is passed or ARES_INITSOCK is set. */int	ar_init(op)int	op;{	int	ret = 0;	if (op & ARES_INITLIST)	    {		bzero(&ar_reinfo, sizeof(ar_reinfo));		ar_first = ar_last = NULL;	    }	if (op & ARES_CALLINIT && !(_res.options & RES_INIT))	    {		ret = res_init();		(void)strcpy(ar_domainname, ar_dot);		(void)strncat(ar_domainname, _res.defdname,				sizeof(ar_domainname)-2);	    }	if (op & ARES_INITSOCK)		ret = ar_resfd = ar_open();	if (op & ARES_INITDEBG)		_res.options |= RES_DEBUG;	if (op == 0)		ret = ar_resfd;	return ret;}/* * ar_open * * Open a socket to talk to a name server with. * Check _res.options to see if we use a TCP or UDP socket. */int	ar_open(){	if (ar_resfd == -1)	    {		if (_res.options & RES_USEVC)		    {			struct	sockaddr_in	*sip;			int	i;			sip = _res.NS_ADDR_LIST;	/* was _res.nsaddr_list */			ar_vc = 1;			ar_resfd = socket(AF_INET, SOCK_STREAM, 0);			/*			 * Try each name server listed in sequence until we			 * succeed or run out.			 */			while (connect(ar_resfd, (struct sockaddr *)sip++,					sizeof(struct sockaddr)))			    {				(void)close(ar_resfd);				ar_resfd = -1;				if (i >= _res.nscount)					break;				ar_resfd = socket(AF_INET, SOCK_STREAM, 0);			    }		    }		else			ar_resfd = socket(AF_INET, SOCK_DGRAM, 0);	    }	if (ar_resfd >= 0)	    {	/* Need one of these two here - and it MUST work!! */		int flags;		if ((flags = fcntl(ar_resfd, F_GETFL, 0)) != -1)#ifdef	O_NONBLOCK			 if (fcntl(ar_resfd, F_SETFL, flags|O_NONBLOCK) == -1)#else# ifdef	O_NDELAY			 if (fcntl(ar_resfd, F_SETFL, flags|O_NDELAY) == -1)# else#  ifdef	FNDELAY			 if (fcntl(ar_resfd, F_SETFL, flags|FNDELAY) == -1)#  endif# endif#endif		    {			(void)close(ar_resfd);			ar_resfd = -1;		    }	    }	return ar_resfd;}/* * ar_close * * Closes and flags the ARLIB socket as closed. */void	ar_close(){	(void)close(ar_resfd);	ar_resfd = -1;	return;}/* * ar_add_request * * Add a new DNS query to the end of the query list. */static	int	ar_add_request(new)struct	reslist *new;{	if (!new)		return -1;	if (!ar_first)		ar_first = ar_last = new;	else {		ar_last->re_next = new;		ar_last = new;	}	new->re_next = NULL;	ar_reinfo.re_requests++;	return 0;}/* * ar_remrequest * * Remove a request from the list. This must also free any memory that has * been allocated for temporary storage of DNS results. * * Returns -1 if there are anyy problems removing the requested structure * or 0 if the remove is successful. */static	int	ar_remrequest(old)struct	reslist *old;{	register struct	reslist	*rptr, *r2ptr;	register char	**s;	if (!old)		return -1;	for (rptr = ar_first, r2ptr = NULL; rptr; rptr = rptr->re_next)	    {		if (rptr == old)			break;		r2ptr = rptr;	    }	if (!rptr)		return -1;	if (rptr == ar_first)		ar_first = ar_first->re_next;	else if (rptr == ar_last)	    {		if (ar_last = r2ptr)			ar_last->re_next = NULL;	    }	else		r2ptr->re_next = rptr->re_next;	if (!ar_first)		ar_last = ar_first;#ifdef	ARLIB_DEBUG	ar_dump_hostent("ar_remrequest:", rptr->re_he);#endif	if (rptr->re_he.h_name)		(void)free(rptr->re_he.h_name);	if (s = rptr->re_he.h_aliases)		for (; *s; s++)			(void)free(*s);	if (rptr->re_rinfo.ri_ptr)		(void)free(rptr->re_rinfo.ri_ptr);	(void)free(rptr);	return 0;}/* * ar_make_request * * Create a DNS query recorded for the request being made and place it on the * current list awaiting replies.  Initialization of the record with set * values should also be done. */static	struct	reslist	*ar_make_request(resi)register struct	resinfo	*resi;{	register struct	reslist	*rptr;	register struct resinfo *rp;	rptr = (struct reslist *)calloc(1, sizeof(struct reslist));	rp = &rptr->re_rinfo;	rptr->re_next    = NULL; /* where NULL is non-zero ;) */	rptr->re_sentat  = time(NULL);	rptr->re_retries = _res.retry;	rptr->re_sends = 1;	rptr->re_resend  = 1;	rptr->re_timeout = rptr->re_sentat + _res.retrans;	rptr->re_he.h_name = NULL;	rptr->re_he.h_addrtype   = AF_INET;	rptr->re_he.h_aliases[0] = NULL;	rp->ri_ptr = resi->ri_ptr;	rp->ri_size = resi->ri_size;	(void)ar_add_request(rptr);	return rptr;}/* * ar_timeout * * Remove queries from the list which have been there too long without * being resolved. */long	ar_timeout(now, info, size)time_t	now;char	*info;int	size;{	register struct	reslist	*rptr, *r2ptr;	register long	next = 0;	for (rptr = ar_first, r2ptr = NULL; rptr; rptr = r2ptr)	    {		r2ptr = rptr->re_next;		if (now >= rptr->re_timeout)		    {			/*			 * If the timeout for the query has been exceeded,			 * then resend the query if we still have some			 * 'retry credit' and reset the timeout. If we have			 * used it all up, then remove the request.			 */			if (--rptr->re_retries <= 0)			    {				ar_reinfo.re_timeouts++;				if (info && rptr->re_rinfo.ri_ptr)					bcopy(rptr->re_rinfo.ri_ptr, info,						MIN(rptr->re_rinfo.ri_size,						    size));				(void)ar_remrequest(rptr);				return now;			    }			else			    {				rptr->re_sends++;				rptr->re_sentat = now;				rptr->re_timeout = now + _res.retrans;				(void)ar_resend_query(rptr);			    }		    }		if (!next || rptr->re_timeout < next)			next = rptr->re_timeout;	    }	return next;}/* * ar_send_res_msg * * When sending queries to nameservers listed in the resolv.conf file, * don't send a query to every one, but increase the number sent linearly * to match the number of resends. This increase only occurs if there are * multiple nameserver entries in the resolv.conf file. * The return value is the number of messages successfully sent to  * nameservers or -1 if no successful sends. */static	int	ar_send_res_msg(msg, len, rcount)char	*msg;int	len, rcount;{	register int	i;	int	sent = 0;	if (!msg)		return -1;	rcount = (_res.nscount > rcount) ? rcount : _res.nscount;	if (_res.options & RES_PRIMARY)		rcount = 1;	if (ar_vc)	    {		ar_reinfo.re_sent++;		sent++;		if (write(ar_resfd, msg, len) == -1)		    {			int errtmp = errno;			(void)close(ar_resfd);			errno = errtmp;			ar_resfd = -1;		    }	    }	else		for (i = 0; i < rcount; i++)		    {			if (sendto(ar_resfd, msg, len, 0,				   (struct sockaddr *)&(_res.NS_ADDR_LIST[i]),				sizeof(struct sockaddr_in)) == len)			    {				ar_reinfo.re_sent++;				sent++;			    }		    }	return (sent) ? sent : -1;}/* * ar_find_id * * find a dns query record by the id (id is determined by dn_mkquery) */static	struct	reslist	*ar_find_id(id)int	id;{	register struct	reslist	*rptr;	for (rptr = ar_first; rptr; rptr = rptr->re_next)		if (rptr->re_id == id)			return rptr;	return NULL;}/* * ar_delete * * Delete a request from the waiting list if it has a data pointer which * matches the one passed. */int	ar_delete(ptr, size)char	*ptr;int	size;{	register struct	reslist	*rptr;	register struct	reslist	*r2ptr;	int	removed = 0;	for (rptr = ar_first; rptr; rptr = r2ptr)	    {		r2ptr = rptr->re_next;		if (rptr->re_rinfo.ri_ptr && ptr && size &&		    bcmp(rptr->re_rinfo.ri_ptr, ptr, size) == 0)		    {			(void)ar_remrequest(rptr);			removed++;		    }	    }	return removed;}/* * ar_query_name * * generate a query based on class, type and name. */static	int	ar_query_name(name, class, type, rptr)char	*name;int	class, type;struct	reslist	*rptr;{	static	char buf[MAXPACKET];	int	r,s,a;	HEADER	*hptr;	bzero(buf, sizeof(buf));	r = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,			buf, sizeof(buf));	if (r <= 0)	    {		h_errno = NO_RECOVERY;		return r;	    }	hptr = (HEADER *)buf;	rptr->re_id = ntohs(hptr->id);	s = ar_send_res_msg(buf, r, rptr->re_sends);	if (s == -1)	    {		h_errno = TRY_AGAIN;		return -1;	    }	else		rptr->re_sent += s;	return 0;}/* * ar_gethostbyname * * Replacement library function call to gethostbyname().  This one, however, * doesn't return the record being looked up but just places the query in the * queue to await answers. */int	ar_gethostbyname(name, info, size)char	*name;char	*info;int	size;{	char	host[65];	struct	resinfo	resi;	register struct resinfo *rp = &resi;	if (size && info)	    {		rp->ri_ptr = (char *)malloc(size);		bcopy(info, rp->ri_ptr, size);		rp->ri_size = size;	    }	else		bzero((char *)rp, sizeof(resi));	ar_reinfo.re_na_look++;	(void)strncpy(host, name, 64);	host[64] = '\0';	return (do_query_name(rp, host, NULL));}static	int	do_query_name(resi, name, rptr)struct	resinfo	*resi;char	*name;register struct	reslist	*rptr;{	char	hname[65];	int	len;	len = strlen((char *)strncpy(hname, name, sizeof(hname)-1));	if (rptr && (hname[len-1] != '.'))	    {		(void)strncat(hname, ar_dot, sizeof(hname)-len-1);		/*		 * NOTE: The logical relationship between DNSRCH and DEFNAMES		 * is implies. ie no DEFNAES, no DNSRCH.		 */		if (_res.options & (RES_DEFNAMES|RES_DNSRCH) ==		    (RES_DEFNAMES|RES_DNSRCH))		    {			if (_res.dnsrch[rptr->re_srch])				(void)strncat(hname, _res.dnsrch[rptr->re_srch],					sizeof(hname) - ++len -1);		    }		else if (_res.options & RES_DEFNAMES)			(void)strncat(hname, ar_domainname, sizeof(hname) - len -1);	    }	/*	 * Store the name passed as the one to lookup and generate other host	 * names to pass onto the nameserver(s) for lookups.	 */	if (!rptr)	    {		rptr = ar_make_request(resi);		rptr->re_type = T_A;		(void)strncpy(rptr->re_name, name, sizeof(rptr->re_name)-1);	    }

⌨️ 快捷键说明

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