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

📄 ntpdate.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef SYS_WINNT	process_handle = GetCurrentProcess();	if (!SetPriorityClass(process_handle, (DWORD) REALTIME_PRIORITY_CLASS)) {		msyslog(LOG_ERR, "SetPriorityClass failed: %m");	}#endif /* SYS_WINNT */	initializing = 0;	was_alarmed = 0;	rbuflist = (struct recvbuf *)0;	while (complete_servers < sys_numservers) {#ifdef HAVE_POLL_H		struct pollfd* rdfdes;		rdfdes = fdmask;#else		fd_set rdfdes;		rdfdes = fdmask;#endif		if (alarm_flag) {		/* alarmed? */			was_alarmed = 1;			alarm_flag = 0;		}		rbuflist = getrecvbufs();	/* get received buffers */		if (!was_alarmed && rbuflist == (struct recvbuf *)0) {			/*			 * Nothing to do.	 Wait for something.			 */#ifdef HAVE_POLL_H			nfound = poll(rdfdes, (unsigned int)nbsock, timeout.tv_sec * 1000);#else			nfound = select(maxfd, &rdfdes, (fd_set *)0,					(fd_set *)0, &timeout);#endif			if (nfound > 0)				input_handler();			else if (nfound == SOCKET_ERROR)			{#ifndef SYS_WINNT				if (errno != EINTR)#else				if (WSAGetLastError() != WSAEINTR)#endif					netsyslog(LOG_ERR,#ifdef HAVE_POLL_H						"poll() error: %m"#else						"select() error: %m"#endif						);			} else if (errno != 0) {#ifndef SYS_VXWORKS				netsyslog(LOG_DEBUG,#ifdef HAVE_POLL_H					"poll(): nfound = %d, error: %m",#else					"select(): nfound = %d, error: %m",#endif					nfound);#endif			}			if (alarm_flag) {		/* alarmed? */				was_alarmed = 1;				alarm_flag = 0;			}			rbuflist = getrecvbufs();	/* get received buffers */		}		/*		 * Out here, signals are unblocked.  Call receive		 * procedure for each incoming packet.		 */		while (rbuflist != (struct recvbuf *)0) {			rbuf = rbuflist;			rbuflist = rbuf->next;			receive(rbuf);			freerecvbuf(rbuf);		}		/*		 * Call timer to process any timeouts		 */		if (was_alarmed) {			timer();			was_alarmed = 0;		}		/*		 * Go around again		 */	}	/*	 * When we get here we've completed the polling of all servers.	 * Adjust the clock, then exit.	 */#ifdef SYS_WINNT	WSACleanup();#endif#ifdef SYS_VXWORKS	close (fd);	timer_delete(ntpdate_timerid);#endif	return clock_adjust();}/* * transmit - transmit a packet to the given server, or mark it completed. *		This is called by the timeout routine and by the receive *		procedure. */static voidtransmit(	register struct server *server	){	struct pkt xpkt;	if (debug)		printf("transmit(%s)\n", stoa(&(server->srcadr)));	if (server->filter_nextpt < server->xmtcnt) {		l_fp ts;		/*		 * Last message to this server timed out.  Shift		 * zeros into the filter.		 */		L_CLR(&ts);		server_data(server, 0, &ts, 0);	}	if ((int)server->filter_nextpt >= sys_samples) {		/*		 * Got all the data we need.  Mark this guy		 * completed and return.		 */		server->event_time = 0;		complete_servers++;		return;	}	/*	 * If we're here, send another message to the server.  Fill in	 * the packet and let 'er rip.	 */	xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,					 sys_version, MODE_CLIENT);	xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);	xpkt.ppoll = NTP_MINPOLL;	xpkt.precision = NTPDATE_PRECISION;	xpkt.rootdelay = htonl(NTPDATE_DISTANCE);	xpkt.rootdispersion = htonl(NTPDATE_DISP);	xpkt.refid = htonl(NTPDATE_REFID);	L_CLR(&xpkt.reftime);	L_CLR(&xpkt.org);	L_CLR(&xpkt.rec);	/*	 * Determine whether to authenticate or not.	If so,	 * fill in the extended part of the packet and do it.	 * If not, just timestamp it and send it away.	 */	if (sys_authenticate) {		int len;		xpkt.exten[0] = htonl(sys_authkey);		get_systime(&server->xmt);		L_ADDUF(&server->xmt, sys_authdelay);		HTONL_FP(&server->xmt, &xpkt.xmt);		len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC);		sendpkt(&(server->srcadr), &xpkt, (int)(LEN_PKT_NOMAC + len));		if (debug > 1)			printf("transmit auth to %s\n",			   stoa(&(server->srcadr)));	} else {		get_systime(&(server->xmt));		HTONL_FP(&server->xmt, &xpkt.xmt);		sendpkt(&(server->srcadr), &xpkt, LEN_PKT_NOMAC);		if (debug > 1)			printf("transmit to %s\n", stoa(&(server->srcadr)));	}	/*	 * Update the server timeout and transmit count	 */	server->event_time = current_time + sys_timeout;	server->xmtcnt++;}/* * receive - receive and process an incoming frame */static voidreceive(	struct recvbuf *rbufp	){	register struct pkt *rpkt;	register struct server *server;	register s_fp di;	l_fp t10, t23, tmp;	l_fp org;	l_fp rec;	l_fp ci;	int has_mac;	int is_authentic;	if (debug)		printf("receive(%s)\n", stoa(&rbufp->recv_srcadr));	/*	 * Check to see if the packet basically looks like something	 * intended for us.	 */	if (rbufp->recv_length == LEN_PKT_NOMAC)		has_mac = 0;	else if (rbufp->recv_length >= LEN_PKT_NOMAC)		has_mac = 1;	else {		if (debug)			printf("receive: packet length %d\n",			   rbufp->recv_length);		return; 		/* funny length packet */	}	rpkt = &(rbufp->recv_pkt);	if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||		PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {		return;	}	if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER		 && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE)		|| rpkt->stratum >= STRATUM_UNSPEC) {		if (debug)			printf("receive: mode %d stratum %d\n",			   PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);		return;	}	/*	 * So far, so good.  See if this is from a server we know.	 */	server = findserver(&(rbufp->recv_srcadr));	if (server == NULL) {		if (debug)			printf("receive: server not found\n");		return;	}	/*	 * Decode the org timestamp and make sure we're getting a response	 * to our last request.	 */	NTOHL_FP(&rpkt->org, &org);	if (!L_ISEQU(&org, &server->xmt)) {		if (debug)			printf("receive: pkt.org and peer.xmt differ\n");		return;	}	/*	 * Check out the authenticity if we're doing that.	 */	if (!sys_authenticate)		is_authentic = 1;	else {		is_authentic = 0;		if (debug > 3)			printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",			   (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey,			   (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt,				LEN_PKT_NOMAC, (int)(rbufp->recv_length - LEN_PKT_NOMAC)));		if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey &&			authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC,			(int)(rbufp->recv_length - LEN_PKT_NOMAC)))			is_authentic = 1;		if (debug)			printf("receive: authentication %s\n",			   is_authentic ? "passed" : "failed");	}	server->trust <<= 1;	if (!is_authentic)		server->trust |= 1;	/*	 * Looks good.	Record info from the packet.	 */	server->leap = PKT_LEAP(rpkt->li_vn_mode);	server->stratum = PKT_TO_STRATUM(rpkt->stratum);	server->precision = rpkt->precision;	server->rootdelay = ntohl(rpkt->rootdelay);	server->rootdispersion = ntohl(rpkt->rootdispersion);	server->refid = rpkt->refid;	NTOHL_FP(&rpkt->reftime, &server->reftime);	NTOHL_FP(&rpkt->rec, &rec);	NTOHL_FP(&rpkt->xmt, &server->org);	/*	 * Make sure the server is at least somewhat sane.	If not, try	 * again.	 */	if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {		transmit(server);		return;	}	/*	 * Calculate the round trip delay (di) and the clock offset (ci).	 * We use the equations (reordered from those in the spec):	 *	 * d = (t2 - t3) - (t1 - t0)	 * c = ((t2 - t3) + (t1 - t0)) / 2	 */	t10 = server->org;		/* pkt.xmt == t1 */	L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/	t23 = rec;			/* pkt.rec == t2 */	L_SUB(&t23, &org);		/* pkt->org == t3 */	/* now have (t2 - t3) and (t0 - t1).	Calculate (ci) and (di) */	/*	 * Calculate (ci) = ((t1 - t0) / 2) + ((t2 - t3) / 2)	 * For large offsets this may prevent an overflow on '+'	 */	ci = t10;	L_RSHIFT(&ci);	tmp = t23;	L_RSHIFT(&tmp);	L_ADD(&ci, &tmp);	/*	 * Calculate di in t23 in full precision, then truncate	 * to an s_fp.	 */	L_SUB(&t23, &t10);	di = LFPTOFP(&t23);	if (debug > 3)		printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));	di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))		+ (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;	if (di <= 0) {		/* value still too raunchy to use? */		L_CLR(&ci);		di = 0;	} else {		di = max(di, NTP_MINDIST);	}	/*	 * Shift this data in, then transmit again.	 */	server_data(server, (s_fp) di, &ci, 0);	transmit(server);}/* * server_data - add a sample to the server's filter registers */static voidserver_data(	register struct server *server,	s_fp d,	l_fp *c,	u_fp e	){	u_short i;	i = server->filter_nextpt;	if (i < NTP_SHIFT) {		server->filter_delay[i] = d;		server->filter_offset[i] = *c;		server->filter_soffset[i] = LFPTOFP(c);		server->filter_error[i] = e;		server->filter_nextpt = (u_short)(i + 1);	}}/* * clock_filter - determine a server's delay, dispersion and offset */static voidclock_filter(	register struct server *server	){	register int i, j;	int ord[NTP_SHIFT];	/*	 * Sort indices into increasing delay order	 */	for (i = 0; i < sys_samples; i++)		ord[i] = i;	for (i = 0; i < (sys_samples-1); i++) {		for (j = i+1; j < sys_samples; j++) {			if (server->filter_delay[ord[j]] == 0)				continue;			if (server->filter_delay[ord[i]] == 0				|| (server->filter_delay[ord[i]]				> server->filter_delay[ord[j]])) {				register int tmp;				tmp = ord[i];				ord[i] = ord[j];				ord[j] = tmp;			}		}	}	/*	 * Now compute the dispersion, and assign values to delay and	 * offset.	If there are no samples in the register, delay and	 * offset go to zero and dispersion is set to the maximum.	 */	if (server->filter_delay[ord[0]] == 0) {		server->delay = 0;		L_CLR(&server->offset);		server->soffset = 0;		server->dispersion = PEER_MAXDISP;	} else {		register s_fp d;		server->delay = server->filter_delay[ord[0]];		server->offset = server->filter_offset[ord[0]];		server->soffset = LFPTOFP(&server->offset);		server->dispersion = 0;		for (i = 1; i < sys_samples; i++) {			if (server->filter_delay[ord[i]] == 0)				d = PEER_MAXDISP;			else {				d = server->filter_soffset[ord[i]]					- server->filter_soffset[ord[0]];				if (d < 0)					d = -d;				if (d > PEER_MAXDISP)					d = PEER_MAXDISP;			}			/*			 * XXX This *knows* PEER_FILTER is 1/2			 */			server->dispersion += (u_fp)(d) >> i;		}	}	/*	 * We're done	 */}/* * clock_select - select the pick-of-the-litter clock from the samples *		  we've got. */static struct server *clock_select(void){	register struct server *server;	register int i;	register int nlist;	register s_fp d;	register int j;	register int n;	s_fp local_threshold;	struct server *server_list[NTP_MAXCLOCK];	u_fp server_badness[NTP_MAXCLOCK];	struct server *sys_server;	/*	 * This first chunk of code is supposed to go through all	 * servers we know about to find the NTP_MAXLIST servers which	 * are most likely to succeed.	We run through the list	 * doing the sanity checks and trying to insert anyone who	 * looks okay.	We are at all times aware that we should	 * only keep samples from the top two strata and we only need	 * NTP_MAXLIST of them.	 */	nlist = 0;	/* none yet */	for (server = sys_servers; server != NULL; server = server->next_server) {		if (server->delay == 0) {			if (debug)				printf("%s: Server dropped: no data\n", ntoa(&server->srcadr));			continue;	/* no data */		}		if (server->stratum > NTP_INFIN) {			if (debug)				printf("%s: Server dropped: strata too high\n", ntoa(&server->srcadr));			continue;	/* stratum no good */		}		if (server->delay > NTP_MAXWGT) {			if (debug)				printf("%s: Server dropped: server too far away\n", 					ntoa(&server->srcadr));			continue;	/* too far away */		}		if (server->leap == LEAP_NOTINSYNC) {			if (debug)				printf("%s: Server dropped: Leap not in sync\n", ntoa(&server->srcadr));			continue;	/* he's in trouble */		}		if (!L_ISHIS(&server->org, &server->reftime)) {			if (debug)				printf("%s: Server dropped: server is very broken\n", 				       ntoa(&server->srcadr));			continue;	/* very broken host */		}		if ((server->org.l_ui - server->reftime.l_ui)		    >= NTP_MAXAGE) {			if (debug)				printf("%s: Server dropped: Server has gone too long without sync\n", 				       ntoa(&server->srcadr));			continue;	/* too long without sync */		}		if (server->trust != 0) {			if (debug)				printf("%s: Server dropped: Server is untrusted\n",				       ntoa(&server->srcadr));			continue;		}		/*		 * This one seems sane.  Find where he belongs		 * on the list.		 */		d = server->dispersion + server->dispersion;		for (i = 0; i < nlist; i++)			if (server->stratum <= server_list[i]->stratum)			break;		for ( ; i < nlist; i++) {			if (server->stratum < server_list[i]->stratum)				break;			if (d < (s_fp) server_badness[i])				break;		}		/*		 * If i points past the end of the list, this		 * guy is a loser, else stick him in.		 */		if (i >= NTP_MAXLIST)			continue;		for (j = nlist; j > i; j--)			if (j < NTP_MAXLIST) {				server_list[j] = server_list[j-1];				server_badness[j]					= server_badness[j-1];			}		server_list[i] = server;		server_badness[i] = d;		if (nlist < NTP_MAXLIST)			nlist++;	}	/*	 * Got the five-or-less best.	 Cut the list where the number of	 * strata exceeds two.	 */	j = 0;	for (i = 1; i < nlist; i++)		if (server_list[i]->stratum > server_list[i-1]->stratum)		if (++j == 2) {			nlist = i;			break;		}

⌨️ 快捷键说明

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