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

📄 ntp_proto.c

📁 ftam等标准协议服务器和客户端的源代码。
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef	lintstatic char *rcsid = "$Header: /xtel/isode/isode/others/ntp/RCS/ntp_proto.c,v 9.0 1992/06/16 12:42:48 isode Rel $";#endif/* * This module actually implements the the bulk of the NTP protocol processing. * It contains a minimum of machine and operating system dependencies (or at * least that's the idea).  Setup of UDP sockets, timers, etc is done in the * ntpd.c module, while arithmetic conversion routines are in ntpsubs.c * * Some of this is now factored out as it was too protocol specific. *//* * $Header: /xtel/isode/isode/others/ntp/RCS/ntp_proto.c,v 9.0 1992/06/16 12:42:48 isode Rel $ * * * Based on the ntp 3.4 code - but modified for use with OSI. * * $Log: ntp_proto.c,v $ * Revision 9.0  1992/06/16  12:42:48  isode * Release 8.0 * */#include "ntp.h"int peer_switches, peer_sw_inhibited;struct ntp_peer dummy_peer;extern double WayTooBig;extern unsigned long clock_watchdog;extern LLog	*pgm_log;#ifdef	DEBUGextern int debug;extern void dump_pkt();#endifextern unsigned int servport;extern int trusting, logstats;extern struct sysdata sys;extern struct list peer_list;extern struct ntp_peer *check_peer();extern char *ntoa();extern double drift_comp, compliance;	/* logical clock variables */extern double s_fixed_to_double(), ul_fixed_to_double();extern void make_new_peer(), double_to_s_fixed(), tstamp(), receive ();extern int demobilize();	char actions[5][5] = { /*      Sym Act   Sym Pas    Client     Server     Broadcast  |Host /       */ /*      --------   --------  --------   ---------  ---------  |    / Peer   */ /*                                                            ------------  */	{ACT_PKT,  ACT_PKT,   ACT_RECV,  ACT_XMIT,  ACT_XMIT},	/* Sym Act   */	{ACT_PKT,  ACT_ERROR, ACT_RECV,  ACT_ERROR, ACT_ERROR},	/* Sym Pas   */	{ACT_XMIT, ACT_XMIT,  ACT_ERROR, ACT_XMIT,  ACT_XMIT},	/* Client    */	{ACT_PKT,  ACT_ERROR, ACT_RECV,  ACT_ERROR, ACT_ERROR},	/* Server    */	{ACT_PKT,  ACT_ERROR, ACT_RECV,  ACT_ERROR, ACT_ERROR}};/* Broadcast */#ifdef	REFCLOCKvoid	refclock_input();#endifvoid	process_packet(), clock_update(), clear(), clock_filter(),	receive(), select_clock(), poll_update();/* 3.4. Event Processing *//* 3.4.1. Transmit Procedure */voidtransmit(peer)	struct ntp_peer *peer;{	struct timeval txtv;	static struct ntpdata ntpframe;	struct ntpdata *pkt = &ntpframe;	int i;	if (peer->src.type == AF_OSI) {		(void) transmit_osi (peer);		return;	}	pkt->status = sys.leap | peer->hmode;	VERS2PKT (pkt -> status, peer -> vers);	pkt->stratum = sys.stratum;	pkt->ppoll = peer->hpoll;	pkt->precision = (char) sys.precision;	pkt->distance = sys.distance;	pkt->dispersion = sys.dispersion;	if (peer -> src.type == AF_INET)		pkt->refid = sys.refid.rid_inet;	pkt->reftime = sys.reftime;	pkt->org = peer->org;	pkt->rec = peer->rec;	(void) gettimeofday(&txtv, (struct timezone *) 0);#ifdef notdef	if (peer->flags & PEER_FL_AUTHENABLE &&	    peer -> vers == 2 &&	    authhavekey (peer -> keyid)) {		pkt->keyid = htonl(peer -> keyid);		auth1crypt (peer -> keyid, pkt, LEN_PKT_NOMAC);		tstamp(&pkt->xmt, &txtv);		auth2crypt (peer -> keyid, pkt, LEN_PKT_NOMAC);	} else #endif	{#ifdef notdef/* Not Yet in this version */		pkt->keyid = 0;			/* XXX */#endif		tstamp(&pkt->xmt, &txtv);	}	peer->xmt = pkt->xmt;	if ((peer->flags & (PEER_FL_BCAST|PEER_FL_REFCLOCK)) == 0) {		/* select correct socket to send reply on */		struct intf *ap;		ap = &addrs[peer->sock < 0 ? 0 : peer-> sock];		switch (peer->src.type) {		    case AF_INET:			if (send_inet (ap, (char *)pkt, sizeof (*pkt),				       &peer->src) < 0)				return;			break;		}#ifdef	REFCLOCK	} else if (peer->flags & PEER_FL_REFCLOCK) {		/* Special version of code below, adjusted for refclocks */		peer->pkt_sent++;		i = peer->reach;	/* save a copy */		peer->reach = (peer->reach << 1) & NTP_WINDOW_SHIFT_MASK;		if (i && peer->reach == 0) {			advise (LLOG_NOTICE, NULLCP,				"Lost reachability with %.4s",				peer->refid.rid_string);		}		if (peer->reach == 0)			clear(peer);		if (peer->valid < 2)			peer->valid++;		else {			clock_filter(peer, 0.0, 0.0);	/* call with invalid values */			select_clock();		/* and try to reselect clock */		}		peer->timer = 1<<NTP_MINPOLL;	/* poll refclocks frequently */		refclock_input(peer, pkt);		return;#endif REFCLOCK	} else {#ifdef	BROADCAST_NTP		if (addrs[peer->sock].addr.type == AF_INET) {			if (send_inet (&addrs[peer->sock], pkt, peer) < 0)				return;		}		else			return;#else		return;#endif	}#ifdef	DEBUG	if (debug > 5) {		(void) printf("\nSent ");		dump_pkt(&peer->src, pkt, (struct ntp_peer *)NULL);	}#endif	peer->pkt_sent++;	i = peer->reach;	/* save a copy */	peer->reach = (peer->reach << 1) & NTP_WINDOW_SHIFT_MASK;	if ((peer->reach == 0) && 	    ((peer->flags & PEER_FL_CONFIG) == 0) &&	    (peer != &dummy_peer) && demobilize(&peer_list, peer))		return;	if (i && peer->reach == 0) {		advise (LLOG_NOTICE, NULLCP,			"Lost reachability with %s",			paddr (&peer->src));	}	if (peer->reach == 0) {		clear(peer);		if (peer->src.type == AF_INET)			peer->sock = -1; /* since he fell off the end of the					   earth, don't depend on local address					   any longer */	}	if (peer->valid < 2)		peer->valid++;	else {		clock_filter(peer, 0.0, 0.0);	/* call with invalid values */		select_clock();		/* and try to reselect clock */		if (sys.peer != NULL)			poll_update(sys.peer, NTP_MINPOLL);	}	peer->timer = 1<<(MAX(MIN((int)peer->ppoll, MIN((int)peer->hpoll, NTP_MAXPOLL)),			       NTP_MINPOLL));	if (peer->reach == 0) {		if (peer->backoff == 0)			peer->backoff = BACKOFF_COUNT;		else {			if (peer->backoff == 1)				poll_update (peer, (int)peer->hpoll + 1);			peer->backoff --;		}	}	else if (peer->estdisp > PEER_THRESHOLD)		poll_update(peer, (int)peer->hpoll - 1);	else		poll_update(peer, (int)peer->hpoll + 1);}#ifdef REFCLOCKvoidrefclock_input(peer, pkt)	struct ntpdata *pkt;	struct ntp_peer *peer;{	struct timeval *tvp;	struct timeval *otvp;	if (read_clock(peer->sock, &tvp, &otvp))		return;	tstamp(&pkt->rec, tvp);	pkt->xmt = pkt->rec;	pkt->reftime = pkt->rec;	tstamp(&pkt->org, otvp);	peer->xmt = pkt->org;	pkt->refid = peer->refid.rid_inet;	/* XXX */	pkt->status &= ~ALARM;	pkt->stratum = peer->stratum;	pkt->ppoll = 0xff;	pkt->precision = peer->precision;	double_to_s_fixed(&pkt->distance, 0.0);	double_to_s_fixed(&pkt->dispersion, 0.0);#ifdef	DEBUG	if (debug > 5) {		(void) printf("\nFaking packet ");		dump_pkt(&peer->src, pkt, (struct ntp_peer *)NULL);	}#endif	receive((struct Naddr *)peer, pkt, otvp, -1);	return;}#endif REFCLOCK/* 3.4.2. Receive Procedure */voidreceive(dst, pkt, tvp, sock)	struct Naddr *dst;	struct ntpdata *pkt;	struct timeval *tvp;	int sock;{	struct ntp_peer *peer;	int peer_mode;	/* if we're only going to support NTP Version 2 then this stuff	   isn't necessary, right? */	if ((peer_mode = pkt->status & MODEMASK) == 0 && dst) {		/* packet from an older NTP implementation.  Synthesize the		   correct mode.  The mapping goes like this:		   pkt source port      pkt dst port	Mode		   ---------------	------------	----		   NTP Port		NTP Port	symmetric active		   NTP Port		not NTP Port	server		   not NTP Port		NTP Port	client		   not NTP Port		not NTP Port	<not possible>		   Now, since we only are processing packets with the		   destination being NTP Port, it reduces to the two cases:		   pkt source port      pkt dst port	Mode		   ---------------	------------	----		   NTP Port		NTP Port	symmetric active		   not NTP Port		NTP Port	client		 */		if (dst->inet_ad.sin_port == servport)			peer_mode = MODE_SYM_ACT;		else			peer_mode = MODE_CLIENT;	}	if (peer_mode == MODE_CLIENT) {		/*		 * Special case: Use the dummy peer item that we keep around		 * just for this type of thing		 */		peer = &dummy_peer;		make_new_peer(peer);		peer->src = *dst;		peer->sock = sock;		peer->hmode = MODE_SYM_PAS;		peer->reach = 0;		clear(peer);#ifdef	REFCLOCK	} else if (sock == -1) {		/* we're begin called by refclock_input(), get peer ptr */		peer = (struct ntp_peer *)dst;#endif	} else		peer = check_peer(dst, sock);	if (peer == NULL) {		peer = (struct ntp_peer *) malloc(sizeof(struct ntp_peer));		if (peer == NULL) {			advise (LLOG_EXCEPTIONS, "malloc", "peer");			return;		}		make_new_peer(peer);		peer->src = *dst;		peer->sock = sock;	/* remember which socket we heard 					   this from */		peer->hmode = MODE_SYM_PAS;		peer->reach = 0;		clear(peer);		/*		 *  If we decide to consider any random NTP peer that might		 *  come as a peer we might sync to, then set the PEER_FL_SYNC		 *  flag in the peer structure.		 *		 *  Alternatively, we could change the hmode to MODE_SERVER, 		 *  but then the peer state wouldn't be persistant.		 */		if (trusting)			peer->flags |= PEER_FL_SYNC;		enqueue(&peer_list, peer);	}	/* 	 *  "pre-configured" peers are initially assigned a socket index of	 *  -1, which means we don't know which interface we'll use to talk	 *  to them.  Once the first reply comes back, we'll update the	 *  peer structure	 */	if (peer->sock == -1)		peer->sock = sock;#ifdef	BROADCAST_NTP	/*	 *  Input frame matched a funny broadcast peer;  these peers only	 *  exist to periodically generate broadcasts.  If an input packet	 *  matched, it means that it looked like it *came* from the broadcast	 *  address.  This is clearly bogus.	 */	if (peer->flags & PEER_FL_BCAST) {		TRACE (1, ("receive: input frame for broadcast peer?"));		return;	}#endif	/* BROADCAST_NTP */#if	0	if ((peer->flags & PEER_FL_AUTHENABLE) &&	    pkt->mac) {		/* verify computed crypto-checksum */	}#endif	if (peer_mode < MODE_SYM_ACT || peer_mode > MODE_BROADCAST) {		TRACE (1, ("Bogus peer_mode %d from %s", peer_mode,			   (struct ntp_peer *) dst == peer ?			   "refclock" : paddr (dst)));#ifdef	DEBUG		if (debug > 3) abort();#endif		return;	}	if (peer->hmode < MODE_SYM_ACT || peer->hmode > MODE_BROADCAST) {		advise (LLOG_EXCEPTIONS, NULLCP,			"Bogus hmode %d for peer %s", peer->hmode,			paddr (&peer->src));		abort();	}	peer->backoff = 0;	switch (actions[peer_mode - 1][peer->hmode - 1]) {	case ACT_RECV:		if (!(((peer->flags & PEER_FL_CONFIG) == 0) &&		      STRMCMP((int)pkt->stratum, >, (int)sys.stratum))) {			peer->flags &= ~PEER_FL_SNOOZE;			peer->reach |= 1;			process_packet(dst, pkt, tvp, peer);			break;		}		/* Note fall-through */	case ACT_ERROR:		if (((peer->flags & PEER_FL_CONFIG) == 0) &&		    (peer != &dummy_peer) && demobilize(&peer_list, peer))			break;		break;	case ACT_PKT:		if (!(((peer->flags & PEER_FL_CONFIG) == 0) &&		      STRMCMP((int)pkt->stratum, >, (int)sys.stratum))) {			peer->flags &= ~PEER_FL_SNOOZE;			peer->reach |= 1;			process_packet((struct ntp_peer *) dst == peer ?				       NULL : dst,				       pkt, tvp, peer);			break;		}		/* Note fall-through */	case ACT_XMIT:		process_packet((struct ntp_peer *) dst == peer ? NULL : dst,			       pkt, tvp, peer);		poll_update(peer, (int)peer->ppoll);		transmit(peer);		break;	default:		abort();	}}/* 3.4.3 Packet procedure */voidprocess_packet(dst, pkt, tvp, peer)	struct Naddr *dst;	struct ntpdata *pkt;	struct timeval *tvp;	struct ntp_peer *peer;{	double t1, t2, t3, t4, offset, delay;	short duplicate, bogus;	duplicate = (pkt->xmt.int_part == peer->org.int_part) &&		(pkt->xmt.fraction == peer->org.fraction);	bogus = ((pkt->org.int_part != peer->xmt.int_part) ||		 (pkt->org.fraction != peer->xmt.fraction))		|| (peer->xmt.int_part == 0);	peer->pkt_rcvd++;	peer->leap = pkt->status & LEAPMASK;	peer->vers = PKT2VERS(pkt->status);	peer->stratum = pkt->stratum;	peer->ppoll = pkt->ppoll;	peer->precision = pkt->precision;	peer->distance = pkt->distance;	peer->dispersion = pkt->dispersion;	if (peer->src.type == AF_INET) {		peer->refid.rid_type = peer -> stratum == 1 ?			RID_STRING : RID_INET;		peer->refid.rid_inet = pkt->refid;	}	peer->reftime = pkt->reftime;	peer->org = pkt->xmt;	tstamp(&peer->rec, tvp);	poll_update(peer, (int)peer->hpoll);	/* 	 * may want to do something special here for Broadcast Mode peers to	 * allow these through 	 */	if (bogus || duplicate || 	    (pkt->org.int_part == 0 && pkt->org.fraction == 0) ||	    (pkt->rec.int_part == 0 && pkt->rec.fraction == 0)) {		peer->pkt_dropped++;		TRACE (3, ("process_packet: dropped duplicate or bogus"));		return;	}	/*	 *  Now compute local adjusts 	 */	t1 = ul_fixed_to_double(&pkt->org);	t2 = ul_fixed_to_double(&pkt->rec);	t3 = ul_fixed_to_double(&pkt->xmt);	t4 = ul_fixed_to_double(&peer->rec);	/* 	 * although the delay computation looks different than the one in the	 * specification, it is correct.  Think about it.	 */	delay = (t2 - t1) - (t3 - t4);	offset = ((t2 - t1) + (t3 - t4)) / 2.0;	delay += 1.0/(unsigned long)(1L << -sys.precision)#ifndef	REFCLOCK		+ NTP_MAXSKW;#else		+ (peer->flags&PEER_FL_REFCLOCK) ? NTP_REFMAXSKW : NTP_MAXSKW;#endif	if (peer->precision < 0 && -peer->precision < sizeof(long)*NBBY)		delay += 1.0/(unsigned long)(1L << -peer->precision);	if (delay < 0.0) {		peer->pkt_dropped++;		return;	}#ifndef	REFCLOCK	delay = MAX(delay, NTP_MINDIST);#else	delay = MAX(delay, (peer->flags & PEER_FL_REFCLOCK) ?		    NTP_REFMINDIST : NTP_MINDIST);#endif	peer->valid = 0;	clock_filter(peer, delay, offset);  /* invoke clock filter procedure */	TRACE (1, ("host: %s : %f : %f : %f : %f : %f : %o",		   dst ? paddr (dst) : "refclock",		   delay, offset,		   peer->estdelay, peer->estoffset, peer->estdisp,		   peer->reach));	clock_update(peer);		/* call clock update procedure */}/* 3.4.4 Primary clock procedure *//* *  We don't have a primary clock. * *  TODO: * *  ``When a  primary clock is connected to the host, it is convient to *    incorporate its information into the database as if the clock was *    represented as an ordinary peer.  The clock can be polled once a *    minute or so and the returned timecheck used to produce a new update *    for the logical clock.'' *//* 3.4.5 Clock update procedure */voidclock_update(peer)	struct ntp_peer *peer;{	double temp;	extern int adj_logical();	select_clock();	if (sys.peer != NULL)		poll_update(sys.peer, NTP_MINPOLL);	/*	 * Did we just sync to this peer?

⌨️ 快捷键说明

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