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

📄 ntpdate.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * Whew!  What we should have by now is 0 to 5 candidates for	 * the job of syncing us.  If we have none, we're out of luck.	 * If we have one, he's a winner.  If we have more, do falseticker	 * detection.	 */	if (nlist == 0)		sys_server = 0;	else if (nlist == 1) {		sys_server = server_list[0];	} else {		/*		 * Re-sort by stratum, bdelay estimate quality and		 * server.delay.		 */		for (i = 0; i < nlist-1; i++)			for (j = i+1; j < nlist; j++) {				if (server_list[i]->stratum				< server_list[j]->stratum)				break;	/* already sorted by stratum */				if (server_list[i]->delay				< server_list[j]->delay)				continue;				server = server_list[i];				server_list[i] = server_list[j];				server_list[j] = server;			}		/*		 * Calculate the fixed part of the dispersion limit		 */		local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION))			+ NTP_MAXSKW;		/*		 * Now drop samples until we're down to one.		 */		while (nlist > 1) {			for (n = 0; n < nlist; n++) {				server_badness[n] = 0;				for (j = 0; j < nlist; j++) {					if (j == n) /* with self? */						continue;					d = server_list[j]->soffset						- server_list[n]->soffset;					if (d < 0)	/* absolute value */						d = -d;					/*					 * XXX This code *knows* that					 * NTP_SELECT is 3/4					 */					for (i = 0; i < j; i++)						d = (d>>1) + (d>>2);					server_badness[n] += d;				}			}			/*			 * We now have an array of nlist badness			 * coefficients.	Find the badest.  Find			 * the minimum precision while we're at			 * it.			 */			i = 0;			n = server_list[0]->precision;;			for (j = 1; j < nlist; j++) {				if (server_badness[j] >= server_badness[i])					i = j;				if (n > server_list[j]->precision)					n = server_list[j]->precision;			}			/*			 * i is the index of the server with the worst			 * dispersion.	If his dispersion is less than			 * the threshold, stop now, else delete him and			 * continue around again.			 */			if ( (s_fp) server_badness[i] < (local_threshold							 + (FP_SECOND >> (-n))))				break;			for (j = i + 1; j < nlist; j++)				server_list[j-1] = server_list[j];			nlist--;		}		/*		 * What remains is a list of less than 5 servers.  Take		 * the best.		 */		sys_server = server_list[0];	}	/*	 * That's it.  Return our server.	 */	return sys_server;}/* * clock_adjust - process what we've received, and adjust the time *		 if we got anything decent. */static intclock_adjust(void){	register struct server *sp, *server;	s_fp absoffset;	int dostep;	for (sp = sys_servers; sp != NULL; sp = sp->next_server)		clock_filter(sp);	server = clock_select();	if (debug || simple_query) {		for (sp = sys_servers; sp != NULL; sp = sp->next_server)			printserver(sp, stdout);	}	if (server == 0) {		msyslog(LOG_ERR,			"no server suitable for synchronization found");		return(1);	}	if (always_step) {		dostep = 1;	} else if (never_step) {		dostep = 0;	} else {		absoffset = server->soffset;		if (absoffset < 0)			absoffset = -absoffset;		dostep = (absoffset >= NTPDATE_THRESHOLD || absoffset < 0);	}	if (dostep) {		if (simple_query || l_step_systime(&server->offset)) {			msyslog(LOG_NOTICE, "step time server %s offset %s sec",				stoa(&server->srcadr),				lfptoa(&server->offset, 6));		}	} else {#if !defined SYS_WINNT && !defined SYS_CYGWIN32		if (simple_query || l_adj_systime(&server->offset)) {			msyslog(LOG_NOTICE, "adjust time server %s offset %s sec",				stoa(&server->srcadr),				lfptoa(&server->offset, 6));		}#else		/* The NT SetSystemTimeAdjustment() call achieves slewing by		 * changing the clock frequency. This means that we cannot specify		 * it to slew the clock by a definite amount and then stop like		 * the Unix adjtime() routine. We can technically adjust the clock		 * frequency, have ntpdate sleep for a while, and then wake		 * up and reset the clock frequency, but this might cause some		 * grief if the user attempts to run ntpd immediately after		 * ntpdate and the socket is in use.		 */		printf("\nThe -b option is required by ntpdate on Windows NT platforms\n");		exit(1);#endif /* SYS_WINNT */	}	return(0);}/* * is_unreachable - check to see if we have a route to given destination *		    (non-blocking). */static intis_reachable (struct sockaddr_storage *dst){	SOCKET sockfd;	sockfd = socket(dst->ss_family, SOCK_DGRAM, 0);	if (sockfd == -1) {		return 0;	}	if(connect(sockfd, (struct sockaddr *)dst, SOCKLEN(dst))) {		closesocket(sockfd);		return 0;	}	closesocket(sockfd);	return 1;}/* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c *//* * addserver - determine a server's address and allocate a new structure *		for it. */static voidaddserver(	char *serv	){	register struct server *server;	/* Address infos structure to store result of getaddrinfo */	struct addrinfo *addrResult, *ptr;	/* Address infos structure to store hints for getaddrinfo */	struct addrinfo hints;	/* Error variable for getaddrinfo */	int error;	/* Service name */	char service[5];	strcpy(service, "ntp");	/* Get host address. Looking for UDP datagram connection. */	memset(&hints, 0, sizeof(hints));	hints.ai_family = ai_fam_templ;	hints.ai_socktype = SOCK_DGRAM;#ifdef DEBUG	if (debug)		printf("Looking for host %s and service %s\n", serv, service);#endif	error = getaddrinfo(serv, service, &hints, &addrResult);	if (error != 0) {		fprintf(stderr, "Error : %s\n", gai_strerror(error));		msyslog(LOG_ERR, "can't find host %s\n", serv);		return;	}#ifdef DEBUG	else if (debug) {		fprintf(stderr, "host found : %s\n", stohost((struct sockaddr_storage*)addrResult->ai_addr));	}#endif	/* We must get all returned server in case the first one fails */	for (ptr = addrResult; ptr != NULL; ptr = ptr->ai_next) {		if (is_reachable ((struct sockaddr_storage *)ptr->ai_addr)) {			server = (struct server *)emalloc(sizeof(struct server));			memset((char *)server, 0, sizeof(struct server));			memset(&(server->srcadr), 0, sizeof(struct sockaddr_storage));			memcpy(&(server->srcadr), ptr->ai_addr, ptr->ai_addrlen);			server->event_time = ++sys_numservers;			if (sys_servers == NULL)				sys_servers = server;			else {				struct server *sp;				for (sp = sys_servers; sp->next_server != NULL;				     sp = sp->next_server) ;				sp->next_server = server;			}		}	}	freeaddrinfo(addrResult);}/* * findserver - find a server in the list given its address * ***(For now it isn't totally AF-Independant, to check later..) */static struct server *findserver(	struct sockaddr_storage *addr	){	struct server *server;	struct server *mc_server;	isc_sockaddr_t laddr;	isc_sockaddr_t saddr;	if(addr->ss_family == AF_INET) {		isc_sockaddr_fromin( &laddr, &((struct sockaddr_in*)addr)->sin_addr, 0);	}	else {		isc_sockaddr_fromin6(&laddr, &((struct sockaddr_in6*)addr)->sin6_addr, 0);	}	mc_server = NULL;	if (htons(((struct sockaddr_in*)addr)->sin_port) != NTP_PORT)		return 0;	for (server = sys_servers; server != NULL; 	     server = server->next_server) {				if(server->srcadr.ss_family == AF_INET) {			isc_sockaddr_fromin(&saddr, &((struct sockaddr_in*)&server->srcadr)->sin_addr, 0);		}		else {			isc_sockaddr_fromin6(&saddr, &((struct sockaddr_in6*)&server->srcadr)->sin6_addr, 0);		}		if (isc_sockaddr_eqaddr(&laddr, &saddr) == ISC_TRUE)			return server;		if(addr->ss_family == server->srcadr.ss_family) {			if (isc_sockaddr_ismulticast(&saddr) == ISC_TRUE)				mc_server = server;		}	}	if (mc_server != NULL) {			struct server *sp;		if (mc_server->event_time != 0) {			mc_server->event_time = 0;			complete_servers++;		}		server = (struct server *)emalloc(sizeof(struct server));		memset((char *)server, 0, sizeof(struct server));		memcpy(&server->srcadr, &addr, sizeof(struct sockaddr_storage));		server->event_time = ++sys_numservers;		for (sp = sys_servers; sp->next_server != NULL;		     sp = sp->next_server) ;		sp->next_server = server;		transmit(server);	}	return NULL;}/* * timer - process a timer interrupt */voidtimer(void){	struct server *server;	/*	 * Bump the current idea of the time	 */	current_time++;	/*	 * Search through the server list looking for guys	 * who's event timers have expired.  Give these to	 * the transmit routine.	 */	for (server = sys_servers; server != NULL; 	     server = server->next_server) {		if (server->event_time != 0		    && server->event_time <= current_time)			transmit(server);	}}/* * The code duplication in the following subroutine sucks, but * we need to appease ansi2knr. */#ifndef SYS_WINNT/* * alarming - record the occurance of an alarm interrupt */static RETSIGTYPEalarming(	int sig	){	alarm_flag++;}#elsevoid CALLBACK alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2){	alarm_flag++;}#endif /* SYS_WINNT *//* * init_alarm - set up the timer interrupt */static voidinit_alarm(void){#ifndef SYS_WINNT# ifndef HAVE_TIMER_SETTIME	struct itimerval itimer;# else	struct itimerspec ntpdate_itimer;# endif#else	TIMECAPS tc;	UINT wTimerRes, wTimerID;# endif /* SYS_WINNT */#if defined SYS_CYGWIN32 || defined SYS_WINNT	HANDLE hToken;	TOKEN_PRIVILEGES tkp;	DWORD dwUser = 0;#endif /* SYS_WINNT */	alarm_flag = 0;#ifndef SYS_WINNT# if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)	alarm_flag = 0;	/* this code was put in as setitimer() is non existant this us the	 * POSIX "equivalents" setup - casey	 */	/* ntpdate_timerid is global - so we can kill timer later */	if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) ==#  ifdef SYS_VXWORKS		ERROR#  else		-1#  endif		)	{		fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n");		return;	}	/*	TIMER_HZ = (5)	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)	 * seconds from now and they continue on every 1/TIMER_HZ seconds.	 */	(void) signal_no_reset(SIGALRM, alarming);	ntpdate_itimer.it_interval.tv_sec = ntpdate_itimer.it_value.tv_sec = 0;	ntpdate_itimer.it_interval.tv_nsec = 1000000000/TIMER_HZ;	ntpdate_itimer.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1);	timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer, NULL);# else	/*	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)	 * seconds from now and they continue on every 1/TIMER_HZ seconds.	 */	(void) signal_no_reset(SIGALRM, alarming);	itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0;	itimer.it_interval.tv_usec = 1000000/TIMER_HZ;	itimer.it_value.tv_usec = 1000000/(TIMER_HZ<<1);	setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);# endif#if defined SYS_CYGWIN32	/*	 * Get previleges needed for fiddling with the clock	 */	/* get the current process token handle */	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {		msyslog(LOG_ERR, "OpenProcessToken failed: %m");		exit(1);	}	/* get the LUID for system-time privilege. */	LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);	tkp.PrivilegeCount = 1;		/* one privilege to set */	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;	/* get set-time privilege for this process. */	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);	/* cannot test return value of AdjustTokenPrivileges. */	if (GetLastError() != ERROR_SUCCESS)		msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");#endif#else	/* SYS_WINNT */	_tzset();	/*	 * Get previleges needed for fiddling with the clock	 */	/* get the current process token handle */	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {		msyslog(LOG_ERR, "OpenProcessToken failed: %m");		exit(1);	}	/* get the LUID for system-time privilege. */	LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);	tkp.PrivilegeCount = 1;		/* one privilege to set */	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;	/* get set-time privilege for this process. */	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);	/* cannot test return value of AdjustTokenPrivileges. */	if (GetLastError() != ERROR_SUCCESS)		msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");	/*	 * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds	 * Under Win/NT, expiry of timer interval leads to invocation	 * of a callback function (on a different thread) rather than	 * generating an alarm signal	 */	/* determine max and min resolution supported */	if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {		msyslog(LOG_ERR, "timeGetDevCaps failed: %m");		exit(1);	}	wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);	/* establish the minimum timer resolution that we'll use */	timeBeginPeriod(wTimerRes);	/* start the timer event */	wTimerID = timeSetEvent(		(UINT) (1000/TIMER_HZ),		/* Delay */		wTimerRes,			/* Resolution */		(LPTIMECALLBACK) alarming,	/* Callback function */		(DWORD) dwUser,			/* User data */		TIME_PERIODIC);			/* Event type (periodic) */	if (wTimerID == 0) {		msyslog(LOG_ERR, "timeSetEvent failed: %m");		exit(1);	}#endif /* SYS_WINNT */}/* * We do asynchronous input using the SIGIO facility.  A number of * recvbuf buffers are preallocated for input.	In the signal * handler we poll to see if the socket is ready and read the * packets from it into the recvbuf's along with a time stamp and * an indication of the source host and the interface it was received * through.  This allows us to get as accurate receive time stamps * as possible independent of other processing going on. * * We allocate a number of recvbufs equal to the number of servers * plus 2.	This should be plenty. *//* * init_io - initialize I/O data and open socket */static voidinit_io(void){	struct addrinfo *res, *ressave;	struct addrinfo hints;	char service[5];	int optval = 1;	/*	 * Init buffer free list and stat counters	 */	init_recvbuff(sys_numservers + 2);	/*	 * Open the socket	 */	strcpy(service, "ntp");	/*	 * Init hints addrinfo structure	 */	memset(&hints, 0, sizeof(hints));	hints.ai_family = ai_fam_templ;	hints.ai_flags = AI_PASSIVE;	hints.ai_socktype = SOCK_DGRAM;	if(getaddrinfo(NULL, service, &hints, &res) != 0) {	       msyslog(LOG_ERR, "getaddrinfo() failed: %m");	       exit(1);	       /*NOTREACHED*/	}#ifdef SYS_WINNT	if (ntp_port_inuse(AF_INET, NTP_PORT) ){		netsyslog(LOG_ERR, "the NTP socket is in use, exiting: %m");		exit(1);	}#endif	/* Remember the address of the addrinfo structure chain */	ressave = res;	/*	 * For each structure returned, open and bind socket

⌨️ 快捷键说明

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