ntp_proto.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,296 行 · 第 1/3 页

C
1,296
字号
#ifndef lintstatic  char    *sccsid = "@(#)ntp_proto.c	4.1  (ULTRIX)        7/2/90";#endif lint/************************************************************************ *                                                                      * *                      Copyright (c) 1988-1990 by			* *              Digital Equipment Corporation, Maynard, MA              * *                      All rights reserved.                            * *                                                                      * *   This software is furnished under a license and may be used and     * *   copied  only  in accordance with the terms of such license and     * *   with the  inclusion  of  the  above  copyright  notice.   This     * *   software  or  any  other copies thereof may not be provided or     * *   otherwise made available to any other person.  No title to and     * *   ownership of the software is hereby transferred.                   * *                                                                      * *   This software is  derived  from  software  received  from  the     * *   University    of   California,   Berkeley,   and   from   Bell     * *   Laboratories.  Use, duplication, or disclosure is  subject  to     * *   restrictions  under  license  agreements  with  University  of     * *   California and with AT&T.                                          * *                                                                      * *   The information in this software is subject to change  without     * *   notice  and should not be construed as a commitment by Digital     * *   Equipment Corporation.                                             * *                                                                      * *   Digital assumes no responsibility for the use  or  reliability     * *   of its software on equipment which is not supplied by Digital.     * *                                                                      * ************************************************************************/ /* *static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp_proto.c,v $ $Revision: 3.4.1.12 $ $Date: 89/05/18 18:25:04 $"; *//* * 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 *//* * $Log:	ntp_proto.c,v $ * Revision 3.4.1.12  89/05/18  18:25:04  louie * Changes for reference clock feature in ntp_proto.c *  * Revision 3.4.1.11  89/05/03  23:51:30  louie * Had my head on backwards with a reversed test in the clockhopper avoidance * code.  Need to switch to the first selected clock when its stratum is lower * than the current sys.peer. *  * Revision 3.4.1.10  89/05/03  19:03:02  louie * Stupid typo - dereferenced unused variable in select_clock() *  * Revision 3.4.1.9  89/05/03  15:13:25  louie * Add code to count number of peer switches and inhibited peer switches.  Clock * selection code has been updated to reflect 21 April 1989 draft of NTP spec. *  * Revision 3.4.1.8  89/04/10  15:57:59  louie * New -l option for ntpd to enable logging for clock adjust messages.  Changed * our idea of a bogus packet in the packet procedure to include a packet received * before a poll is sent.  Fix stupid bug in delay computation having to do with * peer->precision. *  * Revision 3.4.1.7  89/04/08  10:36:53  louie * The syslog message for peer selection had to be moved to account for the * anti-peer flapping code just installed. *  * Revision 3.4.1.6  89/04/07  19:07:10  louie * Don't clear peer.reach register in the clear() procedure.  Code to prevent * flapping between two peers with very similar dispersions. *  * Revision 3.4.1.5  89/03/31  16:36:38  louie * There is now a run-time option that can be specified in the configuration  * which specifies if we will synchronize to unconfigured hosts.  Fixes to * receive() logic state machine. *  * Revision 3.4.1.4  89/03/29  12:29:10  louie * The variable 'mode' in the peer structure was renamed 'hmode'.  Add  * poll_update() calls in a few places per Mills.  The receive() procedure is * now table driven.  The poll_update procedure only randomized the timer * when the interval changes.  If we lose synchronization, don't zap sys.stratum. * Clean up the sanity_check() routine a bit. *  * Revision 3.4.1.3  89/03/22  18:32:31  louie * patch3: Use new RCS headers. *  * Revision 3.4.1.2  89/03/22  18:02:22  louie * Add some fiddles for BROADCAST NTP mode.  In the receive procedure, set the * reachability shift register of peers that are configured, even if we won't * synchronized to them.  Fix adjustment of delay in the process_packet() * routine.  Repair byteswapping problem. *  *  * Revision 3.4.1.1  89/03/20  00:10:06  louie * patch1: sys.refid could have garbage left if the peer we're synchronized to * patch1: is lost. *  * Revision 3.4  89/03/17  18:37:05  louie * Latest test release. *  * Revision 3.3.1.1  89/03/17  18:26:02  louie * Oh my, peer->hpoll wasn't being set in peer_update! *  * Revision 3.3  89/03/15  14:19:49  louie * New baseline for next release. *  * Revision 3.2.1.2  89/03/15  13:54:41  louie * Change use of "%lf" in format strings to use "%f" instead. * poll_update no longer returns a value, due to a change in the transmit * procedure; it is now declared as returning void.  Removed syslog * message "Dropping peer ...".  You still get messages for peers which * were configured when reachability is lost with them.  Clarification of * calling poll_update on sys.peer rather than on the host whose packet * we're processing when sys.peer changes.  poll_update has been updated * including randomizing peer.timer. *  * Revision 3.2.1.1  89/03/10  11:30:33  louie * Remove computation of peer->timer that was present due to a bug in the NTP * spec.  Don't set sys.precision in the NTP protocol initialization; this has * bad side effects with the code that get tick from the kernel and the NTP * config file scanner. *  * Revision 3.2  89/03/07  18:24:54  louie * New version of UNIX NTP daemon based on the 6 March 1989 draft of the new * NTP protocol specification.  This version has a bunch of bugs fixes and * new algorithms which were discussed on the NTP mailing list over the past * few weeks. *  * Revision 3.1.1.1  89/02/15  08:57:34  louie * *** empty log message *** *  *  * Revision 3.1  89/01/30  14:43:10  louie * Second UNIX NTP test release. *  * Revision 3.0  88/12/12  15:59:35  louie * Test release of new UNIX NTP software.  This version should conform to the * revised NTP protocol specification. *  */#include <stdio.h>#include <sys/types.h>#include <sys/param.h>#include <sys/uio.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/resource.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/udp.h>#include <arpa/inet.h>#include <netdb.h>#include <strings.h>#include <errno.h>#include <syslog.h>#include "ntp.h"int peer_switches, peer_sw_inhibited;struct ntp_peer dummy_peer;extern double WayTooBig;extern unsigned long clock_watchdog;#ifdef	DEBUGextern int debug;extern void dump_pkt();#endifextern int trusting, logstats;extern struct sysdata sys;extern struct list peer_list;extern struct ntp_peer *check_peer();extern struct servent *servp;extern char *malloc(), *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(), demobilize();	#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;	pkt->status = sys.leap | NTPVERSION_1 | peer->hmode;	pkt->stratum = sys.stratum;	pkt->ppoll = peer->hpoll;	pkt->precision = (char) sys.precision;	pkt->distance = sys.distance;	pkt->dispersion = sys.dispersion;	pkt->refid = sys.refid;	pkt->reftime = sys.reftime;	pkt->org = peer->org;	pkt->rec = peer->rec;	(void) gettimeofday(&txtv, (struct timezone *) 0);#if	0	if (peer->flags & PEER_FL_AUTHENABLE) {		/* add encryption time into the timestamp */		tstamp(&pkt->xmt, &txtv);		/* call encrypt() procedure */		pkt->keyid = ???;		pkt->mac = ???;	} else {		pkt->mac[0] = pkt->mac[1] = 0;		pkt->keyid = 0;			/* XXX */		tstamp(&pkt->xmt, &txtv);	}#else	tstamp(&pkt->xmt, &txtv);#endif	peer->xmt = pkt->xmt;	if ((peer->flags & (PEER_FL_BCAST|PEER_FL_REFCLOCK)) == 0) {		/* select correct socket to send reply on */		if (sendto(addrs[(peer->sock < 0 ? 0 : peer->sock)].fd,			   (char *) pkt, sizeof(ntpframe),			   0, &peer->src, sizeof(peer->src)) < 0) {			syslog(LOG_ERR, "sendto: %s  %m",			       ntoa(peer->src.sin_addr));			return;		}#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) {			syslog(LOG_INFO, "Lost reachability with %.4s",			       (char *)&peer->refid);#ifdef	DEBUG			if (debug)				printf("Lost reachability with %.4s\n",				       (char *)&peer->refid);#endif		}		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 (sendto(addrs[peer->sock].fd,			   (char *) pkt, sizeof(ntpframe),			   0, &peer->src, sizeof(peer->src)) < 0) {			syslog(LOG_ERR, "bcast sendto: %s  %m",			       ntoa(peer->src.sin_addr));			return;		}#else		return;#endif	}#ifdef	DEBUG	if (debug > 5) {		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) {		syslog(LOG_INFO, "Lost reachability with %s",			       ntoa(peer->src.sin_addr));#ifdef	DEBUG		if (debug)			printf("Lost reachability with %s",			       ntoa(peer->src.sin_addr));#endif	}	if (peer->reach == 0) {		clear(peer);		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(peer->ppoll, MIN(peer->hpoll, NTP_MAXPOLL)),			       NTP_MINPOLL));	if (peer->estdisp > PEER_THRESHOLD)		poll_update(peer, peer->hpoll - 1);	else		poll_update(peer, 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;	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) {		printf("\nFaking packet ");		dump_pkt(&peer->src, pkt, (struct ntp_peer *)NULL);	}#endif	receive((struct sockaddr_in *)peer, pkt, otvp, -1);	return;}#endif REFCLOCK/* 3.4.2. Receive Procedure */voidreceive(dst, pkt, tvp, sock)	struct sockaddr_in *dst;	struct ntpdata *pkt;	struct timeval *tvp;	int sock;{	struct ntp_peer *peer;	int peer_mode;#define	ACT_ERROR	1#define	ACT_RECV	2#define	ACT_XMIT	3#define	ACT_PKT		4	static 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 */	/* 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->sin_port == servp->s_port)			peer_mode = MODE_SYM_ACT;		else			peer_mode = MODE_CLIENT;

⌨️ 快捷键说明

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