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

📄 ntp_intres.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ripped off from ../ntpres/ntpres.c by Greg Troxel 4/2/92 * routine callable from ntpd, rather than separate program * also, key info passed in via a global, so no key file needed. *//* * ntpres - process configuration entries which require use of the resolver * * This is meant to be run by ntpd on the fly.  It is not guaranteed * to work properly if run by hand.  This is actually a quick hack to * stave off violence from people who hate using numbers in the * configuration file (at least I hope the rest of the daemon is * better than this).  Also might provide some ideas about how one * might go about autoconfiguring an NTP distribution network. * */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include "ntp_machine.h"#include "ntpd.h"#include "ntp_io.h"#include "ntp_request.h"#include "ntp_stdlib.h"#include "ntp_syslog.h"#include <stdio.h>#include <ctype.h>#include <signal.h>/**/#include <netinet/in.h>#include <arpa/inet.h>/**/#ifdef HAVE_SYS_PARAM_H# include <sys/param.h>		/* MAXHOSTNAMELEN (often) */#endif#include <isc/net.h>#include <isc/result.h>#define	STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)/* * Each item we are to resolve and configure gets one of these * structures defined for it. */struct conf_entry {	struct conf_entry *ce_next;	char *ce_name;			/* name we are trying to resolve */	struct conf_peer ce_config;	/* configuration info for peer */	struct sockaddr_storage peer_store; /* address info for both fams */};#define	ce_peeraddr	ce_config.peeraddr#define	ce_peeraddr6	ce_config.peeraddr6#define	ce_hmode	ce_config.hmode#define	ce_version	ce_config.version#define ce_minpoll	ce_config.minpoll#define ce_maxpoll	ce_config.maxpoll#define	ce_flags	ce_config.flags#define ce_ttl		ce_config.ttl#define	ce_keyid	ce_config.keyid#define ce_keystr	ce_config.keystr/* * confentries is a pointer to the list of configuration entries * we have left to do. */static struct conf_entry *confentries = NULL;/* * We take an interrupt every thirty seconds, at which time we decrement * config_timer and resolve_timer.  The former is set to 2, so we retry * unsucessful reconfigurations every minute.  The latter is set to * an exponentially increasing value which starts at 2 and increases to * 32.  When this expires we retry failed name resolutions. * * We sleep SLEEPTIME seconds before doing anything, to give the server * time to arrange itself. */#define	MINRESOLVE	2#define	MAXRESOLVE	32#define	CONFIG_TIME	2#define	ALARM_TIME	30#define	SLEEPTIME	2static	volatile int config_timer = 0;static	volatile int resolve_timer = 0;static	int resolve_value;	/* next value of resolve timer *//* * Big hack attack */#define	LOCALHOST	0x7f000001	/* 127.0.0.1, in hex, of course */#define	SKEWTIME	0x08000000	/* 0.03125 seconds as a l_fp fraction *//* * Select time out.  Set to 2 seconds.  The server is on the local machine, * after all. */#define	TIMEOUT_SEC	2#define	TIMEOUT_USEC	0/* * Input processing.  The data on each line in the configuration file * is supposed to consist of entries in the following order */#define	TOK_HOSTNAME	0#define	TOK_HMODE	1#define	TOK_VERSION	2#define TOK_MINPOLL	3#define TOK_MAXPOLL	4#define	TOK_FLAGS	5#define TOK_TTL		6#define	TOK_KEYID	7#define TOK_KEYSTR	8#define	NUMTOK		9#define	MAXLINESIZE	512/* * File descriptor for ntp request code. */static	SOCKET sockfd = INVALID_SOCKET;	/* NT uses SOCKET *//* stuff to be filled in by caller */keyid_t req_keyid;	/* request keyid */char *req_file;		/* name of the file with configuration info *//* end stuff to be filled in */static	RETSIGTYPE bong		P((int));static	void	checkparent	P((void));static	void	removeentry	P((struct conf_entry *));static	void	addentry	P((char *, int, int, int, int, u_int,				   int, keyid_t, char *));static	int	findhostaddr	P((struct conf_entry *));static	void	openntp		P((void));static	int	request		P((struct conf_peer *));static	char *	nexttoken	P((char **));static	void	readconf	P((FILE *, char *));static	void	doconfigure	P((int));struct ntp_res_t_pkt {		/* Tagged packet: */	void *tag;		/* For the caller */	u_int32 paddr;		/* IP to look up, or 0 */	char name[MAXHOSTNAMELEN]; /* Name to look up (if 1st byte is not 0) */};struct ntp_res_c_pkt {		/* Control packet: */	char name[MAXHOSTNAMELEN];	u_int32 paddr;	int mode;	int version;	int minpoll;	int maxpoll;	u_int flags;	int ttl;	keyid_t keyid;	u_char keystr[MAXFILENAME];};static void	resolver_exit P((int));/* * Call here instead of just exiting */static void resolver_exit (int code){#ifdef SYS_WINNT	ExitThread (code);	/* Just to kill the thread not the process */#else	exit (code);		/* fill the forked process */#endif}/* * ntp_res_recv: Process an answer from the resolver */voidntp_res_recv(void){	/*	  We have data ready on our descriptor.	  It may be an EOF, meaning the resolver process went away.	  Otherwise, it will be an "answer".	*/}/* * ntp_intres needs; * *	req_key(???), req_keyid, req_file valid *	syslog still open */voidntp_intres(void){	FILE *in;#ifdef HAVE_SIGSUSPEND	sigset_t set;	sigemptyset(&set);#endif /* HAVE_SIGSUSPEND */#ifdef DEBUG	if (debug > 1) {		msyslog(LOG_INFO, "NTP_INTRES running");	}#endif	/* check out auth stuff */	if (sys_authenticate) {		if (!authistrusted(req_keyid)) {			msyslog(LOG_ERR, "invalid request keyid %08x",			    req_keyid );			resolver_exit(1);		}	}	/*	 * Read the configuration info	 * {this is bogus, since we are forked, but it is easier	 * to keep this code - gdt}	 */	if ((in = fopen(req_file, "r")) == NULL) {		msyslog(LOG_ERR, "can't open configuration file %s: %m",			req_file);		resolver_exit(1);	}	readconf(in, req_file);	(void) fclose(in);	if (!debug )		(void) unlink(req_file);	/*	 * Sleep a little to make sure the server is completely up	 */	sleep(SLEEPTIME);	/*	 * Make a first cut at resolving the bunch	 */	doconfigure(1);	if (confentries == NULL) {		resolver_exit(0);	}		/*	 * Here we've got some problem children.  Set up the timer	 * and wait for it.	 */	resolve_value = resolve_timer = MINRESOLVE;	config_timer = CONFIG_TIME;#ifndef SYS_WINNT	(void) signal_no_reset(SIGALRM, bong);	alarm(ALARM_TIME);#endif /* SYS_WINNT */	for (;;) {		if (confentries == NULL)		    resolver_exit(0);		checkparent();		if (resolve_timer == 0) {			if (resolve_value < MAXRESOLVE)			    resolve_value <<= 1;			resolve_timer = resolve_value;#ifdef DEBUG			if (debug > 2)				msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);#endif			config_timer = CONFIG_TIME;			doconfigure(1);			continue;		} else if (config_timer == 0) {			config_timer = CONFIG_TIME;#ifdef DEBUG			if (debug > 2)				msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);#endif			doconfigure(0);			continue; 		}#ifndef SYS_WINNT		/*		 * There is a race in here.  Is okay, though, since		 * all it does is delay things by 30 seconds.		 */# ifdef HAVE_SIGSUSPEND		sigsuspend(&set);# else		sigpause(0);# endif /* HAVE_SIGSUSPEND */#else		if (config_timer > 0)		    config_timer--;		if (resolve_timer > 0)		    resolve_timer--;		sleep(ALARM_TIME);#endif /* SYS_WINNT */	}}#ifndef SYS_WINNT/* * bong - service and reschedule an alarm() interrupt */static RETSIGTYPEbong(	int sig	){	if (config_timer > 0)	    config_timer--;	if (resolve_timer > 0)	    resolve_timer--;	alarm(ALARM_TIME);}#endif /* SYS_WINNT *//* * checkparent - see if our parent process is still running * * No need to worry in the Windows NT environment whether the * main thread is still running, because if it goes * down it takes the whole process down with it (in * which case we won't be running this thread either) * Turn function into NOP; */static voidcheckparent(void){#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS)	/*	 * If our parent (the server) has died we will have been	 * inherited by init.  If so, exit.	 */	if (getppid() == 1) {		msyslog(LOG_INFO, "parent died before we finished, exiting");		resolver_exit(0);	}#endif /* SYS_WINNT && SYS_VXWORKS*/}/* * removeentry - we are done with an entry, remove it from the list */static voidremoveentry(	struct conf_entry *entry	){	register struct conf_entry *ce;	ce = confentries;	if (ce == entry) {		confentries = ce->ce_next;		return;	}	while (ce != NULL) {		if (ce->ce_next == entry) {			ce->ce_next = entry->ce_next;			return;		}		ce = ce->ce_next;	}}/* * addentry - add an entry to the configuration list */static voidaddentry(	char *name,	int mode,	int version,	int minpoll,	int maxpoll,	u_int flags,	int ttl,	keyid_t keyid,	char *keystr	){	register char *cp;	register struct conf_entry *ce;	unsigned int len;#ifdef DEBUG	if (debug > 1)		msyslog(LOG_INFO, 		    "intres: <%s> %d %d %d %d %x %d %x %s\n", name,		    mode, version, minpoll, maxpoll, flags, ttl, keyid,		    keystr);#endif	len = strlen(name) + 1;	cp = (char *)emalloc(len);	memmove(cp, name, len);	ce = (struct conf_entry *)emalloc(sizeof(struct conf_entry));	ce->ce_name = cp;	ce->ce_peeraddr = 0;#ifdef ISC_PLATFORM_HAVEIPV6	ce->ce_peeraddr6 = in6addr_any;#endif	ANYSOCK(&ce->peer_store);	ce->ce_hmode = (u_char)mode;	ce->ce_version = (u_char)version;	ce->ce_minpoll = (u_char)minpoll;	ce->ce_maxpoll = (u_char)maxpoll;	ce->ce_flags = (u_char)flags;	ce->ce_ttl = (u_char)ttl;	ce->ce_keyid = keyid;	strncpy((char *)ce->ce_keystr, keystr, MAXFILENAME);	ce->ce_next = NULL;	if (confentries == NULL) {		confentries = ce;	} else {		register struct conf_entry *cep;		for (cep = confentries; cep->ce_next != NULL;		     cep = cep->ce_next)		    /* nothing */;		cep->ce_next = ce;	}}/* * findhostaddr - resolve a host name into an address (Or vice-versa) * * Given one of {ce_peeraddr,ce_name}, find the other one. * It returns 1 for "success" and 0 for an uncorrectable failure. * Note that "success" includes try again errors.  You can tell that you *  got a "try again" since {ce_peeraddr,ce_name} will still be zero. */static intfindhostaddr(	struct conf_entry *entry	){	struct addrinfo *addr;	struct addrinfo hints;	int error;	checkparent();		/* make sure our guy is still running */	if (entry->ce_name != NULL && !SOCKNUL(&entry->peer_store)) {		/* HMS: Squawk? */		msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined...");		return 1;	}        if (entry->ce_name == NULL && SOCKNUL(&entry->peer_store)) {		msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");		return 0;	}	if (entry->ce_name) {#ifdef DEBUG		if (debug > 2)			msyslog(LOG_INFO, "findhostaddr: Resolving <%s>",				entry->ce_name);#endif /* DEBUG */		memset(&hints, 0, sizeof(hints));		hints.ai_family = AF_UNSPEC;		/*		 * If the IPv6 stack is not available look only for IPv4 addresses		 */		if (isc_net_probeipv6() != ISC_R_SUCCESS)			hints.ai_family = AF_INET;		error = getaddrinfo(entry->ce_name, NULL, &hints, &addr);		if (error == 0) {			entry->peer_store = *((struct sockaddr_storage*)(addr->ai_addr));			if (entry->peer_store.ss_family == AF_INET) {				entry->ce_peeraddr =				    GET_INADDR(entry->peer_store);				entry->ce_config.v6_flag = 0;			} else {				entry->ce_peeraddr6 =				    GET_INADDR6(entry->peer_store);				entry->ce_config.v6_flag = 1;			}		}	} else {#ifdef DEBUG		if (debug > 2)			msyslog(LOG_INFO, "findhostaddr: Resolving %s>",				stoa(&entry->peer_store));#endif		entry->ce_name = emalloc(MAXHOSTNAMELEN);		error = getnameinfo((const struct sockaddr *)&entry->peer_store,				   SOCKLEN(&entry->peer_store),				   (char *)&entry->ce_name, MAXHOSTNAMELEN,				   NULL, 0, 0);	}	if (error != 0) {		/*		 * If the resolver is in use, see if the failure is		 * temporary.  If so, return success.		 */		if (error == EAI_AGAIN)		    return (1);		return (0);	}	if (entry->ce_name) {#ifdef DEBUG		if (debug > 2)			msyslog(LOG_INFO, "findhostaddr: name resolved.");#endif#ifdef DEBUG		if (debug > 2)			msyslog(LOG_INFO, "findhostaddr: address resolved.");#endif	}		   	return (1);}/* * openntp - open a socket to the ntp server */static void

⌨️ 快捷键说明

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