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

📄 ntp_proto.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * Popcorn spike or step threshold exceeded. Pretend it never	 * happened.	 */	default:		break;	}	if (ostratum != sys_stratum)		report_event(EVNT_PEERSTCHG, NULL);}/* * poll_update - update peer poll interval */voidpoll_update(	struct peer *peer,	int	mpoll	){	int	hpoll;	/*	 * This routine figures out when the next poll should be sent.	 * That turns out to be wickedly complicated. The big problem is	 * that sometimes the time for the next poll is in the past.	 * Watch out for races here between the receive process and the	 * poll process. The key assertion is that, if nextdate equals	 * current_time, the call is from the poll process; otherwise,	 * it is from the receive process.	 *	 * First, bracket the poll interval according to the type of	 * association and options. If a fixed interval is configured,	 * use minpoll. This primarily is for reference clocks, but	 * works for any association.	 */	if (peer->flags & FLAG_FIXPOLL) {		hpoll = peer->minpoll;	/*	 * The ordinary case; clamp the poll interval between minpoll	 * and maxpoll.	 */	} else {		hpoll = max(min(peer->maxpoll, mpoll), peer->minpoll);	}#ifdef OPENSSL	/*	 * Bit of crass arrogance at this point. If the poll interval	 * has changed and we have a keylist, the lifetimes in the	 * keylist are probably bogus. In this case purge the keylist	 * and regenerate it later.	 */	if (hpoll != peer->hpoll)		key_expire(peer);#endif /* OPENSSL */	peer->hpoll = hpoll;	/*	 * Now we figure out if there is an override. If during the	 * crypto protocol and a message is pending, make it wait not	 * more than two seconds.	 */#ifdef OPENSSL	if (peer->cmmd != NULL && (sys_leap != LEAP_NOTINSYNC ||	    peer->crypto)) {		peer->nextdate = current_time + RESP_DELAY;	/*	 * If we get called from the receive routine while a burst is	 * pending, just slink away. If from the poll routine and a	 * reference clock or a pending crypto response, delay for one	 * second. If this is the first sent in a burst, wait for the	 * modem to come up. For others in the burst, delay two seconds.	 */	} else if (peer->burst > 0) {#else /* OPENSSL */	if (peer->burst > 0) {#endif /* OPENSSL */		if (peer->nextdate != current_time)			return;#ifdef REFCLOCK		else if (peer->flags & FLAG_REFCLOCK)			peer->nextdate += RESP_DELAY;#endif /* REFCLOCK */		else if (peer->flags & (FLAG_IBURST | FLAG_BURST) &&		    peer->burst == NTP_BURST)			peer->nextdate += sys_calldelay;		else			peer->nextdate += BURST_DELAY;	/*	 * The ordinary case; use the minimum of the host and peer	 * intervals, but not less than minpoll. In other words,	 * oversampling is okay but understampling is evil.	 */	} else {		peer->nextdate = peer->outdate +		    RANDPOLL(max(min(peer->ppoll, hpoll),		    peer->minpoll));	}	/*	 * If the time for the next poll has already happened, bring it	 * up to the next second after this one. This way the only way	 * to get nexdate == current time is from the poll routine.	 */	if (peer->nextdate <= current_time)		peer->nextdate = current_time + 1;#ifdef DEBUG	if (debug > 1)		printf("poll_update: at %lu %s flags %04x poll %d burst %d last %lu next %lu\n",		    current_time, ntoa(&peer->srcadr), peer->flags,		    peer->hpoll, peer->burst, peer->outdate,		    peer->nextdate);#endif}/* * peer_clear - clear peer filter registers.  See Section 3.4.8 of the spec. */voidpeer_clear(	struct peer *peer,		/* peer structure */	char	*ident			/* tally lights */	){	int	i;	/*	 * If cryptographic credentials have been acquired, toss them to	 * Valhalla. Note that autokeys are ephemeral, in that they are	 * tossed immediately upon use. Therefore, the keylist can be	 * purged anytime without needing to preserve random keys. Note	 * that, if the peer is purged, the cryptographic variables are	 * purged, too. This makes it much harder to sneak in some	 * unauthenticated data in the clock filter.	 */#ifdef OPENSSL	key_expire(peer);	if (peer->pkey != NULL)		EVP_PKEY_free(peer->pkey);	if (peer->ident_pkey != NULL)		EVP_PKEY_free(peer->ident_pkey);	if (peer->subject != NULL)		free(peer->subject);	if (peer->issuer != NULL)		free(peer->issuer);	if (peer->iffval != NULL)		BN_free(peer->iffval);	if (peer->grpkey != NULL)		BN_free(peer->grpkey);	if (peer->cmmd != NULL) {		free(peer->cmmd);		peer->cmmd = NULL;	}	value_free(&peer->cookval);	value_free(&peer->recval);	value_free(&peer->encrypt);	value_free(&peer->sndval);#endif /* OPENSSL */	if (peer == sys_peer)		sys_peer = NULL;	/*	 * Wipe the association clean and initialize the nonzero values.	 */	memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);	peer->estbdelay = sys_bdelay;	peer->ppoll = peer->maxpoll;	peer->hpoll = peer->minpoll;	peer->disp = MAXDISPERSE;	peer->jitter = LOGTOD(sys_precision);	for (i = 0; i < NTP_SHIFT; i++) {		peer->filter_order[i] = i;		peer->filter_disp[i] = MAXDISPERSE;	}#ifdef REFCLOCK	if (!(peer->flags & FLAG_REFCLOCK)) {		peer->leap = LEAP_NOTINSYNC;		peer->stratum = STRATUM_UNSPEC;		memcpy(&peer->refid, ident, 4);	}#else	peer->leap = LEAP_NOTINSYNC;	peer->stratum = STRATUM_UNSPEC;	memcpy(&peer->refid, ident, 4);#endif /* REFCLOCK */	/*	 * During initialization use the association count to spread out	 * the polls at one-second intervals. Othersie, randomize over	 * the minimum poll interval in order to avoid broadcast	 * implosion.	 */	peer->nextdate = peer->update = peer->outdate = current_time;	if (initializing)		peer->nextdate += peer_associations;	else if (peer->hmode == MODE_PASSIVE)		peer->nextdate += RESP_DELAY;	else		peer->nextdate += (ntp_random() & ((1 << NTP_MINDPOLL) -		    1));#ifdef DEBUG	if (debug)		printf("peer_clear: at %ld next %ld assoc ID %d refid %s\n",		    current_time, peer->nextdate, peer->associd, ident);#endif}/* * clock_filter - add incoming clock sample to filter register and run *		  the filter procedure to find the best sample. */voidclock_filter(	struct peer *peer,		/* peer structure pointer */	double	sample_offset,		/* clock offset */	double	sample_delay,		/* roundtrip delay */	double	sample_disp		/* dispersion */	){	double	dst[NTP_SHIFT];		/* distance vector */	int	ord[NTP_SHIFT];		/* index vector */	int	i, j, k, m;	double	dtemp, etemp;	/*	 * Shift the new sample into the register and discard the oldest	 * one. The new offset and delay come directly from the	 * timestamp calculations. The dispersion grows from the last	 * outbound packet or reference clock update to the present time	 * and increased by the sum of the peer precision and the system	 * precision. The delay can sometimes swing negative due to	 * frequency skew, so it is clamped non-negative.	 */	j = peer->filter_nextpt;	peer->filter_offset[j] = sample_offset;	peer->filter_delay[j] = max(0, sample_delay);	peer->filter_disp[j] = sample_disp;	peer->filter_epoch[j] = current_time;	j = (j + 1) % NTP_SHIFT;	peer->filter_nextpt = j;	/*	 * Update dispersions since the last update and at the same	 * time initialize the distance and index lists. The distance	 * list uses a compound metric. If the sample is valid and	 * younger than the minimum Allan intercept, use delay;	 * otherwise, use biased dispersion.	 */	dtemp = clock_phi * (current_time - peer->update);	peer->update = current_time;	for (i = NTP_SHIFT - 1; i >= 0; i--) {		if (i != 0)			peer->filter_disp[j] += dtemp;		if (peer->filter_disp[j] >= MAXDISPERSE) 			peer->filter_disp[j] = MAXDISPERSE;		if (peer->filter_disp[j] >= MAXDISPERSE)			dst[i] = MAXDISPERSE;		else if (peer->update - peer->filter_epoch[j] >		    allan_xpt)			dst[i] = sys_maxdist + peer->filter_disp[j];		else			dst[i] = peer->filter_delay[j];		ord[i] = j;		j++; j %= NTP_SHIFT;	}        /*	 * Sort the samples in both lists by distance. Note, we do not	 * displace a higher distance sample by a lower distance one	 * unless lower by at least the precision.  	 */	for (i = 1; i < NTP_SHIFT; i++) {		for (j = 0; j < i; j++) {			if (dst[j] > dst[i] + LOGTOD(sys_precision)) {				k = ord[j];				ord[j] = ord[i];				ord[i] = k;				etemp = dst[j];				dst[j] = dst[i];				dst[i] = etemp;			}		}	}	/*	 * Copy the index list to the association structure so ntpq	 * can see it later. Prune the distance list to samples less	 * than max distance, but keep at least two valid samples for	 * jitter calculation.	 */	m = 0;	for (i = 0; i < NTP_SHIFT; i++) {		peer->filter_order[i] = (u_char) ord[i];		if (dst[i] >= MAXDISPERSE || (m >= 2 && dst[i] >=		    sys_maxdist))			continue;		m++;	}		/*	 * Compute the dispersion and jitter. The dispersion is weighted	 * exponentially by NTP_FWEIGHT (0.5) so it is normalized close	 * to 1.0. The jitter is the RMS differences relative to the	 * lowest delay sample. If no acceptable samples remain in the	 * shift register, quietly tiptoe home leaving only the	 * dispersion.	 */	peer->disp = peer->jitter = 0;	k = ord[0];	for (i = NTP_SHIFT - 1; i >= 0; i--) {		j = ord[i];		peer->disp = NTP_FWEIGHT * (peer->disp +		    peer->filter_disp[j]);		if (i < m)			peer->jitter += DIFF(peer->filter_offset[j],			    peer->filter_offset[k]);	}	/*	 * If no acceptable samples remain in the shift register,	 * quietly tiptoe home leaving only the dispersion. Otherwise,	 * save the offset, delay and jitter. Note the jitter must not	 * be less than the precision.	 */	if (m == 0)		return;	etemp = fabs(peer->offset - peer->filter_offset[k]);	peer->offset = peer->filter_offset[k];	peer->delay = peer->filter_delay[k];	if (m > 1)		peer->jitter /= m - 1;	peer->jitter = max(SQRT(peer->jitter), LOGTOD(sys_precision));	/*	 * A new sample is useful only if it is younger than the last	 * one used, but only if the sucker has been synchronized.	 */	if (peer->filter_epoch[k] <= peer->epoch && sys_leap !=	    LEAP_NOTINSYNC) {#ifdef DEBUG		if (debug)			printf("clock_filter: discard %lu\n",			    peer->epoch - peer->filter_epoch[k]);#endif		return;	}	/*	 * If the difference between the last offset and the current one	 * exceeds the jitter by CLOCK_SGATE and the interval since the	 * last update is less than twice the system poll interval,	 * consider the update a popcorn spike and ignore it.	 */	if (etemp > CLOCK_SGATE * peer->jitter && m > 1 &&	    peer->filter_epoch[k] - peer->epoch < 2. *	    ULOGTOD(sys_poll)) {#ifdef DEBUG		if (debug)			printf("clock_filter: popcorn %.6f %.6f\n",			    etemp, dtemp);#endif		return;	}	/*	 * The mitigated sample statistics are saved for later	 * processing. If not in a burst, tickle the select.	 */	peer->epoch = peer->filter_epoch[k];#ifdef DEBUG	if (debug)		printf(		    "clock_filter: n %d off %.6f del %.6f dsp %.6f jit %.6f, age %lu\n",		    m, peer->offset, peer->delay, peer->disp,		    peer->jitter, current_time - peer->epoch);#endif	if (peer->burst == 0 || sys_leap == LEAP_NOTINSYNC)		clock_select();}/* * clock_select - find the pick-of-the-litter clock * * LOCKCLOCK: If the local clock is the prefer peer, it will always be * enabled, even if declared falseticker, (2) only the prefer peer can * be selected as the system peer, (3) if the external source is down, * the system leap bits are set to 11 and the stratum set to infinity. */voidclock_select(void){	struct peer *peer;	int	i, j, k, n;	int	nlist, nl3;	int	allow, osurv;	double	d, e, f, g;	double	high, low;	double	synch[NTP_MAXASSOC], error[NTP_MAXASSOC];	struct peer *osys_peer;	struct peer *typeacts = NULL;	struct peer *typelocal = NULL;	struct peer *typesystem = NULL;	static int list_alloc = 0;	static struct endpoint *endpoint = NULL;	static int *indx = NULL;	static struct peer **peer_list = NULL;	static u_int endpoint_size = 0;	static u_int indx_size = 0;	static u_int peer_list_size = 0;	/*	 * Initialize and create endpoint, index and peer lists big	 * enough to handle all associations.	 */	osys_peer = sys_peer;	sys_peer = NULL;	sys_pps = NULL;	sys_prefer = NULL;	osurv = sys_survivors;	sys_survivors = 0;#ifdef LOCKCLOCK	sys_leap = LEAP_NOTINSYNC;	sys_stratum = STRATUM_UNSPEC;	memcpy(&sys_refid, "DOWN", 4);#endif /* LOCKCLOCK */	nlist = 0;	for (n = 0; n < NTP_HASH_SIZE; n++)		nlist += peer_hash_count[n];	if (nlist > list_alloc) {		if (list_alloc > 0) {			free(endpoint);			free(indx);			free(peer_list);		}		while (list_alloc < nlist) {			list_alloc += 5;			endpoint_size += 5 * 3 * sizeof(*endpoint);			indx_size += 5 * 3 * sizeof(*indx);			peer_list_size += 5 * sizeof(*peer_list);		}		endpoint = (struct endpoint *)emalloc(endpoint_size);		indx = (int *)emalloc(indx_size);		peer_list = (struct peer **)emalloc(peer_list_size);	}

⌨️ 快捷键说明

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