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

📄 ntp_proto.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * For everything else there is the bit bucket.	 */	default:		return;	}	peer->flash &= ~PKT_TEST_MASK;	/*	 * Next comes a rigorous schedule of timestamp checking. If the	 * transmit timestamp is zero, the server is horribly broken.	 */	if (L_ISZERO(&p_xmt)) {		return;				/* read rfc1305 */	/*	 * If the transmit timestamp duplicates a previous one, the	 * packet is a replay. This prevents the bad guys from replaying	 * the most recent packet, authenticated or not.	 */	} else if (L_ISEQU(&peer->org, &p_xmt)) {		peer->flash |= TEST1;		peer->oldpkt++;		return;				/* duplicate packet */		/*	 * If this is a broadcast mode packet, skip further checking.	 */	} else if (hismode != MODE_BROADCAST) {		if (L_ISZERO(&p_org))			peer->flash |= TEST3;	/* protocol unsynch */		else if (!L_ISEQU(&p_org, &peer->xmt))			peer->flash |= TEST2;	/* bogus packet */	}	/*	 * Update the origin and destination timestamps. If	 * unsynchronized or bogus abandon ship. If the crypto machine	 * breaks, light the crypto bit and plaint the log.	 */	peer->org = p_xmt;	peer->rec = rbufp->recv_time;	if (peer->flash & PKT_TEST_MASK) {#ifdef OPENSSL		if (crypto_flags && (peer->flags & FLAG_SKEY)) {			rval = crypto_recv(peer, rbufp);			if (rval != XEVNT_OK) {				peer_clear(peer, "CRYP");				peer->flash |= TEST9; /* crypto error */			}		}#endif /* OPENSSL */		return;				/* unsynch */	}	/*	 * The timestamps are valid and the receive packet matches the	 * last one sent. If the packet is a crypto-NAK, the server	 * might have just changed keys. We reset the association	 * and restart the protocol.	 */	if (is_authentic == AUTH_CRYPTO) {		peer_clear(peer, "AUTH");		return;				/* crypto-NAK */	/* 	 * If the association is authenticated, the key ID is nonzero	 * and received packets must be authenticated. This is designed	 * to avoid a bait-and-switch attack, which was possible in past	 * versions. If symmetric modes, return a crypto-NAK. The peer	 * should restart the protocol.	 */	} else if (!AUTH(peer->keyid || (restrict_mask & RES_DONTTRUST),	    is_authentic)) {		peer->flash |= TEST5;		if (hismode == MODE_ACTIVE || hismode == MODE_PASSIVE)			fast_xmit(rbufp, MODE_ACTIVE, 0, restrict_mask);		return;				/* bad auth */	}	/*	 * That was hard and I am sweaty, but the packet is squeaky	 * clean. Get on with real work.	 */	peer->received++;	peer->timereceived = current_time;	if (is_authentic == AUTH_OK)		peer->flags |= FLAG_AUTHENTIC;	else		peer->flags &= ~FLAG_AUTHENTIC;#ifdef OPENSSL	/*	 * More autokey dance. The rules of the cha-cha are as follows:	 *	 * 1. If there is no key or the key is not auto, do nothing.	 *	 * 2. If this packet is in response to the one just previously	 *    sent or from a broadcast server, do the extension fields.	 *    Otherwise, assume bogosity and bail out.	 *	 * 3. If an extension field contains a verified signature, it is	 *    self-authenticated and we sit the dance.	 *	 * 4. If this is a server reply, check only to see that the	 *    transmitted key ID matches the received key ID.	 *	 * 5. Check to see that one or more hashes of the current key ID	 *    matches the previous key ID or ultimate original key ID	 *    obtained from the broadcaster or symmetric peer. If no	 *    match, sit the dance and wait for timeout.	 *	 * In case of crypto error, fire the orchestra and stop dancing.	 * This is considered a permanant error, so light the crypto bit	 * to suppress further requests. If preemptable or ephemeral,	 * scuttle the ship.	 */	if (crypto_flags && (peer->flags & FLAG_SKEY)) {		peer->flash |= TEST8;		rval = crypto_recv(peer, rbufp);		if (rval != XEVNT_OK) {			peer_clear(peer, "CRYP");			peer->flash |= TEST9;	/* crypto error */			if (peer->flags & FLAG_PREEMPT ||			    !(peer->flags & FLAG_CONFIG))				unpeer(peer);			return;		} else if (hismode == MODE_SERVER) {			if (skeyid == peer->keyid)				peer->flash &= ~TEST8;		} else if (!(peer->flash & TEST8)) {			peer->pkeyid = skeyid;		} else if ((ap = (struct autokey *)peer->recval.ptr) !=		    NULL) {			int i;			for (i = 0; ; i++) {				if (tkeyid == peer->pkeyid ||				    tkeyid == ap->key) {					peer->flash &= ~TEST8;					peer->pkeyid = skeyid;					break;				}				if (i > ap->seq)					break;				tkeyid = session_key(				    &rbufp->recv_srcadr, dstadr_sin,				    tkeyid, pkeyid, 0);			}		}		if (!(peer->crypto & CRYPTO_FLAG_PROV)) /* test 9 */			peer->flash |= TEST8;	/* not proventic */		/*		 * If the transmit queue is nonempty, clamp the host		 * poll interval to the packet poll interval.		 */		if (peer->cmmd != 0) {			peer->ppoll = pkt->ppoll;			poll_update(peer, peer->hpoll);		}	}#endif /* OPENSSL */	/*	 * The dance is complete and the flash bits have been lit. Toss	 * the packet over the fence for processing, which may light up	 * more flashers.	 */	process_packet(peer, pkt);	/*	 * Well, that was nice. If TEST4 is lit, either the crypto	 * machine jammed or a kiss-o'-death packet flew in, either of	 * which is fatal.	 */	if (peer->flash & TEST4) {		msyslog(LOG_INFO, "receive: fatal error %04x for %s",		    peer->flash, stoa(&peer->srcadr));		return;	}}/* * process_packet - Packet Procedure, a la Section 3.4.4 of the *	specification. Or almost, at least. If we're in here we have a *	reasonable expectation that we will be having a long term *	relationship with this host. */voidprocess_packet(	register struct peer *peer,	register struct pkt *pkt	){	double	t34, t21;	double	p_offset, p_del, p_disp;	l_fp	p_rec, p_xmt, p_org, p_reftime;	l_fp	ci;	u_char	pmode, pleap, pstratum;	sys_processed++;	peer->processed++;	p_del = FPTOD(NTOHS_FP(pkt->rootdelay));	p_disp = FPTOD(NTOHS_FP(pkt->rootdispersion));	NTOHL_FP(&pkt->reftime, &p_reftime);	NTOHL_FP(&pkt->rec, &p_rec);	NTOHL_FP(&pkt->xmt, &p_xmt);	pmode = PKT_MODE(pkt->li_vn_mode);	pleap = PKT_LEAP(pkt->li_vn_mode);	if (pmode != MODE_BROADCAST)		NTOHL_FP(&pkt->org, &p_org);	else		p_org = peer->rec;	pstratum = PKT_TO_STRATUM(pkt->stratum);	/*	 * Test for kiss-o'death packet)	 */	if (pleap == LEAP_NOTINSYNC && pstratum == STRATUM_UNSPEC) {		if (memcmp(&pkt->refid, "DENY", 4) == 0) {			peer_clear(peer, "DENY");			peer->flash |= TEST4;	/* access denied */		}	}	/*	 * Capture the header values.	 */	record_raw_stats(&peer->srcadr, &peer->dstadr->sin, &p_org,	    &p_rec, &p_xmt, &peer->rec);	peer->leap = pleap;	peer->stratum = min(pstratum, STRATUM_UNSPEC);	peer->pmode = pmode;	peer->ppoll = pkt->ppoll;	peer->precision = pkt->precision;	peer->rootdelay = p_del;	peer->rootdispersion = p_disp;	peer->refid = pkt->refid;		/* network byte order */	peer->reftime = p_reftime;	/*	 * Verify the server is synchronized; that is, the leap bits and	 * stratum are valid, the root delay and root dispersion are	 * valid and the reference timestamp is not later than the	 * transmit timestamp.	 */	if (pleap == LEAP_NOTINSYNC ||		/* test 6 */	    pstratum < sys_floor || pstratum >= sys_ceiling)		peer->flash |= TEST6;		/* peer not synch */	if (p_del < 0 || p_disp < 0 || p_del /	/* test 7 */	    2 + p_disp >= MAXDISPERSE || !L_ISHIS(&p_xmt, &p_reftime))		peer->flash |= TEST7;		/* bad header */	/*	 * If any tests fail at this point, the packet is discarded.	 * Note that some flashers may have already been set in the	 * receive() routine.	 */	if (peer->flash & PKT_TEST_MASK) {#ifdef DEBUG		if (debug)			printf("packet: flash header %04x\n",			    peer->flash);#endif		return;	}	if (!(peer->reach)) {		report_event(EVNT_REACH, peer);		peer->timereachable = current_time;	}	poll_update(peer, peer->hpoll);	peer->reach |= 1;	/*	 * For a client/server association, calculate the clock offset,	 * roundtrip delay and dispersion. The equations are reordered	 * from the spec for more efficient use of temporaries. For a	 * broadcast association, offset the last measurement by the	 * computed delay during the client/server volley. Note that	 * org has been set to the time of last reception. Note the	 * computation of dispersion includes the system precision plus	 * that due to the frequency error since the origin time.	 *	 * It is very important to respect the hazards of overflow. The	 * only permitted operation on raw timestamps is subtraction,	 * where the result is a signed quantity spanning from 68 years	 * in the past to 68 years in the future. To avoid loss of	 * precision, these calculations are done using 64-bit integer	 * arithmetic. However, the offset and delay calculations are	 * sums and differences of these first-order differences, which	 * if done using 64-bit integer arithmetic, would be valid over	 * only half that span. Since the typical first-order	 * differences are usually very small, they are converted to 64-	 * bit doubles and all remaining calculations done in floating-	 * point arithmetic. This preserves the accuracy while retaining	 * the 68-year span.	 *	 * Let t1 = p_org, t2 = p_rec, t3 = p_xmt, t4 = peer->rec:	 */	ci = p_xmt;			/* t3 - t4 */	L_SUB(&ci, &peer->rec);	LFPTOD(&ci, t34);	ci = p_rec;			/* t2 - t1 */	L_SUB(&ci, &p_org);	LFPTOD(&ci, t21);	ci = peer->rec;			/* t4 - t1 */	L_SUB(&ci, &p_org);	/*	 * If running in a broadcast association, the clock offset is	 * (t1 - t0) corrected by the one-way delay, but we can't	 * measure that directly. Therefore, we start up in MODE_CLIENT	 * mode, set FLAG_MCAST and exchange eight messages to determine	 * the clock offset. When the last message is sent, we switch to	 * MODE_BCLIENT mode. The next broadcast message after that	 * computes the broadcast offset and clears FLAG_MCAST.	 */	if (pmode == MODE_BROADCAST) {		p_offset = t34;		if (peer->flags & FLAG_MCAST) {			peer->estbdelay = peer->offset - p_offset;			if (peer->hmode == MODE_CLIENT)				return;			peer->flags &= ~(FLAG_MCAST | FLAG_BURST);		}		p_offset += peer->estbdelay;		p_del = peer->delay;		p_disp = 0;	} else {		p_offset = (t21 + t34) / 2.;		p_del = t21 - t34;		LFPTOD(&ci, p_disp);		p_disp = LOGTOD(sys_precision) +		    LOGTOD(peer->precision) + clock_phi * p_disp;	}	p_del = max(p_del, LOGTOD(sys_precision));	clock_filter(peer, p_offset, p_del, p_disp);	record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),	    peer->offset, peer->delay, peer->disp, peer->jitter);}/* * clock_update - Called at system process update intervals. */static voidclock_update(void){	u_char	oleap;	u_char	ostratum;	double	dtemp;	/*	 * There must be a system peer at this point. If we just changed	 * the system peer, but have a newer sample from the old one,	 * wait until newer data are available.	 */	if (sys_poll < sys_peer->minpoll)		sys_poll = sys_peer->minpoll;	if (sys_poll > sys_peer->maxpoll)		sys_poll = sys_peer->maxpoll;	poll_update(sys_peer, sys_poll);	if (sys_peer->epoch <= sys_clocktime)		return;#ifdef DEBUG	if (debug)		printf("clock_update: at %ld assoc %d \n", current_time,		    peer_associations);#endif	oleap = sys_leap;	ostratum = sys_stratum;	switch (local_clock(sys_peer, sys_offset)) {	/*	 * Clock exceeds panic threshold. Life as we know it ends.	 */	case -1:		report_event(EVNT_SYSFAULT, NULL);		exit (-1);		/* not reached */	/*	 * Clock was stepped. Flush all time values of all peers.	 */	case 2:		clear_all();		sys_leap = LEAP_NOTINSYNC;		sys_stratum = STRATUM_UNSPEC;		sys_peer = NULL;		sys_rootdelay = 0;		sys_rootdispersion = 0;		memcpy(&sys_refid, "STEP", 4);		sys_poll = NTP_MINPOLL;		report_event(EVNT_CLOCKRESET, NULL);		break;	/*	 * Clock was slewed. Update the system stratum, leap bits, root	 * delay, root dispersion, reference ID and reference time. If	 * the leap changes, we gotta reroll the keys. Except for	 * reference clocks, the minimum dispersion increment is not	 * less than sys_mindisp.	 */	case 1:		sys_leap = leap_next;		sys_stratum = min(sys_peer->stratum + 1,		    STRATUM_UNSPEC);		sys_reftime = sys_peer->rec;		/*		 * In orphan mode the stratum defaults to the orphan		 * stratum. The root delay is set to a random value		 * generated at startup. The root dispersion is set from		 * the peer dispersion; the peer root dispersion is		 * ignored.		 */		dtemp = sys_peer->disp + clock_phi * (current_time -		    sys_peer->update) + sys_jitter +		    fabs(sys_peer->offset);#ifdef REFCLOCK		if (!(sys_peer->flags & FLAG_REFCLOCK) && dtemp <		    sys_mindisp)			dtemp = sys_mindisp;#else		if (dtemp < sys_mindisp)			dtemp = sys_mindisp;#endif /* REFCLOCK */		if (sys_stratum >= sys_orphan) {			sys_stratum = sys_orphan;			sys_rootdelay = sys_peer->delay;			sys_rootdispersion = dtemp;		} else {			sys_rootdelay = sys_peer->delay +			    sys_peer->rootdelay;			sys_rootdispersion = dtemp +			    sys_peer->rootdispersion;		}		if (oleap == LEAP_NOTINSYNC) {			report_event(EVNT_SYNCCHG, NULL);#ifdef OPENSSL			expire_all();			crypto_update();#endif /* OPENSSL */		}		break;	/*

⌨️ 快捷键说明

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