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

📄 ntp_proto.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * ntp_proto.c - NTP version 4 protocol machinery * * ATTENTION: Get approval from Dave Mills on all changes to this file! * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "ntpd.h"#include "ntp_stdlib.h"#include "ntp_unixtime.h"#include "ntp_control.h"#include "ntp_string.h"#include <stdio.h>#if defined(VMS) && defined(VMS_LOCALUNIT)	/*wjm*/#include "ntp_refclock.h"#endif#if defined(__FreeBSD__) && __FreeBSD__ >= 3#include <sys/sysctl.h>#endif/* * This macro defines the authentication state. If x is 1 authentication * is required; othewise it is optional. */#define	AUTH(x, y)	((x) ? (y) == AUTH_OK : (y) == AUTH_OK || \			    (y) == AUTH_NONE)/* * System variables are declared here. See Section 3.2 of the * specification. */u_char	sys_leap;		/* system leap indicator */u_char	sys_stratum;		/* stratum of system */s_char	sys_precision;		/* local clock precision (log2 s) */double	sys_rootdelay;		/* roundtrip delay to primary source */double	sys_rootdispersion;	/* dispersion to primary source */u_int32 sys_refid;		/* source/loop in network byte order */static	double sys_offset;	/* current local clock offset */l_fp	sys_reftime;		/* time we were last updated */struct	peer *sys_peer;		/* our current peer */struct	peer *sys_pps;		/* our PPS peer */struct	peer *sys_prefer;	/* our cherished peer */int	sys_kod;		/* kod credit */int	sys_kod_rate = 2;	/* max kod packets per second */#ifdef OPENSSLu_long	sys_automax;		/* maximum session key lifetime */#endif /* OPENSSL *//* * Nonspecified system state variables. */int	sys_bclient;		/* broadcast client enable */double	sys_bdelay;		/* broadcast client default delay */int	sys_calldelay;		/* modem callup delay (s) */int	sys_authenticate;	/* requre authentication for config */l_fp	sys_authdelay;		/* authentication delay */static	u_long sys_authdly[2];	/* authentication delay shift reg */static	double sys_mindisp = MINDISPERSE; /* min disp increment (s) */static	double sys_maxdist = MAXDISTANCE; /* selection threshold (s) */double	sys_jitter;		/* system jitter (s) */static	int sys_hopper;		/* anticlockhop counter */static	int sys_maxhop = MAXHOP; /* anticlockhop counter threshold */int	leap_next;		/* leap consensus */keyid_t	sys_private;		/* private value for session seed */int	sys_manycastserver;	/* respond to manycast client pkts */int	peer_ntpdate;		/* active peers in ntpdate mode */int	sys_survivors;		/* truest of the truechimers */#ifdef OPENSSLchar	*sys_hostname;		/* gethostname() name */#endif /* OPENSSL *//* * TOS and multicast mapping stuff */int	sys_floor = 0;		/* cluster stratum floor */int	sys_ceiling = STRATUM_UNSPEC; /* cluster stratum ceiling */int	sys_minsane = 1;	/* minimum candidates */int	sys_minclock = NTP_MINCLOCK; /* minimum survivors */int	sys_maxclock = NTP_MAXCLOCK; /* maximum candidates */int	sys_cohort = 0;		/* cohort switch */int	sys_orphan = STRATUM_UNSPEC + 1; /* orphan stratum */double	sys_orphandelay = 0;	/* orphan root delay */int	sys_beacon = BEACON;	/* manycast beacon interval */int	sys_ttlmax;		/* max ttl mapping vector index */u_char	sys_ttl[MAX_TTL];	/* ttl mapping vector *//* * Statistics counters */u_long	sys_stattime;		/* time since reset */u_long	sys_received;		/* packets received */u_long	sys_processed;		/* packets processed */u_long	sys_newversionpkt;	/* current version */u_long	sys_oldversionpkt;	/* recent version */u_long	sys_unknownversion;	/* invalid version */u_long	sys_restricted;		/* access denied */u_long	sys_badlength;		/* bad length or format */u_long	sys_badauth;		/* bad authentication */u_long	sys_limitrejected;	/* rate exceeded */static	double	root_distance	P((struct peer *));static	void	clock_combine	P((struct peer **, int));static	void	peer_xmit	P((struct peer *));static	void	fast_xmit	P((struct recvbuf *, int, keyid_t,				    int));static	void	clock_update	P((void));static	int	default_get_precision	P((void));static	int	peer_unfit	P((struct peer *));/* * transmit - Transmit Procedure. See Section 3.4.2 of the *	specification. */voidtransmit(	struct peer *peer	/* peer structure pointer */	){	int	hpoll;	/*	 * The polling state machine. There are two kinds of machines,	 * those that never expect a reply (broadcast and manycast	 * server modes) and those that do (all other modes). The dance	 * is intricate...	 */	/*	 * Orphan mode is active when enabled and when no servers less	 * than the orphan statum are available. In this mode packets	 * are sent at the orphan stratum. An orphan with no other	 * synchronization source is an orphan parent. It assumes root	 * delay zero and reference ID the loopback address. All others	 * are orphan children with root delay randomized over a 1-s	 * range. The root delay is used by the election algorithm to	 * select the order of synchronization.	 */	hpoll = peer->hpoll;	if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL) {		sys_leap = LEAP_NOWARNING;		sys_stratum = sys_orphan;		sys_refid = htonl(LOOPBACKADR);		sys_rootdelay = 0;		sys_rootdispersion = 0;	}	/*	 * In broadcast mode the poll interval is never changed from	 * minpoll.	 */	if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) {		peer->outdate = current_time;		peer_xmit(peer);		poll_update(peer, hpoll);		return;	}	/*	 * In manycast mode we start with unity ttl. The ttl is	 * increased by one for each poll until either sys_maxclock	 * servers have been found or the maximum ttl is reached. When	 * sys_maxclock servers are found we stop polling until one or	 * more servers have timed out or until less than minpoll	 * associations turn up. In this case additional better servers	 * are dragged in and preempt the existing ones.	 */	if (peer->cast_flags & MDF_ACAST) {		peer->outdate = current_time;		if (peer->unreach > sys_beacon) {			peer->unreach = 0;			peer->ttl = 0;			peer_xmit(peer);		} else if (sys_survivors < sys_minclock ||		    peer_preempt < sys_maxclock) {			if (peer->ttl < sys_ttlmax)				peer->ttl++;			peer_xmit(peer);		}		peer->unreach++;		poll_update(peer, hpoll);		return;	}	/*	 * In unicast modes the dance is much more intricate. It is	 * desigmed to back off whenever possible to minimize network	 * traffic.	 */	if (peer->burst == 0) {		u_char oreach;		/*		 * Update the reachability status. If not heard for		 * three consecutive polls, stuff infinity in the clock		 * filter. 		 */		oreach = peer->reach;		peer->outdate = current_time;		if (peer == sys_peer)			sys_hopper++;		peer->reach <<= 1;		if (!(peer->reach & 0x07))			clock_filter(peer, 0., 0., MAXDISPERSE);		if (!peer->reach) {			/*			 * Here the peer is unreachable. If it was			 * previously reachable, raise a trap.			 */			if (oreach) {				report_event(EVNT_UNREACH, peer);				peer->timereachable = current_time;			}			/*			 * Send a burst if enabled, but only once after			 * a peer becomes unreachable. If the prempt			 * flag is dim, bump the unreach counter by one;			 * otherwise, bump it by three.			 */			if (peer->flags & FLAG_IBURST &&			    peer->unreach == 0) {				peer->burst = NTP_BURST;			}			if (!(peer->flags & FLAG_PREEMPT))					peer->unreach++;			else				peer->unreach += 3;		} else {			/*			 * Here the peer is reachable. Set the poll			 * interval to the system poll interval. Send a			 * burst only if enabled and the peer is fit.			 *			 * Respond to the peer evaluation produced by			 * the selection algorithm. If less than the			 * outlyer level, up the unreach by three. If			 * there are excess associations, up the unreach			 * by two if not a candidate and by one if so.			 */			if (!(peer->flags & FLAG_PREEMPT)) {				peer->unreach = 0;			} else if (peer->status < CTL_PST_SEL_SELCAND) {				peer->unreach += 3;			} else if (peer_preempt > sys_maxclock) {				if (peer->status < CTL_PST_SEL_SYNCCAND)					peer->unreach += 2;				else					peer->unreach++;			} else {				peer->unreach = 0;			}			hpoll = sys_poll;			if (peer->flags & FLAG_BURST &&			    peer_unfit(peer))				peer->burst = NTP_BURST;		}		/*		 * Watch for timeout. If ephemeral or preemptable, toss		 * the rascal; otherwise, bump the poll interval.		 */ 		if (peer->unreach >= NTP_UNREACH) {			if (peer->flags & FLAG_PREEMPT ||			    !(peer->flags & FLAG_CONFIG)) {				peer_clear(peer, "TIME");				unpeer(peer);				return;			} else {				hpoll++;			}		}	} else {		peer->burst--;		/*		 * If a broadcast client at this point, the burst has		 * concluded, so we switch to client mode and purge the		 * keylist, since no further transmissions will be made.		 */		if (peer->burst == 0) {			if (peer->cast_flags & MDF_BCLNT) {				peer->hmode = MODE_BCLIENT;#ifdef OPENSSL				key_expire(peer);#endif /* OPENSSL */			}			/*			 * If ntpdate mode and the clock has not been			 * set and all peers have completed the burst,			 * we declare a successful failure.			 */			if (mode_ntpdate) {				peer_ntpdate--;				if (peer_ntpdate == 0) {					msyslog(LOG_NOTICE,					    "no reply; clock not set");					exit (0);				}			}		}	}	/*	 * Do not transmit if in broadcast client mode. 	 */	if (peer->hmode != MODE_BCLIENT)		peer_xmit(peer);	poll_update(peer, hpoll);}/* * receive - Receive Procedure.  See section 3.4.3 in the specification. */voidreceive(	struct recvbuf *rbufp	){	register struct peer *peer;	/* peer structure pointer */	register struct pkt *pkt;	/* receive packet pointer */	int	hisversion;		/* packet version */	int	hisleap;		/* packet leap indicator */	int	hismode;		/* packet mode */	int	hisstratum;		/* packet stratum */	int	restrict_mask;		/* restrict bits */	int	has_mac;		/* length of MAC field */	int	authlen;		/* offset of MAC field */	int	is_authentic = 0;	/* cryptosum ok */	keyid_t	skeyid = 0;		/* key ID */	struct sockaddr_storage *dstadr_sin; /* active runway */	struct peer *peer2;		/* aux peer structure pointer */	l_fp	p_org;			/* origin timestamp */	l_fp	p_rec;			/* receive timestamp */	l_fp	p_xmt;			/* transmit timestamp */#ifdef OPENSSL	keyid_t tkeyid = 0;		/* temporary key ID */	keyid_t	pkeyid = 0;		/* previous key ID */	struct autokey *ap;		/* autokey structure pointer */	int	rval;			/* cookie snatcher */#endif /* OPENSSL */	int retcode = AM_NOMATCH;	/*	 * Monitor the packet and get restrictions. Note that the packet	 * length for control and private mode packets must be checked	 * by the service routines. Note that no statistics counters are	 * recorded for restrict violations, since these counters are in	 * the restriction routine. Note the careful distinctions here	 * between a packet with a format error and a packet that is	 * simply discarded without prejudice. Some restrictions have to	 * be handled later in order to generate a kiss-of-death packet.	 */	/*	 * Bogus port check is before anything, since it probably	 * reveals a clogging attack.	 */	sys_received++;	if (SRCPORT(&rbufp->recv_srcadr) == 0) {		sys_badlength++;		return;				/* bogus port */	}	ntp_monitor(rbufp);	restrict_mask = restrictions(&rbufp->recv_srcadr);#ifdef DEBUG	if (debug > 1)		printf("receive: at %ld %s<-%s flags %x restrict %03x\n",		    current_time, stoa(&rbufp->dstadr->sin),		    stoa(&rbufp->recv_srcadr),		    rbufp->dstadr->flags, restrict_mask);#endif	if (restrict_mask & RES_IGNORE) {		sys_restricted++;		return;				/* ignore everything */	}	pkt = &rbufp->recv_pkt;	hisversion = PKT_VERSION(pkt->li_vn_mode);	hisleap = PKT_LEAP(pkt->li_vn_mode);	hismode = (int)PKT_MODE(pkt->li_vn_mode);	hisstratum = PKT_TO_STRATUM(pkt->stratum);	if (hismode == MODE_PRIVATE) {		if (restrict_mask & RES_NOQUERY) {			sys_restricted++;			return;			/* no query private */		}		process_private(rbufp, ((restrict_mask &		    RES_NOMODIFY) == 0));		return;	}	if (hismode == MODE_CONTROL) {		if (restrict_mask & RES_NOQUERY) {			sys_restricted++;			return;			/* no query control */		}		process_control(rbufp, restrict_mask);		return;	}	if (restrict_mask & RES_DONTSERVE) {		sys_restricted++;		return;				/* no time */	}	if (rbufp->recv_length < LEN_PKT_NOMAC) {		sys_badlength++;		return;				/* runt packet */	}		/*	 * Version check must be after the query packets, since they	 * intentionally use early version.	 */	if (hisversion == NTP_VERSION) {		sys_newversionpkt++;		/* new version */	} else if (!(restrict_mask & RES_VERSION) && hisversion >=	    NTP_OLDVERSION) {		sys_oldversionpkt++;		/* previous version */	} else {		sys_unknownversion++;		return;				/* old version */	}	/*	 * Figure out his mode and validate the packet. This has some	 * legacy raunch that probably should be removed. In very early	 * NTP versions mode 0 was equivalent to what later versions	 * would interpret as client mode.	 */	if (hismode == MODE_UNSPEC) {		if (hisversion == NTP_OLDVERSION) {			hismode = MODE_CLIENT;		} else {			sys_badlength++;			return;                 /* invalid mode */		}	}	/*	 * Parse the extension field if present. We figure out whether	 * an extension field is present by measuring the MAC size. If	 * the number of words following the packet header is 0, no MAC	 * is present and the packet is not authenticated. If 1, the	 * packet is a crypto-NAK; if 3, the packet is authenticated	 * with DES; if 5, the packet is authenticated with MD5. If 2 or	 * 4, the packet is a runt and discarded forthwith. If greater

⌨️ 快捷键说明

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