ntp_proto.c revision 54359
154359Sroberto/*
254359Sroberto * ntp_proto.c - NTP version 4 protocol machinery
354359Sroberto */
454359Sroberto#ifdef HAVE_CONFIG_H
554359Sroberto#include <config.h>
654359Sroberto#endif
754359Sroberto
854359Sroberto#include <stdio.h>
954359Sroberto#include <sys/types.h>
1054359Sroberto#include <sys/time.h>
1154359Sroberto
1254359Sroberto#include "ntpd.h"
1354359Sroberto#include "ntp_stdlib.h"
1454359Sroberto#include "ntp_unixtime.h"
1554359Sroberto#include "ntp_control.h"
1654359Sroberto#include "ntp_string.h"
1754359Sroberto
1854359Sroberto#if defined(VMS) && defined(VMS_LOCALUNIT)	/*wjm*/
1954359Sroberto#include "ntp_refclock.h"
2054359Sroberto#endif
2154359Sroberto
2254359Sroberto#if defined(__FreeBSD__) && __FreeBSD__ >= 3
2354359Sroberto#include <sys/sysctl.h>
2454359Sroberto#endif
2554359Sroberto
2654359Sroberto/*
2754359Sroberto * System variables are declared here.	See Section 3.2 of the
2854359Sroberto * specification.
2954359Sroberto */
3054359Srobertou_char	sys_leap;		/* system leap indicator */
3154359Srobertou_char	sys_stratum;		/* stratum of system */
3254359Srobertos_char	sys_precision;		/* local clock precision */
3354359Srobertodouble	sys_rootdelay;		/* distance to current sync source */
3454359Srobertodouble	sys_rootdispersion;	/* dispersion of system clock */
3554359Srobertou_int32 sys_refid;		/* reference source for local clock */
3654359Srobertostatic	double sys_offset;	/* current local clock offset */
3754359Srobertol_fp	sys_reftime;		/* time we were last updated */
3854359Srobertostruct	peer *sys_peer; 	/* our current peer */
3954359Srobertou_long	sys_automax;		/* maximum session key lifetime */
4054359Sroberto
4154359Sroberto/*
4254359Sroberto * Nonspecified system state variables.
4354359Sroberto */
4454359Srobertoint	sys_bclient;		/* we set our time to broadcasts */
4554359Srobertodouble	sys_bdelay; 		/* broadcast client default delay */
4654359Srobertoint	sys_authenticate;	/* requre authentication for config */
4754359Srobertol_fp	sys_authdelay;		/* authentication delay */
4854359Srobertostatic	u_long sys_authdly[2]; 	/* authentication delay shift reg */
4954359Srobertostatic	u_char leap_consensus;	/* consensus of survivor leap bits */
5054359Srobertostatic	double sys_maxd; 	/* select error (squares) */
5154359Srobertostatic	double sys_epsil;	/* system error (squares) */
5254359Srobertou_long	sys_private;		/* private value for session seed */
5354359Srobertoint	sys_manycastserver;	/* 1 => respond to manycast client pkts */
5454359Sroberto
5554359Sroberto/*
5654359Sroberto * Statistics counters
5754359Sroberto */
5854359Srobertou_long	sys_stattime;		/* time when we started recording */
5954359Srobertou_long	sys_badstratum; 	/* packets with invalid stratum */
6054359Srobertou_long	sys_oldversionpkt;	/* old version packets received */
6154359Srobertou_long	sys_newversionpkt;	/* new version packets received */
6254359Srobertou_long	sys_unknownversion;	/* don't know version packets */
6354359Srobertou_long	sys_badlength;		/* packets with bad length */
6454359Srobertou_long	sys_processed;		/* packets processed */
6554359Srobertou_long	sys_badauth;		/* packets dropped because of auth */
6654359Srobertou_long	sys_limitrejected;	/* pkts rejected due to client count per net */
6754359Sroberto
6854359Srobertostatic	double	root_distance	P((struct peer *));
6954359Srobertostatic	double	clock_combine	P((struct peer **, int));
7054359Srobertostatic	void	peer_xmit	P((struct peer *));
7154359Srobertostatic	void	fast_xmit	P((struct recvbuf *, int, u_long));
7254359Srobertostatic	void	clock_update	P((void));
7354359Sroberto#ifdef MD5
7454359Srobertostatic	void	make_keylist	P((struct peer *));
7554359Sroberto#endif /* MD5 */
7654359Sroberto
7754359Sroberto/*
7854359Sroberto * transmit - Transmit Procedure. See Section 3.4.2 of the
7954359Sroberto *	specification.
8054359Sroberto */
8154359Srobertovoid
8254359Srobertotransmit(
8354359Sroberto	struct peer *peer	/* peer structure pointer */
8454359Sroberto	)
8554359Sroberto{
8654359Sroberto	int hpoll;
8754359Sroberto
8854359Sroberto	hpoll = peer->hpoll;
8954359Sroberto	if (peer->burst == 0) {
9054359Sroberto		u_char oreach;
9154359Sroberto
9254359Sroberto		/*
9354359Sroberto		 * Determine reachability and diddle things if we
9454359Sroberto		 * haven't heard from the host for a while. If the peer
9554359Sroberto		 * is not configured and not likely to stay around,
9654359Sroberto		 * we exhaust it.
9754359Sroberto		 */
9854359Sroberto		oreach = peer->reach;
9954359Sroberto		if (oreach & 0x01)
10054359Sroberto			peer->valid++;
10154359Sroberto		if (oreach & 0x80)
10254359Sroberto			peer->valid--;
10354359Sroberto		if (!(peer->flags & FLAG_CONFIG) &&
10454359Sroberto		    peer->valid > NTP_SHIFT / 2 && (peer->reach & 0x80) &&
10554359Sroberto		    peer->status < CTL_PST_SEL_SYNCCAND)
10654359Sroberto			peer->reach = 0;
10754359Sroberto		peer->reach <<= 1;
10854359Sroberto		if (peer->reach == 0) {
10954359Sroberto
11054359Sroberto			/*
11154359Sroberto			 * If this is an uncofigured association and
11254359Sroberto			 * has become unreachable, demobilize it.
11354359Sroberto			 */
11454359Sroberto			if (oreach != 0) {
11554359Sroberto				report_event(EVNT_UNREACH, peer);
11654359Sroberto				peer->timereachable = current_time;
11754359Sroberto				peer_clear(peer);
11854359Sroberto				if (!(peer->flags & FLAG_CONFIG)) {
11954359Sroberto					unpeer(peer);
12054359Sroberto					return;
12154359Sroberto				}
12254359Sroberto			}
12354359Sroberto
12454359Sroberto			/*
12554359Sroberto			 * We would like to respond quickly when the
12654359Sroberto			 * peer comes back to life. If the probes since
12754359Sroberto			 * becoming unreachable are less than
12854359Sroberto			 * NTP_UNREACH, clamp the poll interval to the
12954359Sroberto			 * minimum. In order to minimize the network
13054359Sroberto			 * traffic, the interval gradually ramps up the
13154359Sroberto			 * the maximum after that.
13254359Sroberto			 */
13354359Sroberto			peer->ppoll = peer->maxpoll;
13454359Sroberto			if (peer->unreach < NTP_UNREACH) {
13554359Sroberto				if (peer->hmode == MODE_CLIENT)
13654359Sroberto					peer->unreach++;
13754359Sroberto				hpoll = peer->minpoll;
13854359Sroberto			} else {
13954359Sroberto				hpoll++;
14054359Sroberto			}
14154359Sroberto			if (peer->flags & FLAG_BURST)
14254359Sroberto				peer->burst = 2;
14354359Sroberto
14454359Sroberto		} else {
14554359Sroberto
14654359Sroberto			/*
14754359Sroberto			 * Here the peer is reachable. If there is no
14854359Sroberto			 * system peer or if the stratum of the system
14954359Sroberto			 * peer is greater than this peer, clamp the
15054359Sroberto			 * poll interval to the minimum. If less than
15154359Sroberto			 * two samples are in the reachability register,
15254359Sroberto			 * reduce the interval; if more than six samples
15354359Sroberto			 * are in the register, increase the interval.
15454359Sroberto			 */
15554359Sroberto			peer->unreach = 0;
15654359Sroberto			if (sys_peer == 0)
15754359Sroberto				hpoll = peer->minpoll;
15854359Sroberto			else if (sys_peer->stratum > peer->stratum)
15954359Sroberto				hpoll = peer->minpoll;
16054359Sroberto			if ((peer->reach & 0x03) == 0) {
16154359Sroberto				clock_filter(peer, 0., 0., MAXDISPERSE);
16254359Sroberto				clock_select();
16354359Sroberto			}
16454359Sroberto			if (peer->valid <= 2)
16554359Sroberto				hpoll--;
16654359Sroberto			else if (peer->valid >= NTP_SHIFT - 2)
16754359Sroberto				hpoll++;
16854359Sroberto			if (peer->flags & FLAG_BURST)
16954359Sroberto				peer->burst = NTP_SHIFT;
17054359Sroberto		}
17154359Sroberto	} else {
17254359Sroberto		peer->burst--;
17354359Sroberto		if (peer->burst == 0) {
17454359Sroberto			if (peer->flags & FLAG_MCAST2) {
17554359Sroberto				peer->flags &= ~FLAG_BURST;
17654359Sroberto				peer->hmode = MODE_BCLIENT;
17754359Sroberto			}
17854359Sroberto			clock_select();
17954359Sroberto			poll_update(peer, hpoll);
18054359Sroberto			return;
18154359Sroberto		}
18254359Sroberto	}
18354359Sroberto
18454359Sroberto	/*
18554359Sroberto	 * We need to be very careful about honking uncivilized time. If
18654359Sroberto	 * not operating in broadcast mode, honk in all except broadcast
18754359Sroberto	 * client mode. If operating in broadcast mode and synchronized
18854359Sroberto	 * to a real source, honk except when the peer is the local-
18954359Sroberto	 * clock driver and the prefer flag is not set. In other words,
19054359Sroberto	 * in broadcast mode we never honk unless known to be
19154359Sroberto	 * synchronized to real time.
19254359Sroberto	 */
19354359Sroberto	if (peer->hmode != MODE_BROADCAST) {
19454359Sroberto		if (peer->hmode != MODE_BCLIENT)
19554359Sroberto			peer_xmit(peer);
19654359Sroberto	} else if (sys_peer != 0 && sys_leap != LEAP_NOTINSYNC) {
19754359Sroberto		if (!(sys_peer->refclktype == REFCLK_LOCALCLOCK &&
19854359Sroberto		    !(sys_peer->flags & FLAG_PREFER)))
19954359Sroberto			peer_xmit(peer);
20054359Sroberto	}
20154359Sroberto	peer->outdate = current_time;
20254359Sroberto	poll_update(peer, hpoll);
20354359Sroberto}
20454359Sroberto
20554359Sroberto/*
20654359Sroberto * receive - Receive Procedure.  See section 3.4.3 in the specification.
20754359Sroberto */
20854359Srobertovoid
20954359Srobertoreceive(
21054359Sroberto	struct recvbuf *rbufp
21154359Sroberto	)
21254359Sroberto{
21354359Sroberto	register struct peer *peer;
21454359Sroberto	register struct pkt *pkt;
21554359Sroberto	int hismode;
21654359Sroberto	int oflags;
21754359Sroberto	int restrict_mask;
21854359Sroberto	int has_mac;			/* has MAC field */
21954359Sroberto	int authlen;			/* length of MAC field */
22054359Sroberto	int is_authentic;		/* cryptosum ok */
22154359Sroberto	int is_mystic;			/* session key exists */
22254359Sroberto	int is_error;			/* parse error */
22354359Sroberto/*	u_long pkeyid; */
22454359Sroberto	u_long skeyid, tkeyid;
22554359Sroberto	struct peer *peer2;
22654359Sroberto	int retcode = AM_NOMATCH;
22754359Sroberto
22854359Sroberto	/*
22954359Sroberto	 * Monitor the packet and get restrictions
23054359Sroberto	 */
23154359Sroberto	ntp_monitor(rbufp);
23254359Sroberto	restrict_mask = restrictions(&rbufp->recv_srcadr);
23354359Sroberto#ifdef DEBUG
23454359Sroberto	if (debug > 1)
23554359Sroberto		printf("receive: from %s restrict %02x\n",
23654359Sroberto		    ntoa(&rbufp->recv_srcadr), restrict_mask);
23754359Sroberto#endif
23854359Sroberto	if (restrict_mask & RES_IGNORE)
23954359Sroberto		return;
24054359Sroberto
24154359Sroberto	/*
24254359Sroberto	 * Discard packets with invalid version number.
24354359Sroberto	 */
24454359Sroberto	pkt = &rbufp->recv_pkt;
24554359Sroberto	if (PKT_VERSION(pkt->li_vn_mode) >= NTP_VERSION)
24654359Sroberto		sys_newversionpkt++;
24754359Sroberto	else if (PKT_VERSION(pkt->li_vn_mode) >= NTP_OLDVERSION)
24854359Sroberto		sys_oldversionpkt++;
24954359Sroberto	else {
25054359Sroberto		sys_unknownversion++;
25154359Sroberto		return;
25254359Sroberto	}
25354359Sroberto
25454359Sroberto	/*
25554359Sroberto	 * Restrict control/private mode packets. Note that packet
25654359Sroberto	 * length has to be checked in the control/private mode protocol
25754359Sroberto	 * module.
25854359Sroberto	 */
25954359Sroberto	if (PKT_MODE(pkt->li_vn_mode) == MODE_PRIVATE) {
26054359Sroberto		if (restrict_mask & RES_NOQUERY)
26154359Sroberto		    return;
26254359Sroberto		process_private(rbufp, ((restrict_mask & RES_NOMODIFY) ==
26354359Sroberto		    0));
26454359Sroberto		return;
26554359Sroberto	}
26654359Sroberto	if (PKT_MODE(pkt->li_vn_mode) == MODE_CONTROL) {
26754359Sroberto		if (restrict_mask & RES_NOQUERY)
26854359Sroberto		    return;
26954359Sroberto		process_control(rbufp, restrict_mask);
27054359Sroberto		return;
27154359Sroberto	}
27254359Sroberto
27354359Sroberto	/*
27454359Sroberto	 * Restrict revenue packets.
27554359Sroberto	 */
27654359Sroberto	if (restrict_mask & RES_DONTSERVE)
27754359Sroberto		return;
27854359Sroberto
27954359Sroberto        /*
28054359Sroberto	 * See if we only accept limited number of clients from the net
28154359Sroberto	 * this guy is from. Note: the flag is determined dynamically
28254359Sroberto	 * within restrictions()
28354359Sroberto	 */
28454359Sroberto	if (restrict_mask & RES_LIMITED) {
28554359Sroberto		sys_limitrejected++;
28654359Sroberto                return;
28754359Sroberto        }
28854359Sroberto
28954359Sroberto	/*
29054359Sroberto	 * If we are not a broadcast client, ignore broadcast packets.
29154359Sroberto	 */
29254359Sroberto	if ((PKT_MODE(pkt->li_vn_mode) == MODE_BROADCAST && !sys_bclient))
29354359Sroberto		return;
29454359Sroberto
29554359Sroberto	/*
29654359Sroberto	 * This is really awful ugly. We figure out whether an extension
29754359Sroberto	 * field is present and then measure the MAC size. If the number
29854359Sroberto	 * of words following the packet header is less than or equal to
29954359Sroberto	 * 5, no extension field is present and these words constitute the
30054359Sroberto	 * MAC. If the number of words is greater than 5, an extension
30154359Sroberto	 * field is present and the first word contains the length of
30254359Sroberto	 * the extension field and the MAC follows that.
30354359Sroberto	 */
30454359Sroberto	has_mac = 0;
30554359Sroberto/*	pkeyid = 0; */
30654359Sroberto	skeyid = tkeyid = 0;
30754359Sroberto	authlen = LEN_PKT_NOMAC;
30854359Sroberto	has_mac = rbufp->recv_length - authlen;
30954359Sroberto	if (has_mac <= 5 * sizeof(u_int32)) {
31054359Sroberto		skeyid = (u_long)ntohl(pkt->keyid1) & 0xffffffff;
31154359Sroberto	} else {
31254359Sroberto		authlen += (u_long)ntohl(pkt->keyid1) & 0xffffffff;
31354359Sroberto		has_mac = rbufp->recv_length - authlen;
31454359Sroberto		if (authlen <= 0) {
31554359Sroberto			sys_badlength++;
31654359Sroberto			return;
31754359Sroberto		}
31854359Sroberto
31954359Sroberto		/*
32054359Sroberto		 * Note that keyid3 is actually the key ident of the
32154359Sroberto		 * MAC itself.
32254359Sroberto		 */
32354359Sroberto/* 		pkeyid = (u_long)ntohl(pkt->keyid2) & 0xffffffff; */
32454359Sroberto		skeyid = tkeyid = (u_long)ntohl(pkt->keyid3) & 0xffffffff;
32554359Sroberto	}
32654359Sroberto
32754359Sroberto	/*
32854359Sroberto	 * Figure out his mode and validate it.
32954359Sroberto	 */
33054359Sroberto	hismode = (int)PKT_MODE(pkt->li_vn_mode);
33154359Sroberto	if (PKT_VERSION(pkt->li_vn_mode) == NTP_OLDVERSION && hismode ==
33254359Sroberto		0) {
33354359Sroberto		/*
33454359Sroberto		 * Easy.  If it is from the NTP port it is
33554359Sroberto		 * a sym act, else client.
33654359Sroberto		 */
33754359Sroberto		if (SRCPORT(&rbufp->recv_srcadr) == NTP_PORT)
33854359Sroberto			hismode = MODE_ACTIVE;
33954359Sroberto		else
34054359Sroberto			hismode = MODE_CLIENT;
34154359Sroberto	} else {
34254359Sroberto		if (hismode != MODE_ACTIVE && hismode != MODE_PASSIVE &&
34354359Sroberto			hismode != MODE_SERVER && hismode != MODE_CLIENT &&
34454359Sroberto			hismode != MODE_BROADCAST)
34554359Sroberto			return;
34654359Sroberto	}
34754359Sroberto
34854359Sroberto	/*
34954359Sroberto	 * If he included a mac field, decrypt it to see if it is
35054359Sroberto	 * authentic.
35154359Sroberto	 */
35254359Sroberto	is_authentic = is_mystic = 0;
35354359Sroberto	if (has_mac == 0) {
35454359Sroberto#ifdef DEBUG
35554359Sroberto		if (debug)
35654359Sroberto			printf("receive: at %ld from %s mode %d\n",
35754359Sroberto				current_time, ntoa(&rbufp->recv_srcadr),
35854359Sroberto				hismode);
35954359Sroberto#endif
36054359Sroberto	} else {
36154359Sroberto		is_mystic = authistrusted(skeyid);
36254359Sroberto#ifdef MD5
36354359Sroberto		if (skeyid > NTP_MAXKEY && !is_mystic) {
36454359Sroberto
36554359Sroberto			/*
36654359Sroberto			 * For multicast mode, generate the session key
36754359Sroberto			 * and install in the key cache. For client mode,
36854359Sroberto			 * generate the session key for the unicast
36954359Sroberto			 * address. For server mode, the session key should
37054359Sroberto			 * already be in the key cache, since it was
37154359Sroberto			 * generated when the last request was sent.
37254359Sroberto			 */
37354359Sroberto			if (hismode == MODE_BROADCAST) {
37454359Sroberto				tkeyid = session_key(
37554359Sroberto					ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr),
37654359Sroberto					ntohl(rbufp->dstadr->bcast.sin_addr.s_addr),
37754359Sroberto					skeyid, (u_long)(4 * (1 << pkt->ppoll)));
37854359Sroberto			} else if (hismode != MODE_SERVER) {
37954359Sroberto				tkeyid = session_key(
38054359Sroberto					ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr),
38154359Sroberto					ntohl(rbufp->dstadr->sin.sin_addr.s_addr),
38254359Sroberto					skeyid, (u_long)(4 * (1 << pkt->ppoll)));
38354359Sroberto			}
38454359Sroberto
38554359Sroberto		}
38654359Sroberto#endif /* MD5 */
38754359Sroberto
38854359Sroberto		/*
38954359Sroberto		 * Compute the cryptosum. Note a clogging attack may
39054359Sroberto		 * succceed in bloating the key cache.
39154359Sroberto		 */
39254359Sroberto		if (authdecrypt(skeyid, (u_int32 *)pkt, authlen, has_mac))
39354359Sroberto			is_authentic = 1;
39454359Sroberto		else
39554359Sroberto			sys_badauth++;
39654359Sroberto#ifdef DEBUG
39754359Sroberto		if (debug)
39854359Sroberto			printf(
39954359Sroberto				"receive: at %ld %s mode %d keyid %08lx mac %d auth %d\n",
40054359Sroberto				current_time, ntoa(&rbufp->recv_srcadr),
40154359Sroberto				hismode, skeyid, has_mac, is_authentic);
40254359Sroberto#endif
40354359Sroberto	}
40454359Sroberto
40554359Sroberto	/*
40654359Sroberto	 * Find the peer.  This will return a null if this guy isn't in
40754359Sroberto	 * the database.
40854359Sroberto	 */
40954359Sroberto	peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, rbufp->fd,
41054359Sroberto		hismode, &retcode);
41154359Sroberto	/*
41254359Sroberto	 * The new association matching rules are driven by a table specified
41354359Sroberto	 * in ntp.h.  We have replaced the *default* behaviour of replying
41454359Sroberto	 * to bogus packets in server mode in this version.
41554359Sroberto	 * A packet must now match an association in order to be processed.
41654359Sroberto	 * In the event that no association exists, then an association is
41754359Sroberto	 * mobilized if need be.  Two different associations can be mobilized
41854359Sroberto	 *   a) passive associations
41954359Sroberto	 *   b) client associations due to broadcasts or manycasts.
42054359Sroberto	 */
42154359Sroberto	is_error = 0;
42254359Sroberto	switch (retcode) {
42354359Sroberto	case AM_FXMIT:
42454359Sroberto	    /*
42554359Sroberto	     * If the client is configured purely as a broadcast client and
42654359Sroberto	     * not as an manycast server, it has no business being a server.
42754359Sroberto	     * Simply go home. Otherwise, send a MODE_SERVER response and go
42854359Sroberto	     * home. Note that we don't do a authentication check here,
42954359Sroberto	     * since we can't set the system clock; but, we do set the
43054359Sroberto	     * key ID to zero to tell the caller about this.
43154359Sroberto	     */
43254359Sroberto	    if (!sys_bclient || sys_manycastserver) {
43354359Sroberto		    if (is_authentic)
43454359Sroberto			    fast_xmit(rbufp, MODE_SERVER, skeyid);
43554359Sroberto		    else
43654359Sroberto			    fast_xmit(rbufp, MODE_SERVER, 0);
43754359Sroberto	    }
43854359Sroberto
43954359Sroberto	    /*
44054359Sroberto	     * We can't get here if an association is mobilized, so just
44154359Sroberto	     * toss the key, if appropriate.
44254359Sroberto	     */
44354359Sroberto	    if (!is_mystic && skeyid > NTP_MAXKEY)
44454359Sroberto		    authtrust(skeyid, 0);
44554359Sroberto	    return;
44654359Sroberto
44754359Sroberto	case AM_MANYCAST:
44854359Sroberto	    /*
44954359Sroberto	     * This could be in response to a multicast packet sent by
45054359Sroberto	     * the "manycast" mode association. Find peer based on the
45154359Sroberto	     * originate timestamp in the packet. Note that we don't
45254359Sroberto	     * mobilize a new association, unless the packet is properly
45354359Sroberto	     * authenticated. The response must be properly authenticated
45454359Sroberto	     * and it's darn funny of the manycaster isn't around now.
45554359Sroberto	     */
45654359Sroberto	    if ((sys_authenticate && !is_authentic)) {
45754359Sroberto		    is_error = 1;
45854359Sroberto		    break;
45954359Sroberto	    }
46054359Sroberto	    peer2 = (struct peer *)findmanycastpeer(&pkt->org);
46154359Sroberto	    if (peer2 == 0) {
46254359Sroberto		    is_error = 1;
46354359Sroberto		    break;
46454359Sroberto	    }
46554359Sroberto
46654359Sroberto	    /*
46754359Sroberto	     * Create a new association and copy the peer variables to it.
46854359Sroberto	     * If something goes wrong, carefully pry the new association
46954359Sroberto	     * away and return its marbles to the candy store.
47054359Sroberto	     */
47154359Sroberto	    peer = newpeer(&rbufp->recv_srcadr,
47254359Sroberto		rbufp->dstadr, MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
47354359Sroberto		NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid);
47454359Sroberto	    if (peer == 0) {
47554359Sroberto		    is_error = 1;
47654359Sroberto		    break;
47754359Sroberto	    }
47854359Sroberto	    peer_config_manycast(peer2, peer);
47954359Sroberto	    break;
48054359Sroberto
48154359Sroberto	case AM_ERR:
48254359Sroberto	    /*
48354359Sroberto	     * Something bad happened. Dirty floor will be mopped by the
48454359Sroberto	     * code at the end of this adventure.
48554359Sroberto	     */
48654359Sroberto	    is_error = 1;
48754359Sroberto	    break;
48854359Sroberto
48954359Sroberto	case AM_NEWPASS:
49054359Sroberto	    /*
49154359Sroberto	     * Okay, we're going to keep him around.  Allocate him some
49254359Sroberto	     * memory. But, don't do that unless the packet is properly
49354359Sroberto	     * authenticated.
49454359Sroberto             */
49554359Sroberto	    if ((sys_authenticate && !is_authentic)) {
49654359Sroberto		    is_error = 1;
49754359Sroberto	    	    break;
49854359Sroberto	    }
49954359Sroberto	    peer = newpeer(&rbufp->recv_srcadr,
50054359Sroberto		rbufp->dstadr, MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode),
50154359Sroberto	 	NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid);
50254359Sroberto	    break;
50354359Sroberto
50454359Sroberto	case AM_NEWBCL:
50554359Sroberto	    /*
50654359Sroberto             * Broadcast client being set up now. Do this only if the
50754359Sroberto	     * packet is properly authenticated.
50854359Sroberto             */
50954359Sroberto	    if ((restrict_mask & RES_NOPEER) || !sys_bclient ||
51054359Sroberto		(sys_authenticate && !is_authentic)) {
51154359Sroberto		    is_error = 1;
51254359Sroberto		    break;
51354359Sroberto	    }
51454359Sroberto	    peer = newpeer(&rbufp->recv_srcadr,
51554359Sroberto		rbufp->dstadr, MODE_MCLIENT, PKT_VERSION(pkt->li_vn_mode),
51654359Sroberto		NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid);
51754359Sroberto	    if (peer == 0)
51854359Sroberto		    break;
51954359Sroberto	    peer->flags |= FLAG_MCAST1 | FLAG_MCAST2 | FLAG_BURST;
52054359Sroberto	    peer->hmode = MODE_CLIENT;
52154359Sroberto	    break;
52254359Sroberto
52354359Sroberto	case AM_POSSBCL:
52454359Sroberto	case AM_PROCPKT:
52554359Sroberto	    /*
52654359Sroberto             * It seems like it is okay to process the packet now
52754359Sroberto             */
52854359Sroberto	     break;
52954359Sroberto
53054359Sroberto	default:
53154359Sroberto	    /*
53254359Sroberto	     * shouldn't be getting here, but simply return anyway!
53354359Sroberto	     */
53454359Sroberto	    is_error = 1;
53554359Sroberto	}
53654359Sroberto	if (is_error) {
53754359Sroberto
53854359Sroberto		/*
53954359Sroberto		 * Error stub. If we get here, something broke. We scuttle
54054359Sroberto		 * the autokey if necessary and sink the ship. This can
54154359Sroberto		 * occur only upon mobilization, so we can throw the
54254359Sroberto		 * structure away without fear of breaking anything.
54354359Sroberto		 */
54454359Sroberto		if (!is_mystic && skeyid > NTP_MAXKEY)
54554359Sroberto			authtrust(skeyid, 0);
54654359Sroberto		if (peer != 0)
54754359Sroberto			if (!(peer->flags & FLAG_CONFIG))
54854359Sroberto				unpeer(peer);
54954359Sroberto#ifdef DEBUG
55054359Sroberto		if (debug)
55154359Sroberto			printf("match error code %d assoc %d\n", retcode,
55254359Sroberto			    peer_associations);
55354359Sroberto#endif
55454359Sroberto		return;
55554359Sroberto	}
55654359Sroberto
55754359Sroberto	/*
55854359Sroberto	 * If the peer isn't configured, set his keyid and authenable
55954359Sroberto	 * status based on the packet.
56054359Sroberto	 */
56154359Sroberto	oflags = peer->flags;
56254359Sroberto	peer->timereceived = current_time;
56354359Sroberto	if (!(peer->flags & FLAG_CONFIG) && has_mac) {
56454359Sroberto		peer->flags |= FLAG_AUTHENABLE;
56554359Sroberto		if (skeyid > NTP_MAXKEY) {
56654359Sroberto			if (peer->flags & FLAG_MCAST2)
56754359Sroberto				peer->keyid = skeyid;
56854359Sroberto			else
56954359Sroberto				peer->flags |= FLAG_SKEY;
57054359Sroberto		}
57154359Sroberto	}
57254359Sroberto
57354359Sroberto	/*
57454359Sroberto	 * Determine if this guy is basically trustable. If not, flush
57554359Sroberto	 * the bugger. If this is the first packet that is authenticated,
57654359Sroberto	 * flush the clock filter. This is to foil clogging attacks that
57754359Sroberto	 * might starve the poor dear.
57854359Sroberto	 */
57954359Sroberto	peer->flash = 0;
58054359Sroberto	if (is_authentic)
58154359Sroberto		peer->flags |= FLAG_AUTHENTIC;
58254359Sroberto	else
58354359Sroberto		peer->flags &= ~FLAG_AUTHENTIC;
58454359Sroberto	if (peer->hmode == MODE_BROADCAST && (restrict_mask & RES_DONTTRUST))
58554359Sroberto		peer->flash |= TEST10;		/* access denied */
58654359Sroberto	if (peer->flags & FLAG_AUTHENABLE) {
58754359Sroberto		if (!(peer->flags & FLAG_AUTHENTIC))
58854359Sroberto			peer->flash |= TEST5;	/* authentication failed */
58954359Sroberto		else if (skeyid == 0)
59054359Sroberto			peer->flash |= TEST9;	/* peer not authenticated */
59154359Sroberto		else if (!(oflags & FLAG_AUTHENABLE)) {
59254359Sroberto			peer_clear(peer);
59354359Sroberto			report_event(EVNT_PEERAUTH, peer);
59454359Sroberto		}
59554359Sroberto	}
59654359Sroberto	if ((peer->flash & ~(u_int)TEST9) != 0) {
59754359Sroberto
59854359Sroberto		/*
59954359Sroberto		 * The packet is bogus, so we throw it away before becoming
60054359Sroberto		 * a denial-of-service hazard. We don't throw the current
60154359Sroberto		 * association away if it is configured or if it has prior
60254359Sroberto		 * reachable friends.
60354359Sroberto		 */
60454359Sroberto		if (!is_mystic && skeyid > NTP_MAXKEY)
60554359Sroberto			authtrust(skeyid, 0);
60654359Sroberto		if (!(peer->flags & FLAG_CONFIG) && peer->reach == 0)
60754359Sroberto			unpeer(peer);
60854359Sroberto#ifdef DEBUG
60954359Sroberto		if (debug)
61054359Sroberto			printf(
61154359Sroberto			    "invalid packet 0x%02x code %d assoc %d\n",
61254359Sroberto			    peer->flash, retcode, peer_associations);
61354359Sroberto#endif
61454359Sroberto		return;
61554359Sroberto	}
61654359Sroberto
61754359Sroberto#ifdef MD5
61854359Sroberto	/*
61954359Sroberto	 * The autokey dance. The cha-cha requires that the hash of the
62054359Sroberto	 * current session key matches the previous key identifier. Heaps
62154359Sroberto	 * of trouble if the steps falter.
62254359Sroberto	 */
62354359Sroberto	if (skeyid > NTP_MAXKEY) {
62454359Sroberto		int i;
62554359Sroberto
62654359Sroberto		/*
62754359Sroberto		 * In the case of a new autokey, verify the hash matches
62854359Sroberto		 * one of the previous four hashes. If not, raise the
62954359Sroberto		 * authentication flasher and hope the next one works.
63054359Sroberto		 */
63154359Sroberto		if (hismode == MODE_SERVER) {
63254359Sroberto			peer->pkeyid = peer->keyid;
63354359Sroberto		} else if (peer->flags & FLAG_MCAST2) {
63454359Sroberto			if (peer->pkeyid > NTP_MAXKEY)
63554359Sroberto				authtrust(peer->pkeyid, 0);
63654359Sroberto			for (i = 0; i < 4 && tkeyid != peer->pkeyid; i++) {
63754359Sroberto				tkeyid = session_key(
63854359Sroberto					ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr),
63954359Sroberto					ntohl(rbufp->dstadr->bcast.sin_addr.s_addr),
64054359Sroberto					tkeyid, 0);
64154359Sroberto			}
64254359Sroberto		} else {
64354359Sroberto			if (peer->pkeyid > NTP_MAXKEY)
64454359Sroberto				authtrust(peer->pkeyid, 0);
64554359Sroberto			for (i = 0; i < 4 && tkeyid != peer->pkeyid; i++) {
64654359Sroberto				tkeyid = session_key(
64754359Sroberto				    ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr),
64854359Sroberto				    ntohl(rbufp->dstadr->sin.sin_addr.s_addr),
64954359Sroberto				    tkeyid, 0);
65054359Sroberto			}
65154359Sroberto		}
65254359Sroberto#ifdef XXX /* temp until certificate code is mplemented */
65354359Sroberto		if (tkeyid != peer->pkeyid)
65454359Sroberto			peer->flash |= TEST9;	/* peer not authentic */
65554359Sroberto#endif
65654359Sroberto		peer->pkeyid = skeyid;
65754359Sroberto	}
65854359Sroberto#endif /* MD5 */
65954359Sroberto
66054359Sroberto	/*
66154359Sroberto	 * Gawdz, it's come to this. Process the dang packet. If something
66254359Sroberto	 * breaks and the association doesn't deserve to live, toss it.
66354359Sroberto	 * Be careful in active mode and return a packet anyway.
66454359Sroberto	 */
66554359Sroberto	process_packet(peer, pkt, &(rbufp->recv_time));
66654359Sroberto	if (!(peer->flags & FLAG_CONFIG) && peer->reach == 0) {
66754359Sroberto		if (peer->hmode == MODE_PASSIVE) {
66854359Sroberto			if (is_authentic)
66954359Sroberto				fast_xmit(rbufp, MODE_PASSIVE, skeyid);
67054359Sroberto			else
67154359Sroberto				fast_xmit(rbufp, MODE_PASSIVE, 0);
67254359Sroberto		}
67354359Sroberto		unpeer(peer);
67454359Sroberto	}
67554359Sroberto}
67654359Sroberto
67754359Sroberto
67854359Sroberto/*
67954359Sroberto * process_packet - Packet Procedure, a la Section 3.4.4 of the
68054359Sroberto *	specification. Or almost, at least. If we're in here we have a
68154359Sroberto *	reasonable expectation that we will be having a long term
68254359Sroberto *	relationship with this host.
68354359Sroberto */
68454359Srobertoint
68554359Srobertoprocess_packet(
68654359Sroberto	register struct peer *peer,
68754359Sroberto	register struct pkt *pkt,
68854359Sroberto	l_fp *recv_ts
68954359Sroberto	)
69054359Sroberto{
69154359Sroberto	l_fp t10, t23;
69254359Sroberto	double p_offset, p_del, p_disp;
69354359Sroberto	double dtemp;
69454359Sroberto	l_fp p_rec, p_xmt, p_org, p_reftime;
69554359Sroberto	l_fp ci;
69654359Sroberto	int pmode;
69754359Sroberto
69854359Sroberto	/*
69954359Sroberto	 * Swap header fields and keep the books.
70054359Sroberto	 */
70154359Sroberto	sys_processed++;
70254359Sroberto	peer->processed++;
70354359Sroberto	p_del = FPTOD(NTOHS_FP(pkt->rootdelay));
70454359Sroberto	p_disp = FPTOD(NTOHS_FP(pkt->rootdispersion));
70554359Sroberto	NTOHL_FP(&pkt->reftime, &p_reftime);
70654359Sroberto	NTOHL_FP(&pkt->rec, &p_rec);
70754359Sroberto	NTOHL_FP(&pkt->xmt, &p_xmt);
70854359Sroberto	if (PKT_MODE(pkt->li_vn_mode) != MODE_BROADCAST)
70954359Sroberto		NTOHL_FP(&pkt->org, &p_org);
71054359Sroberto	else
71154359Sroberto		p_org = peer->rec;
71254359Sroberto	peer->rec = *recv_ts;
71354359Sroberto	peer->ppoll = pkt->ppoll;
71454359Sroberto	pmode = PKT_MODE(pkt->li_vn_mode);
71554359Sroberto
71654359Sroberto	/*
71754359Sroberto	 * Test for old or duplicate packets (tests 1 through 3).
71854359Sroberto	 */
71954359Sroberto	if (L_ISHIS(&peer->org, &p_xmt))	/* count old packets */
72054359Sroberto		peer->oldpkt++;
72154359Sroberto	if (L_ISEQU(&peer->org, &p_xmt))	/* test 1 */
72254359Sroberto		peer->flash |= TEST1;		/* duplicate packet */
72354359Sroberto	if (PKT_MODE(pkt->li_vn_mode) != MODE_BROADCAST) {
72454359Sroberto		if (!L_ISEQU(&peer->xmt, &p_org)) { /* test 2 */
72554359Sroberto			peer->bogusorg++;
72654359Sroberto			peer->flash |= TEST2;	/* bogus packet */
72754359Sroberto		}
72854359Sroberto		if (L_ISZERO(&p_rec) || L_ISZERO(&p_org))
72954359Sroberto			peer->flash |= TEST3;	/* unsynchronized */
73054359Sroberto	} else {
73154359Sroberto		if (L_ISZERO(&p_org))
73254359Sroberto			peer->flash |= TEST3;	/* unsynchronized */
73354359Sroberto	}
73454359Sroberto	peer->org = p_xmt;
73554359Sroberto
73654359Sroberto	/*
73754359Sroberto	 * Test for valid header (tests 5 through 10)
73854359Sroberto	 */
73954359Sroberto	ci = p_xmt;
74054359Sroberto	L_SUB(&ci, &p_reftime);
74154359Sroberto	LFPTOD(&ci, dtemp);
74254359Sroberto	if (PKT_LEAP(pkt->li_vn_mode) == LEAP_NOTINSYNC || /* test 6 */
74354359Sroberto	    PKT_TO_STRATUM(pkt->stratum) >= NTP_MAXSTRATUM ||
74454359Sroberto	    dtemp < 0)
74554359Sroberto		peer->flash |= TEST6;	/* peer clock unsynchronized */
74654359Sroberto	if (!(peer->flags & FLAG_CONFIG) && sys_peer != 0) { /* test 7 */
74754359Sroberto		if (PKT_TO_STRATUM(pkt->stratum) > sys_stratum) {
74854359Sroberto			peer->flash |= TEST7; /* peer stratum too high */
74954359Sroberto			sys_badstratum++;
75054359Sroberto		}
75154359Sroberto	}
75254359Sroberto	if (fabs(p_del) >= MAXDISPERSE	/* test 8 */
75354359Sroberto	    || p_disp >= MAXDISPERSE)
75454359Sroberto		peer->flash |= TEST8;	/* delay/dispersion too high */
75554359Sroberto
75654359Sroberto	/*
75754359Sroberto	 * If the packet header is invalid (tests 5 through 10), exit.
75854359Sroberto	 * XXX we let TEST9 sneak by until the certificate code is
75954359Sroberto	 * implemented, but only to mobilize the association.
76054359Sroberto	 */
76154359Sroberto	if (peer->flash & (TEST5 | TEST6 | TEST7 | TEST8 | TEST10)) {
76254359Sroberto#ifdef DEBUG
76354359Sroberto		if (debug)
76454359Sroberto			printf(
76554359Sroberto			    "invalid packet header 0x%02x mode %d\n",
76654359Sroberto			    peer->flash, pmode);
76754359Sroberto#endif
76854359Sroberto		return (0);
76954359Sroberto	}
77054359Sroberto
77154359Sroberto	/*
77254359Sroberto	 * Valid header; update our state.
77354359Sroberto	 */
77454359Sroberto	record_raw_stats(&peer->srcadr, &peer->dstadr->sin,
77554359Sroberto	    &p_org, &p_rec, &p_xmt, &peer->rec);
77654359Sroberto
77754359Sroberto	peer->leap = PKT_LEAP(pkt->li_vn_mode);
77854359Sroberto	peer->pmode = pmode;		/* unspec */
77954359Sroberto	peer->stratum = PKT_TO_STRATUM(pkt->stratum);
78054359Sroberto	peer->precision = pkt->precision;
78154359Sroberto	peer->rootdelay = p_del;
78254359Sroberto	peer->rootdispersion = p_disp;
78354359Sroberto	peer->refid = pkt->refid;
78454359Sroberto	peer->reftime = p_reftime;
78554359Sroberto	if (peer->reach == 0) {
78654359Sroberto		report_event(EVNT_REACH, peer);
78754359Sroberto		peer->timereachable = current_time;
78854359Sroberto	}
78954359Sroberto	peer->reach |= 1;
79054359Sroberto	poll_update(peer, peer->hpoll);
79154359Sroberto
79254359Sroberto	/*
79354359Sroberto	 * If running in a client/server association, calculate the
79454359Sroberto	 * clock offset c, roundtrip delay d and dispersion e. We use
79554359Sroberto	 * the equations (reordered from those in the spec). Note that,
79654359Sroberto	 * in a broadcast association, org has been set to the time of
79754359Sroberto	 * last reception. Note the computation of dispersion includes
79854359Sroberto	 * the system precision plus that due to the frequency error
79954359Sroberto	 * since the originate time.
80054359Sroberto	 *
80154359Sroberto	 * c = ((t2 - t3) + (t1 - t0)) / 2
80254359Sroberto	 * d = (t2 - t3) - (t1 - t0)
80354359Sroberto	 * e = (org - rec) (seconds only)
80454359Sroberto	 */
80554359Sroberto	t10 = p_xmt;			/* compute t1 - t0 */
80654359Sroberto	L_SUB(&t10, &peer->rec);
80754359Sroberto	t23 = p_rec;			/* compute t2 - t3 */
80854359Sroberto	L_SUB(&t23, &p_org);
80954359Sroberto	ci = t10;
81054359Sroberto	p_disp = CLOCK_PHI * (peer->rec.l_ui - p_org.l_ui);
81154359Sroberto
81254359Sroberto	/*
81354359Sroberto	 * If running in a broadcast association, the clock offset is (t1
81454359Sroberto	 * - t0) corrected by the one-way delay, but we can't measure
81554359Sroberto	 * that directly; therefore, we start up in client/server mode,
81654359Sroberto	 * calculate the clock offset, using the engineered refinement
81754359Sroberto	 * algorithms, while also receiving broadcasts. When a broadcast
81854359Sroberto	 * is received in client/server mode, we calculate a correction
81954359Sroberto	 * factor to use after switching back to broadcast mode. We know
82054359Sroberto	 * NTP_SKEWFACTOR == 16, which accounts for the simplified ei
82154359Sroberto	 * calculation.
82254359Sroberto	 *
82354359Sroberto	 * If FLAG_MCAST2 is set, we are a broadcast/multicast client.
82454359Sroberto	 * If FLAG_MCAST1 is set, we haven't calculated the propagation
82554359Sroberto	 * delay. If hmode is MODE_CLIENT, we haven't set the local
82654359Sroberto	 * clock in client/server mode. Initially, we come up
82754359Sroberto	 * MODE_CLIENT. When the clock is first updated and FLAG_MCAST2
82854359Sroberto	 * is set, we switch from MODE_CLIENT to MODE_BCLIENT.
82954359Sroberto	 */
83054359Sroberto	if (pmode == MODE_BROADCAST) {
83154359Sroberto		if (peer->flags & FLAG_MCAST1) {
83254359Sroberto			if (peer->hmode == MODE_BCLIENT)
83354359Sroberto				peer->flags &= ~FLAG_MCAST1;
83454359Sroberto			LFPTOD(&ci, p_offset);
83554359Sroberto			peer->estbdelay = peer->offset - p_offset;
83654359Sroberto			return (1);
83754359Sroberto
83854359Sroberto		}
83954359Sroberto		DTOLFP(peer->estbdelay, &t10);
84054359Sroberto		L_ADD(&ci, &t10);
84154359Sroberto		p_del = peer->delay;
84254359Sroberto	} else {
84354359Sroberto		L_ADD(&ci, &t23);
84454359Sroberto		L_RSHIFT(&ci);
84554359Sroberto		L_SUB(&t23, &t10);
84654359Sroberto		LFPTOD(&t23, p_del);
84754359Sroberto	}
84854359Sroberto	LFPTOD(&ci, p_offset);
84954359Sroberto	if (fabs(p_del) >= MAXDISPERSE || p_disp >= MAXDISPERSE) /* test 4 */
85054359Sroberto		peer->flash |= TEST4;	/* delay/dispersion too big */
85154359Sroberto
85254359Sroberto	/*
85354359Sroberto	 * If the packet data are invalid (tests 1 through 4), exit.
85454359Sroberto	 */
85554359Sroberto	if (peer->flash) {
85654359Sroberto#ifdef DEBUG
85754359Sroberto		if (debug)
85854359Sroberto			printf("invalid packet data 0x%02x mode %d\n",
85954359Sroberto			    peer->flash, pmode);
86054359Sroberto#endif
86154359Sroberto		return(1);
86254359Sroberto	}
86354359Sroberto
86454359Sroberto
86554359Sroberto	/*
86654359Sroberto	 * This one is valid. Mark it so, give it to clock_filter().
86754359Sroberto	 */
86854359Sroberto	clock_filter(peer, p_offset, p_del, fabs(p_disp));
86954359Sroberto	clock_select();
87054359Sroberto	record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
87154359Sroberto	    peer->offset, peer->delay, peer->disp, SQRT(peer->variance));
87254359Sroberto	return(1);
87354359Sroberto}
87454359Sroberto
87554359Sroberto
87654359Sroberto/*
87754359Sroberto * clock_update - Called at system process update intervals.
87854359Sroberto */
87954359Srobertostatic void
88054359Srobertoclock_update(void)
88154359Sroberto{
88254359Sroberto	u_char oleap;
88354359Sroberto	u_char ostratum;
88454359Sroberto	int i;
88554359Sroberto	struct peer *peer;
88654359Sroberto
88754359Sroberto	/*
88854359Sroberto	 * Reset/adjust the system clock. Do this only if there is a
88954359Sroberto	 * system peer and we haven't seen that peer lately. Watch for
89054359Sroberto	 * timewarps here.
89154359Sroberto	 */
89254359Sroberto	if (sys_peer == 0)
89354359Sroberto		return;
89454359Sroberto	if (sys_peer->pollsw == FALSE || sys_peer->burst > 0)
89554359Sroberto		return;
89654359Sroberto	sys_peer->pollsw = FALSE;
89754359Sroberto#ifdef DEBUG
89854359Sroberto	if (debug)
89954359Sroberto		printf("clock_update: at %ld assoc %d \n", current_time,
90054359Sroberto		    peer_associations);
90154359Sroberto#endif
90254359Sroberto	oleap = sys_leap;
90354359Sroberto	ostratum = sys_stratum;
90454359Sroberto	switch (local_clock(sys_peer, sys_offset, sys_epsil)) {
90554359Sroberto
90654359Sroberto		case -1:
90754359Sroberto		/*
90854359Sroberto		 * Clock is too screwed up. Just exit for now.
90954359Sroberto		 */
91054359Sroberto		report_event(EVNT_SYSFAULT, (struct peer *)0);
91154359Sroberto		exit(1);
91254359Sroberto		/*NOTREACHED*/
91354359Sroberto
91454359Sroberto		case 1:
91554359Sroberto		/*
91654359Sroberto		 * Clock was stepped. Clear filter registers
91754359Sroberto		 * of all peers.
91854359Sroberto		 */
91954359Sroberto		for (i = 0; i < HASH_SIZE; i++) {
92054359Sroberto			for (peer = peer_hash[i]; peer != 0;
92154359Sroberto				peer =peer->next)
92254359Sroberto				peer_clear(peer);
92354359Sroberto		}
92454359Sroberto		NLOG(NLOG_SYNCSTATUS)
92554359Sroberto			msyslog(LOG_INFO, "synchronisation lost");
92654359Sroberto		sys_peer = 0;
92754359Sroberto		sys_stratum = STRATUM_UNSPEC;
92854359Sroberto		report_event(EVNT_CLOCKRESET, (struct peer *)0);
92954359Sroberto		break;
93054359Sroberto
93154359Sroberto		default:
93254359Sroberto		/*
93354359Sroberto		 * Update the system stratum, leap bits, root delay,
93454359Sroberto		 * root dispersion, reference ID and reference time. We
93554359Sroberto		 * also update select dispersion and max frequency
93654359Sroberto		 * error.
93754359Sroberto		 */
93854359Sroberto		sys_stratum = sys_peer->stratum + 1;
93954359Sroberto		if (sys_stratum == 1)
94054359Sroberto			sys_refid = sys_peer->refid;
94154359Sroberto		else
94254359Sroberto			sys_refid = sys_peer->srcadr.sin_addr.s_addr;
94354359Sroberto		sys_reftime = sys_peer->rec;
94454359Sroberto		sys_rootdelay = sys_peer->rootdelay + fabs(sys_peer->delay);
94554359Sroberto		sys_leap = leap_consensus;
94654359Sroberto	}
94754359Sroberto	if (oleap != sys_leap)
94854359Sroberto		report_event(EVNT_SYNCCHG, (struct peer *)0);
94954359Sroberto	if (ostratum != sys_stratum)
95054359Sroberto		report_event(EVNT_PEERSTCHG, (struct peer *)0);
95154359Sroberto}
95254359Sroberto
95354359Sroberto
95454359Sroberto/*
95554359Sroberto * poll_update - update peer poll interval. See Section 3.4.9 of the
95654359Sroberto *	   spec.
95754359Sroberto */
95854359Srobertovoid
95954359Srobertopoll_update(
96054359Sroberto	struct peer *peer,
96154359Sroberto	int hpoll
96254359Sroberto	)
96354359Sroberto{
96454359Sroberto	long update;
96554359Sroberto
96654359Sroberto	/*
96754359Sroberto	 * The wiggle-the-poll-interval dance. Broadcasters dance only
96854359Sroberto	 * the minpoll beat. Reference clock partners sit this one out.
96954359Sroberto	 * Dancers surviving the clustering algorithm beat to the system
97054359Sroberto	 * clock. Broadcast clients are usually lead by their broadcast
97154359Sroberto	 * partner, but faster in the initial mating dance.
97254359Sroberto	 */
97354359Sroberto	if (peer->hmode == MODE_BROADCAST) {
97454359Sroberto		peer->hpoll = peer->minpoll;
97554359Sroberto	} else if (peer->flags & FLAG_SYSPEER) {
97654359Sroberto		peer->hpoll = sys_poll;
97754359Sroberto	} else {
97854359Sroberto		if (hpoll > peer->maxpoll)
97954359Sroberto			peer->hpoll = peer->maxpoll;
98054359Sroberto		else if (hpoll < peer->minpoll)
98154359Sroberto			peer->hpoll = peer->minpoll;
98254359Sroberto		else
98354359Sroberto			peer->hpoll = hpoll;
98454359Sroberto	}
98554359Sroberto	if (peer->burst > 0) {
98654359Sroberto		if (peer->nextdate != current_time)
98754359Sroberto			return;
98854359Sroberto		if (peer->flags & FLAG_REFCLOCK)
98954359Sroberto			peer->nextdate++;
99054359Sroberto		else if (peer->reach & 0x1)
99154359Sroberto			peer->nextdate += RANDPOLL(BURST_INTERVAL2);
99254359Sroberto		else
99354359Sroberto			peer->nextdate += RANDPOLL(BURST_INTERVAL1);
99454359Sroberto	} else {
99554359Sroberto		update = max(min(peer->ppoll, peer->hpoll), peer->minpoll);
99654359Sroberto		peer->nextdate = peer->outdate + RANDPOLL(update);
99754359Sroberto	}
99854359Sroberto#ifdef DEBUG
99954359Sroberto	if (debug > 1)
100054359Sroberto		printf("poll_update: at %lu %s poll %d burst %d last %lu next %lu\n",
100154359Sroberto		    current_time, ntoa(&peer->srcadr), hpoll, peer->burst,
100254359Sroberto		    peer->outdate, peer->nextdate);
100354359Sroberto#endif
100454359Sroberto}
100554359Sroberto
100654359Sroberto
100754359Sroberto/*
100854359Sroberto * clear - clear peer filter registers.  See Section 3.4.8 of the spec.
100954359Sroberto */
101054359Srobertovoid
101154359Srobertopeer_clear(
101254359Sroberto	register struct peer *peer
101354359Sroberto	)
101454359Sroberto{
101554359Sroberto	register int i;
101654359Sroberto
101754359Sroberto	memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);
101854359Sroberto	peer->estbdelay = sys_bdelay;
101954359Sroberto	peer->hpoll = peer->minpoll;
102054359Sroberto	peer->pollsw = FALSE;
102154359Sroberto	peer->variance = MAXDISPERSE;
102254359Sroberto	peer->epoch = current_time;
102354359Sroberto	for (i = 0; i < NTP_SHIFT; i++) {
102454359Sroberto		peer->filter_order[i] = i;
102554359Sroberto		peer->filter_disp[i] = MAXDISPERSE;
102654359Sroberto		peer->filter_epoch[i] = current_time;
102754359Sroberto	}
102854359Sroberto	poll_update(peer, peer->minpoll);
102954359Sroberto
103054359Sroberto	/*
103154359Sroberto	 * Since we have a chance to correct possible funniness in
103254359Sroberto	 * our selection of interfaces on a multihomed host, do so
103354359Sroberto	 * by setting us to no particular interface.
103454359Sroberto	 * WARNING: do so only in non-broadcast mode!
103554359Sroberto	 */
103654359Sroberto	if (peer->hmode != MODE_BROADCAST)
103754359Sroberto		peer->dstadr = any_interface;
103854359Sroberto}
103954359Sroberto
104054359Sroberto
104154359Sroberto/*
104254359Sroberto * clock_filter - add incoming clock sample to filter register and run
104354359Sroberto *		  the filter procedure to find the best sample.
104454359Sroberto */
104554359Srobertovoid
104654359Srobertoclock_filter(
104754359Sroberto	register struct peer *peer,
104854359Sroberto	double sample_offset,
104954359Sroberto	double sample_delay,
105054359Sroberto	double sample_disp
105154359Sroberto	)
105254359Sroberto{
105354359Sroberto	register int i, j, k, n = 0;
105454359Sroberto	register u_char *ord;
105554359Sroberto	double distance[NTP_SHIFT];
105654359Sroberto	double x, y, z, off;
105754359Sroberto
105854359Sroberto	/*
105954359Sroberto	 * Update error bounds and calculate distances. Also initialize
106054359Sroberto	 * sort index vector.
106154359Sroberto	 */
106254359Sroberto	x = CLOCK_PHI * (current_time - peer->update);
106354359Sroberto	peer->update = current_time;
106454359Sroberto	ord = peer->filter_order;
106554359Sroberto	j = peer->filter_nextpt;
106654359Sroberto	for (i = 0; i < NTP_SHIFT; i++) {
106754359Sroberto		peer->filter_disp[j] += x;
106854359Sroberto		if (peer->filter_disp[j] > MAXDISPERSE)
106954359Sroberto			peer->filter_disp[j] = MAXDISPERSE;
107054359Sroberto		distance[i] = fabs(peer->filter_delay[j]) / 2 +
107154359Sroberto		    peer->filter_disp[j];
107254359Sroberto		ord[i] = j;
107354359Sroberto		if (--j < 0)
107454359Sroberto			j += NTP_SHIFT;
107554359Sroberto	}
107654359Sroberto
107754359Sroberto	/*
107854359Sroberto	 * Insert the new sample at the beginning of the register.
107954359Sroberto	 */
108054359Sroberto	peer->filter_offset[peer->filter_nextpt] = sample_offset;
108154359Sroberto	peer->filter_delay[peer->filter_nextpt] = sample_delay;
108254359Sroberto	x = LOGTOD(peer->precision) + LOGTOD(sys_precision) + sample_disp;
108354359Sroberto	peer->filter_disp[peer->filter_nextpt] = min(x, MAXDISPERSE);
108454359Sroberto	peer->filter_epoch[peer->filter_nextpt] = current_time;
108554359Sroberto	distance[0] = min(x + fabs(sample_delay) / 2, MAXDISTANCE);
108654359Sroberto	peer->filter_nextpt++;
108754359Sroberto	if (peer->filter_nextpt >= NTP_SHIFT)
108854359Sroberto		peer->filter_nextpt = 0;
108954359Sroberto
109054359Sroberto	/*
109154359Sroberto	 * Sort the samples in the register by distance. The winning
109254359Sroberto	 * sample will be in ord[0]. Sort the samples only if they
109354359Sroberto	 * are younger than the Allen intercept.
109454359Sroberto	 */
109554359Sroberto	y = min(allan_xpt, NTP_SHIFT * ULOGTOD(sys_poll));
109654359Sroberto	for (n = 0; n < NTP_SHIFT && current_time -
109754359Sroberto	    peer->filter_epoch[ord[n]] <= y; n++) {
109854359Sroberto		for (j = 0; j < n; j++) {
109954359Sroberto			if (distance[j] > distance[n]) {
110054359Sroberto				x = distance[j];
110154359Sroberto				k = ord[j];
110254359Sroberto				distance[j] = distance[n];
110354359Sroberto				ord[j] = ord[n];
110454359Sroberto				distance[n] = x;
110554359Sroberto				ord[n] = k;
110654359Sroberto			}
110754359Sroberto		}
110854359Sroberto	}
110954359Sroberto
111054359Sroberto	/*
111154359Sroberto	 * Compute the error bound and standard error.
111254359Sroberto	 */
111354359Sroberto	x = y = z = off = 0.;
111454359Sroberto	for (i = NTP_SHIFT - 1; i >= 0; i--) {
111554359Sroberto		x = NTP_FWEIGHT * (x + peer->filter_disp[ord[i]]);
111654359Sroberto		if (i < n) {
111754359Sroberto			z += 1. / distance[i];
111854359Sroberto			off += peer->filter_offset[ord[i]] / distance[i];
111954359Sroberto			y += DIFF(peer->filter_offset[ord[i]],
112054359Sroberto			    peer->filter_offset[ord[0]]);
112154359Sroberto		}
112254359Sroberto	}
112354359Sroberto	peer->delay = peer->filter_delay[ord[0]];
112454359Sroberto	peer->variance = min(y / n, MAXDISPERSE);
112554359Sroberto	peer->disp = min(x, MAXDISPERSE);
112654359Sroberto	peer->epoch = current_time;
112754359Sroberto	x = peer->offset;
112854359Sroberto	if (peer->flags & FLAG_BURST)
112954359Sroberto		peer->offset = off / z;
113054359Sroberto	else
113154359Sroberto		peer->offset = peer->filter_offset[ord[0]];
113254359Sroberto
113354359Sroberto	/*
113454359Sroberto	 * A new sample is useful only if it is younger than the last
113554359Sroberto	 * one used.
113654359Sroberto	 */
113754359Sroberto	if (peer->filter_epoch[ord[0]] > peer->epoch) {
113854359Sroberto#ifdef DEBUG
113954359Sroberto		if (debug)
114054359Sroberto			printf("clock_filter: discard %lu\n",
114154359Sroberto			    peer->filter_epoch[ord[0]] - peer->epoch);
114254359Sroberto#endif
114354359Sroberto		return;
114454359Sroberto	}
114554359Sroberto
114654359Sroberto	/*
114754359Sroberto	 * If the offset exceeds the dispersion by CLOCK_SGATE and the
114854359Sroberto	 * interval since the last update is less than twice the system
114954359Sroberto	 * poll interval, consider the update a popcorn spike and ignore
115054359Sroberto	 * it.
115154359Sroberto	 */
115254359Sroberto	if (fabs(x - peer->offset) > CLOCK_SGATE &&
115354359Sroberto	    peer->filter_epoch[ord[0]] - peer->epoch < (1 <<
115454359Sroberto	    (sys_poll + 1))) {
115554359Sroberto#ifdef DEBUG
115654359Sroberto		if (debug)
115754359Sroberto			printf("clock_filter: popcorn spike %.6f\n", x);
115854359Sroberto#endif
115954359Sroberto		return;
116054359Sroberto	}
116154359Sroberto	peer->epoch = peer->filter_epoch[ord[0]];
116254359Sroberto	peer->pollsw = TRUE;
116354359Sroberto#ifdef DEBUG
116454359Sroberto	if (debug)
116554359Sroberto		printf(
116654359Sroberto		    "clock_filter: offset %.6f delay %.6f disp %.6f std %.6f, age %lu\n",
116754359Sroberto		    peer->offset, peer->delay, peer->disp,
116854359Sroberto		    SQRT(peer->variance), current_time - peer->epoch);
116954359Sroberto#endif
117054359Sroberto}
117154359Sroberto
117254359Sroberto
117354359Sroberto/*
117454359Sroberto * clock_select - find the pick-of-the-litter clock
117554359Sroberto */
117654359Srobertovoid
117754359Srobertoclock_select(void)
117854359Sroberto{
117954359Sroberto	register struct peer *peer;
118054359Sroberto	int i;
118154359Sroberto	int nlist, nl3;
118254359Sroberto	double d, e, f;
118354359Sroberto	int j;
118454359Sroberto	int n;
118554359Sroberto	int allow, found, k;
118654359Sroberto	double high, low;
118754359Sroberto	double synch[NTP_MAXCLOCK], error[NTP_MAXCLOCK];
118854359Sroberto	struct peer *osys_peer;
118954359Sroberto	struct peer *typeacts = 0;
119054359Sroberto	struct peer *typelocal = 0;
119154359Sroberto	struct peer *typepps = 0;
119254359Sroberto	struct peer *typeprefer = 0;
119354359Sroberto	struct peer *typesystem = 0;
119454359Sroberto
119554359Sroberto	static int list_alloc = 0;
119654359Sroberto	static struct endpoint *endpoint = NULL;
119754359Sroberto	static int *index = NULL;
119854359Sroberto	static struct peer **peer_list = NULL;
119954359Sroberto	static u_int endpoint_size = 0;
120054359Sroberto	static u_int index_size = 0;
120154359Sroberto	static u_int peer_list_size = 0;
120254359Sroberto
120354359Sroberto	/*
120454359Sroberto	 * Initialize. If a prefer peer does not survive this thing,
120554359Sroberto	 * the pps_update switch will remain zero.
120654359Sroberto	 */
120754359Sroberto	pps_update = 0;
120854359Sroberto	nlist = 0;
120954359Sroberto	low = 1e9;
121054359Sroberto	high = -1e9;
121154359Sroberto	for (n = 0; n < HASH_SIZE; n++)
121254359Sroberto		nlist += peer_hash_count[n];
121354359Sroberto	if (nlist > list_alloc) {
121454359Sroberto		if (list_alloc > 0) {
121554359Sroberto			free(endpoint);
121654359Sroberto			free(index);
121754359Sroberto			free(peer_list);
121854359Sroberto		}
121954359Sroberto		while (list_alloc < nlist) {
122054359Sroberto			list_alloc += 5;
122154359Sroberto			endpoint_size += 5 * 3 * sizeof *endpoint;
122254359Sroberto			index_size += 5 * 3 * sizeof *index;
122354359Sroberto			peer_list_size += 5 * sizeof *peer_list;
122454359Sroberto		}
122554359Sroberto		endpoint = (struct endpoint *)emalloc(endpoint_size);
122654359Sroberto		index = (int *)emalloc(index_size);
122754359Sroberto		peer_list = (struct peer **)emalloc(peer_list_size);
122854359Sroberto	}
122954359Sroberto
123054359Sroberto	/*
123154359Sroberto	 * This first chunk of code is supposed to go through all
123254359Sroberto	 * peers we know about to find the peers which are most likely
123354359Sroberto	 * to succeed. We run through the list doing the sanity checks
123454359Sroberto	 * and trying to insert anyone who looks okay.
123554359Sroberto	 */
123654359Sroberto	nlist = nl3 = 0;	/* none yet */
123754359Sroberto	for (n = 0; n < HASH_SIZE; n++) {
123854359Sroberto		for (peer = peer_hash[n]; peer != 0; peer = peer->next) {
123954359Sroberto			peer->flags &= ~FLAG_SYSPEER;
124054359Sroberto			peer->status = CTL_PST_SEL_REJECT;
124154359Sroberto			if (peer->flags & FLAG_NOSELECT)
124254359Sroberto				continue;	/* noselect (survey only) */
124354359Sroberto			if (peer->reach == 0)
124454359Sroberto				continue;	/* unreachable */
124554359Sroberto			if (peer->stratum > 1 && peer->refid ==
124654359Sroberto			    peer->dstadr->sin.sin_addr.s_addr)
124754359Sroberto				continue;	/* sync loop */
124854359Sroberto			if (root_distance(peer) >= MAXDISTANCE + 2 *
124954359Sroberto			    CLOCK_PHI * ULOGTOD(sys_poll)) {
125054359Sroberto				peer->seldisptoolarge++;
125154359Sroberto				continue;	/* too noisy or broken */
125254359Sroberto			}
125354359Sroberto
125454359Sroberto			/*
125554359Sroberto			 * Don't allow the local-clock or acts drivers
125654359Sroberto			 * in the kitchen at this point, unless the
125754359Sroberto			 * prefer peer. Do that later, but only if
125854359Sroberto			 * nobody else is around.
125954359Sroberto			 */
126054359Sroberto			if (peer->refclktype == REFCLK_LOCALCLOCK
126154359Sroberto#if defined(VMS) && defined(VMS_LOCALUNIT)
126254359Sroberto				/* wjm: local unit VMS_LOCALUNIT taken seriously */
126354359Sroberto				&& REFCLOCKUNIT(&peer->srcadr) != VMS_LOCALUNIT
126454359Sroberto#endif	/* VMS && VMS_LOCALUNIT */
126554359Sroberto				) {
126654359Sroberto				typelocal = peer;
126754359Sroberto				if (!(peer->flags & FLAG_PREFER))
126854359Sroberto					continue; /* no local clock */
126954359Sroberto			}
127054359Sroberto			if (peer->sstclktype == CTL_SST_TS_TELEPHONE) {
127154359Sroberto				typeacts = peer;
127254359Sroberto				if (!(peer->flags & FLAG_PREFER))
127354359Sroberto					continue; /* no acts */
127454359Sroberto			}
127554359Sroberto
127654359Sroberto			/*
127754359Sroberto			 * If we get this far, we assume the peer is
127854359Sroberto			 * acceptable.
127954359Sroberto			 */
128054359Sroberto			peer->status = CTL_PST_SEL_SANE;
128154359Sroberto			peer_list[nlist++] = peer;
128254359Sroberto
128354359Sroberto			/*
128454359Sroberto			 * Insert each interval endpoint on the sorted
128554359Sroberto			 * list.
128654359Sroberto			 */
128754359Sroberto			e = peer->offset;	 /* Upper end */
128854359Sroberto			f = root_distance(peer);
128954359Sroberto			e = e + f;
129054359Sroberto			for (i = nl3 - 1; i >= 0; i--) {
129154359Sroberto				if (e >= endpoint[index[i]].val)
129254359Sroberto					break;
129354359Sroberto				index[i + 3] = index[i];
129454359Sroberto			}
129554359Sroberto			index[i + 3] = nl3;
129654359Sroberto			endpoint[nl3].type = 1;
129754359Sroberto			endpoint[nl3++].val = e;
129854359Sroberto
129954359Sroberto			e = e - f;		/* Center point */
130054359Sroberto			for ( ; i >= 0; i--) {
130154359Sroberto				if (e >= endpoint[index[i]].val)
130254359Sroberto					break;
130354359Sroberto				index[i + 2] = index[i];
130454359Sroberto			}
130554359Sroberto			index[i + 2] = nl3;
130654359Sroberto			endpoint[nl3].type = 0;
130754359Sroberto			endpoint[nl3++].val = e;
130854359Sroberto
130954359Sroberto			e = e - f;		/* Lower end */
131054359Sroberto			for ( ; i >= 0; i--) {
131154359Sroberto				if (e >= endpoint[index[i]].val)
131254359Sroberto					break;
131354359Sroberto				index[i + 1] = index[i];
131454359Sroberto			}
131554359Sroberto			index[i + 1] = nl3;
131654359Sroberto			endpoint[nl3].type = -1;
131754359Sroberto			endpoint[nl3++].val = e;
131854359Sroberto		}
131954359Sroberto	}
132054359Sroberto#ifdef DEBUG
132154359Sroberto	if (debug > 1)
132254359Sroberto		for (i = 0; i < nl3; i++)
132354359Sroberto		printf("select: endpoint %2d %.6f\n",
132454359Sroberto			   endpoint[index[i]].type, endpoint[index[i]].val);
132554359Sroberto#endif
132654359Sroberto	i = 0;
132754359Sroberto	j = nl3 - 1;
132854359Sroberto	allow = nlist;		/* falsetickers assumed */
132954359Sroberto	found = 0;
133054359Sroberto	while (allow > 0) {
133154359Sroberto		allow--;
133254359Sroberto		for (n = 0; i <= j; i++) {
133354359Sroberto			n += endpoint[index[i]].type;
133454359Sroberto			if (n < 0)
133554359Sroberto				break;
133654359Sroberto			if (endpoint[index[i]].type == 0)
133754359Sroberto				found++;
133854359Sroberto		}
133954359Sroberto		for (n = 0; i <= j; j--) {
134054359Sroberto			n += endpoint[index[j]].type;
134154359Sroberto			if (n > 0)
134254359Sroberto				break;
134354359Sroberto			if (endpoint[index[j]].type == 0)
134454359Sroberto				found++;
134554359Sroberto		}
134654359Sroberto		if (found > allow)
134754359Sroberto			break;
134854359Sroberto		low = endpoint[index[i++]].val;
134954359Sroberto		high = endpoint[index[j--]].val;
135054359Sroberto	}
135154359Sroberto
135254359Sroberto	/*
135354359Sroberto	 * If no survivors remain at this point, check if the acts or
135454359Sroberto	 * local clock drivers have been found. If so, nominate one of
135554359Sroberto	 * them as the only survivor. Otherwise, give up and declare us
135654359Sroberto	 * unsynchronized.
135754359Sroberto	 */
135854359Sroberto	if ((allow << 1) >= nlist) {
135954359Sroberto		if (typeacts != 0) {
136054359Sroberto			typeacts->status = CTL_PST_SEL_SANE;
136154359Sroberto			peer_list[0] = typeacts;
136254359Sroberto			nlist = 1;
136354359Sroberto		} else if (typelocal != 0) {
136454359Sroberto			typelocal->status = CTL_PST_SEL_SANE;
136554359Sroberto			peer_list[0] = typelocal;
136654359Sroberto			nlist = 1;
136754359Sroberto		} else {
136854359Sroberto			if (sys_peer != 0) {
136954359Sroberto				report_event(EVNT_PEERSTCHG,
137054359Sroberto					(struct peer *)0);
137154359Sroberto				NLOG(NLOG_SYNCSTATUS)
137254359Sroberto					msyslog(LOG_INFO, "synchronisation lost");
137354359Sroberto			}
137454359Sroberto			sys_peer = 0;
137554359Sroberto			return;
137654359Sroberto		}
137754359Sroberto	}
137854359Sroberto#ifdef DEBUG
137954359Sroberto	if (debug > 1)
138054359Sroberto		printf("select: low %.6f high %.6f\n", low, high);
138154359Sroberto#endif
138254359Sroberto
138354359Sroberto	/*
138454359Sroberto	 * Clustering algorithm. Process intersection list to discard
138554359Sroberto	 * outlyers. Construct candidate list in cluster order
138654359Sroberto	 * determined by the sum of peer synchronization distance plus
138754359Sroberto	 * scaled stratum. We must find at least one peer.
138854359Sroberto	 */
138954359Sroberto	j = 0;
139054359Sroberto	for (i = 0; i < nlist; i++) {
139154359Sroberto		peer = peer_list[i];
139254359Sroberto		if (nlist > 1 && (low >= peer->offset ||
139354359Sroberto			peer->offset >= high))
139454359Sroberto			continue;
139554359Sroberto		peer->status = CTL_PST_SEL_CORRECT;
139654359Sroberto		d = root_distance(peer) + peer->stratum * MAXDISPERSE;
139754359Sroberto		if (j >= NTP_MAXCLOCK) {
139854359Sroberto			if (d >= synch[j - 1])
139954359Sroberto				continue;
140054359Sroberto			else
140154359Sroberto				j--;
140254359Sroberto		}
140354359Sroberto		for (k = j; k > 0; k--) {
140454359Sroberto			if (d >= synch[k - 1])
140554359Sroberto				break;
140654359Sroberto			synch[k] = synch[k - 1];
140754359Sroberto			peer_list[k] = peer_list[k - 1];
140854359Sroberto		}
140954359Sroberto		peer_list[k] = peer;
141054359Sroberto		synch[k] = d;
141154359Sroberto		j++;
141254359Sroberto	}
141354359Sroberto	nlist = j;
141454359Sroberto
141554359Sroberto#ifdef DEBUG
141654359Sroberto	if (debug > 1)
141754359Sroberto		for (i = 0; i < nlist; i++)
141854359Sroberto			printf("select: %s distance %.6f\n",
141954359Sroberto				ntoa(&peer_list[i]->srcadr), synch[i]);
142054359Sroberto#endif
142154359Sroberto
142254359Sroberto	/*
142354359Sroberto	 * Now, prune outlyers by root dispersion. Continue as long as
142454359Sroberto	 * there are more than NTP_MINCLOCK survivors and the minimum
142554359Sroberto	 * select dispersion is greater than the maximum peer
142654359Sroberto	 * dispersion. Stop if we are about to discard a prefer peer.
142754359Sroberto	 */
142854359Sroberto	for (i = 0; i < nlist; i++) {
142954359Sroberto		peer = peer_list[i];
143054359Sroberto		error[i] = peer->variance;
143154359Sroberto		if (i < NTP_CANCLOCK)
143254359Sroberto			peer->status = CTL_PST_SEL_SELCAND;
143354359Sroberto		else
143454359Sroberto			peer->status = CTL_PST_SEL_DISTSYSPEER;
143554359Sroberto	}
143654359Sroberto	while (1) {
143754359Sroberto		sys_maxd = 0;
143854359Sroberto		d = error[0];
143954359Sroberto		for (k = i = nlist - 1; i >= 0; i--) {
144054359Sroberto			double sdisp = 0;
144154359Sroberto
144254359Sroberto			for (j = nlist - 1; j > 0; j--) {
144354359Sroberto				sdisp = NTP_SWEIGHT * (sdisp +
144454359Sroberto					DIFF(peer_list[i]->offset,
144554359Sroberto					peer_list[j]->offset));
144654359Sroberto			}
144754359Sroberto			if (sdisp > sys_maxd) {
144854359Sroberto				sys_maxd = sdisp;
144954359Sroberto				k = i;
145054359Sroberto			}
145154359Sroberto			if (error[i] < d)
145254359Sroberto				d = error[i];
145354359Sroberto		}
145454359Sroberto
145554359Sroberto#ifdef DEBUG
145654359Sroberto		if (debug > 1)
145754359Sroberto			printf(
145854359Sroberto			    "select: survivors %d select %.6f peer %.6f\n",
145954359Sroberto			    nlist, SQRT(sys_maxd), SQRT(d));
146054359Sroberto#endif
146154359Sroberto		if (nlist <= NTP_MINCLOCK || sys_maxd <= d ||
146254359Sroberto			peer_list[k]->flags & FLAG_PREFER)
146354359Sroberto			break;
146454359Sroberto		for (j = k + 1; j < nlist; j++) {
146554359Sroberto			peer_list[j - 1] = peer_list[j];
146654359Sroberto			error[j - 1] = error[j];
146754359Sroberto		}
146854359Sroberto		nlist--;
146954359Sroberto	}
147054359Sroberto#ifdef DEBUG
147154359Sroberto	if (debug > 1) {
147254359Sroberto		for (i = 0; i < nlist; i++)
147354359Sroberto			printf(
147454359Sroberto			    "select: %s offset %.6f, distance %.6f poll %d\n",
147554359Sroberto			    ntoa(&peer_list[i]->srcadr), peer_list[i]->offset,
147654359Sroberto			    synch[i], peer_list[i]->pollsw);
147754359Sroberto	}
147854359Sroberto#endif
147954359Sroberto
148054359Sroberto	/*
148154359Sroberto	 * What remains is a list of not greater than NTP_MINCLOCK
148254359Sroberto	 * peers. We want only a peer at the lowest stratum to become
148354359Sroberto	 * the system peer, although all survivors are eligible for the
148454359Sroberto	 * combining algorithm. First record their order, diddle the
148554359Sroberto	 * flags and clamp the poll intervals. Then, consider the peers
148654359Sroberto	 * at the lowest stratum. Of these, OR the leap bits on the
148754359Sroberto	 * assumption that, if some of them honk nonzero bits, they must
148854359Sroberto	 * know what they are doing. Also, check for prefer and pps
148954359Sroberto	 * peers. If a prefer peer is found within clock_max, update the
149054359Sroberto	 * pps switch. Of the other peers not at the lowest stratum,
149154359Sroberto	 * check if the system peer is among them and, if found, zap
149254359Sroberto	 * him. We note that the head of the list is at the lowest
149354359Sroberto	 * stratum and that unsynchronized peers cannot survive this
149454359Sroberto	 * far.
149554359Sroberto	 */
149654359Sroberto	leap_consensus = 0;
149754359Sroberto	for (i = nlist - 1; i >= 0; i--) {
149854359Sroberto		peer_list[i]->status = CTL_PST_SEL_SYNCCAND;
149954359Sroberto		peer_list[i]->flags |= FLAG_SYSPEER;
150054359Sroberto		poll_update(peer_list[i], peer_list[i]->hpoll);
150154359Sroberto		if (peer_list[i]->stratum == peer_list[0]->stratum) {
150254359Sroberto			leap_consensus |= peer_list[i]->leap;
150354359Sroberto			if (peer_list[i]->refclktype == REFCLK_ATOM_PPS)
150454359Sroberto				typepps = peer_list[i];
150554359Sroberto			if (peer_list[i] == sys_peer)
150654359Sroberto				typesystem = peer_list[i];
150754359Sroberto			if (peer_list[i]->flags & FLAG_PREFER) {
150854359Sroberto				typeprefer = peer_list[i];
150954359Sroberto				if (fabs(typeprefer->offset) < clock_max)
151054359Sroberto					pps_update = 1;
151154359Sroberto			}
151254359Sroberto		} else {
151354359Sroberto			if (peer_list[i] == sys_peer)
151454359Sroberto				sys_peer = 0;
151554359Sroberto		}
151654359Sroberto	}
151754359Sroberto
151854359Sroberto	/*
151954359Sroberto	 * Mitigation rules of the game. There are several types of
152054359Sroberto	 * peers that make a difference here: (1) prefer local peers
152154359Sroberto	 * (type REFCLK_LOCALCLOCK with FLAG_PREFER) or prefer modem
152254359Sroberto	 * peers (type REFCLK_NIST_ATOM etc with FLAG_PREFER), (2) pps peers
152354359Sroberto	 * (type REFCLK_ATOM_PPS), (3) remaining prefer peers (flag
152454359Sroberto	 * FLAG_PREFER), (4) the existing system peer, if any, (5) the
152554359Sroberto	 * head of the survivor list. Note that only one peer can be
152654359Sroberto	 * declared prefer. The order of preference is in the order
152754359Sroberto	 * stated. Note that all of these must be at the lowest stratum,
152854359Sroberto	 * i.e., the stratum of the head of the survivor list.
152954359Sroberto	 */
153054359Sroberto	osys_peer = sys_peer;
153154359Sroberto	if (typeprefer && (typeprefer->refclktype == REFCLK_LOCALCLOCK ||
153254359Sroberto		typeprefer->sstclktype == CTL_SST_TS_TELEPHONE || !typepps)) {
153354359Sroberto		sys_peer = typeprefer;
153454359Sroberto		sys_peer->status = CTL_PST_SEL_SYSPEER;
153554359Sroberto		sys_offset = sys_peer->offset;
153654359Sroberto		sys_epsil = sys_peer->variance;
153754359Sroberto#ifdef DEBUG
153854359Sroberto		if (debug > 1)
153954359Sroberto			printf("select: prefer offset %.6f\n", sys_offset);
154054359Sroberto#endif
154154359Sroberto	} else if (typepps && pps_update) {
154254359Sroberto		sys_peer = typepps;
154354359Sroberto		sys_peer->status = CTL_PST_SEL_PPS;
154454359Sroberto		sys_offset = sys_peer->offset;
154554359Sroberto		sys_epsil = sys_peer->variance;
154654359Sroberto		if (!pps_control)
154754359Sroberto			NLOG(NLOG_SYSEVENT) /* conditional syslog */
154854359Sroberto				msyslog(LOG_INFO, "pps sync enabled");
154954359Sroberto		pps_control = current_time;
155054359Sroberto#ifdef DEBUG
155154359Sroberto		if (debug > 1)
155254359Sroberto			printf("select: pps offset %.6f\n", sys_offset);
155354359Sroberto#endif
155454359Sroberto	} else {
155554359Sroberto		if (!typesystem)
155654359Sroberto			sys_peer = peer_list[0];
155754359Sroberto		sys_peer->status = CTL_PST_SEL_SYSPEER;
155854359Sroberto		sys_offset = clock_combine(peer_list, nlist);
155954359Sroberto		sys_epsil = sys_peer->variance + sys_maxd;
156054359Sroberto#ifdef DEBUG
156154359Sroberto		if (debug > 1)
156254359Sroberto			printf("select: combine offset %.6f\n",
156354359Sroberto			   sys_offset);
156454359Sroberto#endif
156554359Sroberto	}
156654359Sroberto	if (osys_peer != sys_peer)
156754359Sroberto		report_event(EVNT_PEERSTCHG, (struct peer *)0);
156854359Sroberto	clock_update();
156954359Sroberto}
157054359Sroberto
157154359Sroberto/*
157254359Sroberto * clock_combine - combine offsets from selected peers
157354359Sroberto */
157454359Srobertostatic double
157554359Srobertoclock_combine(
157654359Sroberto	struct peer **peers,
157754359Sroberto	int npeers
157854359Sroberto	)
157954359Sroberto{
158054359Sroberto	int i;
158154359Sroberto	double x, y, z;
158254359Sroberto	y = z = 0;
158354359Sroberto	for (i = 0; i < npeers; i++) {
158454359Sroberto		x = root_distance(peers[i]);
158554359Sroberto		y += 1. / x;
158654359Sroberto		z += peers[i]->offset / x;
158754359Sroberto	}
158854359Sroberto	return (z / y);
158954359Sroberto}
159054359Sroberto
159154359Sroberto/*
159254359Sroberto * root_distance - compute synchronization distance from peer to root
159354359Sroberto */
159454359Srobertostatic double
159554359Srobertoroot_distance(
159654359Sroberto	struct peer *peer
159754359Sroberto	)
159854359Sroberto{
159954359Sroberto	return ((fabs(peer->delay) + peer->rootdelay) / 2 +
160054359Sroberto		peer->rootdispersion + peer->disp +
160154359Sroberto		    SQRT(peer->variance) + CLOCK_PHI * (current_time -
160254359Sroberto		    peer->update));
160354359Sroberto}
160454359Sroberto
160554359Sroberto/*
160654359Sroberto * peer_xmit - send packet for persistent association.
160754359Sroberto */
160854359Srobertostatic void
160954359Srobertopeer_xmit(
161054359Sroberto	struct peer *peer	/* peer structure pointer */
161154359Sroberto	)
161254359Sroberto{
161354359Sroberto	struct pkt xpkt;
161454359Sroberto	int find_rtt = (peer->cast_flags & MDF_MCAST) &&
161554359Sroberto		peer->hmode != MODE_BROADCAST;
161654359Sroberto	int sendlen;
161754359Sroberto
161854359Sroberto	/*
161954359Sroberto	 * Initialize protocol fields.
162054359Sroberto	 */
162154359Sroberto	xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
162254359Sroberto		peer->version, peer->hmode);
162354359Sroberto	xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
162454359Sroberto	xpkt.ppoll = peer->hpoll;
162554359Sroberto	xpkt.precision = sys_precision;
162654359Sroberto	xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
162754359Sroberto	xpkt.rootdispersion = HTONS_FP(DTOUFP(sys_rootdispersion +
162854359Sroberto		LOGTOD(sys_precision)));
162954359Sroberto	xpkt.refid = sys_refid;
163054359Sroberto	HTONL_FP(&sys_reftime, &xpkt.reftime);
163154359Sroberto	HTONL_FP(&peer->org, &xpkt.org);
163254359Sroberto	HTONL_FP(&peer->rec, &xpkt.rec);
163354359Sroberto
163454359Sroberto	/*
163554359Sroberto	 * Authenticate the packet if enabled and either configured or
163654359Sroberto	 * the previous packet was authenticated. If for some reason the
163754359Sroberto	 * key associated with the key identifier is not in the key
163854359Sroberto	 * cache, then honk key zero.
163954359Sroberto	 */
164054359Sroberto	sendlen = LEN_PKT_NOMAC;
164154359Sroberto	if (peer->flags & FLAG_AUTHENABLE) {
164254359Sroberto		u_long xkeyid;
164354359Sroberto		l_fp xmt_tx;
164454359Sroberto
164554359Sroberto		/*
164654359Sroberto		 * Transmit encrypted packet compensated for the
164754359Sroberto		 * encryption delay.
164854359Sroberto		 */
164954359Sroberto#ifdef MD5
165054359Sroberto		if (peer->flags & FLAG_SKEY) {
165154359Sroberto
165254359Sroberto			/*
165354359Sroberto			 * In SKEY mode, allocate and initialize a key list if
165454359Sroberto			 * not already done. Then, use the list in inverse
165554359Sroberto			 * order, discarding keys once used. Keep the latest
165654359Sroberto			 * key around until the next one, so clients can use
165754359Sroberto			 * client/server packets to compute propagation delay.
165854359Sroberto			 * Note we have to wait until the receive side of the
165954359Sroberto			 * socket is bound and the server address confirmed.
166054359Sroberto			 */
166154359Sroberto			if (ntohl(peer->dstadr->sin.sin_addr.s_addr) == 0 &&
166254359Sroberto				ntohl(peer->dstadr->bcast.sin_addr.s_addr) == 0)
166354359Sroberto				peer->keyid = 0;
166454359Sroberto			else {
166554359Sroberto				 if (peer->keylist == 0) {
166654359Sroberto					make_keylist(peer);
166754359Sroberto				} else {
166854359Sroberto					authtrust(peer->keylist[peer->keynumber], 0);
166954359Sroberto					if (peer->keynumber == 0)
167054359Sroberto						make_keylist(peer);
167154359Sroberto					else {
167254359Sroberto						peer->keynumber--;
167354359Sroberto						xkeyid = peer->keylist[peer->keynumber];
167454359Sroberto						if (!authistrusted(xkeyid))
167554359Sroberto							make_keylist(peer);
167654359Sroberto					}
167754359Sroberto				}
167854359Sroberto				peer->keyid = peer->keylist[peer->keynumber];
167954359Sroberto				xpkt.keyid1 = htonl(2 * sizeof(u_int32));
168054359Sroberto				xpkt.keyid2 = htonl(sys_private);
168154359Sroberto				sendlen += 2 * sizeof(u_int32);
168254359Sroberto			}
168354359Sroberto		}
168454359Sroberto#endif /* MD5 */
168554359Sroberto		xkeyid = peer->keyid;
168654359Sroberto		get_systime(&peer->xmt);
168754359Sroberto		L_ADD(&peer->xmt, &sys_authdelay);
168854359Sroberto		HTONL_FP(&peer->xmt, &xpkt.xmt);
168954359Sroberto		sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
169054359Sroberto		get_systime(&xmt_tx);
169154359Sroberto		sendpkt(&peer->srcadr, find_rtt ? any_interface :
169254359Sroberto			peer->dstadr,
169354359Sroberto			((peer->cast_flags & MDF_MCAST) && !find_rtt) ?
169454359Sroberto			((peer->cast_flags & MDF_ACAST) ? -7 : peer->ttl) : -7,
169554359Sroberto			&xpkt, sendlen);
169654359Sroberto
169754359Sroberto		/*
169854359Sroberto		 * Calculate the encryption delay. Keep the minimum over
169954359Sroberto		 * the latest two samples.
170054359Sroberto		 */
170154359Sroberto		L_SUB(&xmt_tx, &peer->xmt);
170254359Sroberto		L_ADD(&xmt_tx, &sys_authdelay);
170354359Sroberto		sys_authdly[1] = sys_authdly[0];
170454359Sroberto		sys_authdly[0] = xmt_tx.l_uf;
170554359Sroberto		if (sys_authdly[0] < sys_authdly[1])
170654359Sroberto			sys_authdelay.l_uf = sys_authdly[0];
170754359Sroberto		else
170854359Sroberto			sys_authdelay.l_uf = sys_authdly[1];
170954359Sroberto		peer->sent++;
171054359Sroberto#ifdef DEBUG
171154359Sroberto		if (debug)
171254359Sroberto			printf(
171354359Sroberto				"transmit: at %ld to %s mode %d keyid %08lx index %d\n",
171454359Sroberto				current_time, ntoa(&peer->srcadr),
171554359Sroberto				peer->hmode, xkeyid, peer->keynumber);
171654359Sroberto#endif
171754359Sroberto	} else {
171854359Sroberto		/*
171954359Sroberto		 * Transmit non-authenticated packet.
172054359Sroberto		 */
172154359Sroberto		get_systime(&(peer->xmt));
172254359Sroberto		HTONL_FP(&peer->xmt, &xpkt.xmt);
172354359Sroberto		sendpkt(&(peer->srcadr), find_rtt ? any_interface :
172454359Sroberto			peer->dstadr,
172554359Sroberto			((peer->cast_flags & MDF_MCAST) && !find_rtt) ?
172654359Sroberto			((peer->cast_flags & MDF_ACAST) ? -7 : peer->ttl) : -8,
172754359Sroberto			&xpkt, sendlen);
172854359Sroberto		peer->sent++;
172954359Sroberto#ifdef DEBUG
173054359Sroberto		if (debug)
173154359Sroberto			printf("transmit: at %ld to %s mode %d\n",
173254359Sroberto				current_time, ntoa(&peer->srcadr),
173354359Sroberto				peer->hmode);
173454359Sroberto#endif
173554359Sroberto	}
173654359Sroberto}
173754359Sroberto
173854359Sroberto/*
173954359Sroberto * fast_xmit - Send packet for nonpersistent association.
174054359Sroberto */
174154359Srobertostatic void
174254359Srobertofast_xmit(
174354359Sroberto	struct recvbuf *rbufp,	/* receive packet pointer */
174454359Sroberto	int xmode,		/* transmit mode */
174554359Sroberto	u_long xkeyid		/* transmit key ID */
174654359Sroberto	)
174754359Sroberto{
174854359Sroberto	struct pkt xpkt;
174954359Sroberto	struct pkt *rpkt;
175054359Sroberto	int sendlen;
175154359Sroberto	l_fp xmt_ts;
175254359Sroberto
175354359Sroberto	/*
175454359Sroberto	 * Initialize transmit packet header fields in the receive
175554359Sroberto	 * buffer provided. We leave some fields intact as received.
175654359Sroberto	 */
175754359Sroberto	rpkt = &rbufp->recv_pkt;
175854359Sroberto	xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
175954359Sroberto		PKT_VERSION(rpkt->li_vn_mode), xmode);
176054359Sroberto	xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
176154359Sroberto	xpkt.ppoll = rpkt->ppoll;
176254359Sroberto	xpkt.precision = sys_precision;
176354359Sroberto	xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
176454359Sroberto	xpkt.rootdispersion = HTONS_FP(DTOUFP(sys_rootdispersion +
176554359Sroberto		LOGTOD(sys_precision)));
176654359Sroberto	xpkt.refid = sys_refid;
176754359Sroberto	HTONL_FP(&sys_reftime, &xpkt.reftime);
176854359Sroberto	xpkt.org = rpkt->xmt;
176954359Sroberto	HTONL_FP(&rbufp->recv_time, &xpkt.rec);
177054359Sroberto	sendlen = LEN_PKT_NOMAC;
177154359Sroberto	if (rbufp->recv_length > sendlen) {
177254359Sroberto		l_fp xmt_tx;
177354359Sroberto
177454359Sroberto		/*
177554359Sroberto		 * Transmit encrypted packet compensated for the
177654359Sroberto		 * encryption delay.
177754359Sroberto		 */
177854359Sroberto		if (xkeyid > NTP_MAXKEY) {
177954359Sroberto			xpkt.keyid1 = htonl(2 * sizeof(u_int32));
178054359Sroberto			xpkt.keyid2 = htonl(sys_private);
178154359Sroberto			sendlen += 2 * sizeof(u_int32);
178254359Sroberto		}
178354359Sroberto		get_systime(&xmt_ts);
178454359Sroberto		L_ADD(&xmt_ts, &sys_authdelay);
178554359Sroberto		HTONL_FP(&xmt_ts, &xpkt.xmt);
178654359Sroberto		sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
178754359Sroberto		get_systime(&xmt_tx);
178854359Sroberto		sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, -9, &xpkt,
178954359Sroberto			sendlen);
179054359Sroberto
179154359Sroberto		/*
179254359Sroberto		 * Calculate the encryption delay. Keep the minimum over
179354359Sroberto		 * the latest two samples.
179454359Sroberto		 */
179554359Sroberto		L_SUB(&xmt_tx, &xmt_ts);
179654359Sroberto		L_ADD(&xmt_tx, &sys_authdelay);
179754359Sroberto		sys_authdly[1] = sys_authdly[0];
179854359Sroberto		sys_authdly[0] = xmt_tx.l_uf;
179954359Sroberto		if (sys_authdly[0] < sys_authdly[1])
180054359Sroberto			sys_authdelay.l_uf = sys_authdly[0];
180154359Sroberto		else
180254359Sroberto			sys_authdelay.l_uf = sys_authdly[1];
180354359Sroberto#ifdef DEBUG
180454359Sroberto		if (debug)
180554359Sroberto			printf(
180654359Sroberto				"transmit: at %ld to %s mode %d keyid %08lx\n",
180754359Sroberto							current_time, ntoa(&rbufp->recv_srcadr),
180854359Sroberto							xmode, xkeyid);
180954359Sroberto#endif
181054359Sroberto	} else {
181154359Sroberto
181254359Sroberto		/*
181354359Sroberto		 * Transmit non-authenticated packet.
181454359Sroberto		 */
181554359Sroberto		get_systime(&xmt_ts);
181654359Sroberto		HTONL_FP(&xmt_ts, &xpkt.xmt);
181754359Sroberto		sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, -10, &xpkt,
181854359Sroberto			sendlen);
181954359Sroberto#ifdef DEBUG
182054359Sroberto		if (debug)
182154359Sroberto			printf("transmit: at %ld to %s mode %d\n",
182254359Sroberto				current_time, ntoa(&rbufp->recv_srcadr),
182354359Sroberto				xmode);
182454359Sroberto#endif
182554359Sroberto	}
182654359Sroberto}
182754359Sroberto
182854359Sroberto#ifdef MD5
182954359Sroberto/*
183054359Sroberto * Compute key list
183154359Sroberto */
183254359Srobertostatic void
183354359Srobertomake_keylist(
183454359Sroberto	struct peer *peer
183554359Sroberto	)
183654359Sroberto{
183754359Sroberto	int i;
183854359Sroberto	u_long keyid;
183954359Sroberto	u_long ltemp;
184054359Sroberto
184154359Sroberto	/*
184254359Sroberto	 * Allocate the key list if necessary.
184354359Sroberto	 */
184454359Sroberto	if (peer->keylist == 0)
184554359Sroberto		peer->keylist = (u_long *)emalloc(sizeof(u_long) *
184654359Sroberto		    NTP_MAXSESSION);
184754359Sroberto
184854359Sroberto	/*
184954359Sroberto	 * Generate an initial key ID which is unique and greater than
185054359Sroberto	 * NTP_MAXKEY.
185154359Sroberto	 */
185254359Sroberto	while (1) {
185354359Sroberto		keyid = (u_long)RANDOM & 0xffffffff;
185454359Sroberto		if (keyid <= NTP_MAXKEY)
185554359Sroberto			continue;
185654359Sroberto		if (authhavekey(keyid))
185754359Sroberto			continue;
185854359Sroberto		break;
185954359Sroberto	}
186054359Sroberto
186154359Sroberto	/*
186254359Sroberto	 * Generate up to NTP_MAXSESSION session keys. Stop if the
186354359Sroberto	 * next one would not be unique or not a session key ID or if
186454359Sroberto	 * it would expire before the next poll.
186554359Sroberto	 */
186654359Sroberto	ltemp = sys_automax;
186754359Sroberto	for (i = 0; i < NTP_MAXSESSION; i++) {
186854359Sroberto		peer->keylist[i] = keyid;
186954359Sroberto		peer->keynumber = i;
187054359Sroberto		keyid = session_key(
187154359Sroberto			ntohl(peer->dstadr->sin.sin_addr.s_addr),
187254359Sroberto			(peer->hmode == MODE_BROADCAST || (peer->flags &
187354359Sroberto			FLAG_MCAST2)) ?
187454359Sroberto			ntohl(peer->dstadr->bcast.sin_addr.s_addr):
187554359Sroberto			ntohl(peer->srcadr.sin_addr.s_addr),
187654359Sroberto			keyid, ltemp);
187754359Sroberto		ltemp -= 1 << peer->hpoll;
187854359Sroberto		if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
187954359Sroberto			ltemp <= (1 << (peer->hpoll + 1)))
188054359Sroberto			break;
188154359Sroberto	}
188254359Sroberto}
188354359Sroberto#endif /* MD5 */
188454359Sroberto
188554359Sroberto/*
188654359Sroberto * Find the precision of this particular machine
188754359Sroberto */
188854359Sroberto#define DUSECS	1000000 /* us in a s */
188954359Sroberto#define HUSECS	(1 << 20) /* approx DUSECS for shifting etc */
189054359Sroberto#define MINSTEP 5	/* minimum clock increment (us) */
189154359Sroberto#define MAXSTEP 20000	/* maximum clock increment (us) */
189254359Sroberto#define MINLOOPS 5	/* minimum number of step samples */
189354359Sroberto
189454359Sroberto/*
189554359Sroberto * This routine calculates the differences between successive calls to
189654359Sroberto * gettimeofday(). If a difference is less than zero, the us field
189754359Sroberto * has rolled over to the next second, so we add a second in us. If
189854359Sroberto * the difference is greater than zero and less than MINSTEP, the
189954359Sroberto * clock has been advanced by a small amount to avoid standing still.
190054359Sroberto * If the clock has advanced by a greater amount, then a timer interrupt
190154359Sroberto * has occurred and this amount represents the precision of the clock.
190254359Sroberto * In order to guard against spurious values, which could occur if we
190354359Sroberto * happen to hit a fat interrupt, we do this for MINLOOPS times and
190454359Sroberto * keep the minimum value obtained.
190554359Sroberto */
190654359Srobertoint
190754359Srobertodefault_get_precision(void)
190854359Sroberto{
190954359Sroberto	struct timeval tp;
191054359Sroberto#if !defined(SYS_WINNT) && !defined(VMS) && !defined(_SEQUENT_)
191154359Sroberto	struct timezone tzp;
191254359Sroberto#elif defined(VMS) || defined(_SEQUENT_)
191354359Sroberto	struct timezone {
191454359Sroberto		int tz_minuteswest;
191554359Sroberto		int tz_dsttime;
191654359Sroberto	} tzp;
191754359Sroberto#endif /* defined(VMS) || defined(_SEQUENT_) */
191854359Sroberto	long last;
191954359Sroberto	int i;
192054359Sroberto	long diff;
192154359Sroberto	long val;
192254359Sroberto	long usec;
192354359Sroberto#ifdef HAVE_GETCLOCK
192454359Sroberto	struct timespec ts;
192554359Sroberto#endif
192654359Sroberto#if defined(__FreeBSD__) && __FreeBSD__ >= 3
192754359Sroberto	u_long freq;
192854359Sroberto	int j;
192954359Sroberto
193054359Sroberto	/* Try to see if we can find the frequency of of the counter
193154359Sroberto	 * which drives our timekeeping
193254359Sroberto	 */
193354359Sroberto	j = sizeof freq;
193454359Sroberto	i = sysctlbyname("kern.timecounter.frequency",
193554359Sroberto			&freq, &j , 0, 0);
193654359Sroberto	if (i)
193754359Sroberto		i = sysctlbyname("machdep.tsc_freq",
193854359Sroberto					&freq, &j , 0, 0);
193954359Sroberto	if (i)
194054359Sroberto		i = sysctlbyname("machdep.i586_freq",
194154359Sroberto					&freq, &j , 0, 0);
194254359Sroberto	if (i)
194354359Sroberto		i = sysctlbyname("machdep.i8254_freq",
194454359Sroberto					&freq, &j , 0, 0);
194554359Sroberto	if (!i) {
194654359Sroberto		for (i = 1; freq ; i--)
194754359Sroberto			freq >>= 1;
194854359Sroberto		return (i);
194954359Sroberto	}
195054359Sroberto#endif
195154359Sroberto	usec = 0;
195254359Sroberto	val = MAXSTEP;
195354359Sroberto#ifdef HAVE_GETCLOCK
195454359Sroberto	(void) getclock(TIMEOFDAY, &ts);
195554359Sroberto	tp.tv_sec = ts.tv_sec;
195654359Sroberto	tp.tv_usec = ts.tv_nsec / 1000;
195754359Sroberto#else /*  not HAVE_GETCLOCK */
195854359Sroberto	GETTIMEOFDAY(&tp, &tzp);
195954359Sroberto#endif /* not HAVE_GETCLOCK */
196054359Sroberto	last = tp.tv_usec;
196154359Sroberto	for (i = 0; i < MINLOOPS && usec < HUSECS;) {
196254359Sroberto#ifdef HAVE_GETCLOCK
196354359Sroberto		(void) getclock(TIMEOFDAY, &ts);
196454359Sroberto		tp.tv_sec = ts.tv_sec;
196554359Sroberto		tp.tv_usec = ts.tv_nsec / 1000;
196654359Sroberto#else /*  not HAVE_GETCLOCK */
196754359Sroberto		GETTIMEOFDAY(&tp, &tzp);
196854359Sroberto#endif /* not HAVE_GETCLOCK */
196954359Sroberto		diff = tp.tv_usec - last;
197054359Sroberto		last = tp.tv_usec;
197154359Sroberto		if (diff < 0)
197254359Sroberto			diff += DUSECS;
197354359Sroberto		usec += diff;
197454359Sroberto		if (diff > MINSTEP) {
197554359Sroberto			i++;
197654359Sroberto			if (diff < val)
197754359Sroberto				val = diff;
197854359Sroberto		}
197954359Sroberto	}
198054359Sroberto	NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
198154359Sroberto		msyslog(LOG_INFO, "precision = %ld usec", val);
198254359Sroberto	if (usec >= HUSECS)
198354359Sroberto		val = MINSTEP;	/* val <= MINSTEP; fast machine */
198454359Sroberto	diff = HUSECS;
198554359Sroberto	for (i = 0; diff > val; i--)
198654359Sroberto		diff >>= 1;
198754359Sroberto	return (i);
198854359Sroberto}
198954359Sroberto
199054359Sroberto/*
199154359Sroberto * init_proto - initialize the protocol module's data
199254359Sroberto */
199354359Srobertovoid
199454359Srobertoinit_proto(void)
199554359Sroberto{
199654359Sroberto	l_fp dummy;
199754359Sroberto
199854359Sroberto	/*
199954359Sroberto	 * Fill in the sys_* stuff.  Default is don't listen to
200054359Sroberto	 * broadcasting, authenticate.
200154359Sroberto	 */
200254359Sroberto	sys_leap = LEAP_NOTINSYNC;
200354359Sroberto	sys_stratum = STRATUM_UNSPEC;
200454359Sroberto	sys_precision = (s_char)default_get_precision();
200554359Sroberto	sys_rootdelay = 0;
200654359Sroberto	sys_rootdispersion = 0;
200754359Sroberto	sys_refid = 0;
200854359Sroberto	L_CLR(&sys_reftime);
200954359Sroberto	sys_peer = 0;
201054359Sroberto	get_systime(&dummy);
201154359Sroberto	sys_bclient = 0;
201254359Sroberto	sys_bdelay = DEFBROADDELAY;
201354359Sroberto#if defined(DES) || defined(MD5)
201454359Sroberto	sys_authenticate = 1;
201554359Sroberto#else
201654359Sroberto	sys_authenticate = 0;
201754359Sroberto#endif
201854359Sroberto	L_CLR(&sys_authdelay);
201954359Sroberto	sys_authdly[0] = sys_authdly[1] = 0;
202054359Sroberto	sys_stattime = 0;
202154359Sroberto	sys_badstratum = 0;
202254359Sroberto	sys_oldversionpkt = 0;
202354359Sroberto	sys_newversionpkt = 0;
202454359Sroberto	sys_badlength = 0;
202554359Sroberto	sys_unknownversion = 0;
202654359Sroberto	sys_processed = 0;
202754359Sroberto	sys_badauth = 0;
202854359Sroberto	sys_manycastserver = 0;
202954359Sroberto	sys_automax = 1 << NTP_AUTOMAX;
203054359Sroberto
203154359Sroberto	/*
203254359Sroberto	 * Default these to enable
203354359Sroberto	 */
203454359Sroberto	ntp_enable = 1;
203554359Sroberto#ifndef KERNEL_FLL_BUG
203654359Sroberto	kern_enable = 1;
203754359Sroberto#endif
203854359Sroberto	msyslog(LOG_DEBUG, "kern_enable is %d", kern_enable);
203954359Sroberto	stats_control = 1;
204054359Sroberto
204154359Sroberto	/*
204254359Sroberto	 * Some system clocks should only be adjusted in 10ms increments.
204354359Sroberto	 */
204454359Sroberto#if defined RELIANTUNIX_CLOCK
204554359Sroberto	systime_10ms_ticks = 1;			/* Reliant UNIX */
204654359Sroberto#elif defined SCO5_CLOCK
204754359Sroberto	if (sys_precision >= (s_char)-10)	/* pre- SCO OpenServer 5.0.6 */
204854359Sroberto		systime_10ms_ticks = 1;
204954359Sroberto#endif
205054359Sroberto	if (systime_10ms_ticks)
205154359Sroberto		msyslog(LOG_INFO, "using 10ms tick adjustments");
205254359Sroberto}
205354359Sroberto
205454359Sroberto
205554359Sroberto/*
205654359Sroberto * proto_config - configure the protocol module
205754359Sroberto */
205854359Srobertovoid
205954359Srobertoproto_config(
206054359Sroberto	int item,
206154359Sroberto	u_long value,
206254359Sroberto	double dvalue
206354359Sroberto	)
206454359Sroberto{
206554359Sroberto	/*
206654359Sroberto	 * Figure out what he wants to change, then do it
206754359Sroberto	 */
206854359Sroberto	switch (item) {
206954359Sroberto		case PROTO_KERNEL:
207054359Sroberto		/*
207154359Sroberto		 * Turn on/off kernel discipline
207254359Sroberto		 */
207354359Sroberto		kern_enable = (int)value;
207454359Sroberto		break;
207554359Sroberto
207654359Sroberto		case PROTO_NTP:
207754359Sroberto		/*
207854359Sroberto		 * Turn on/off clock discipline
207954359Sroberto		 */
208054359Sroberto		ntp_enable = (int)value;
208154359Sroberto		break;
208254359Sroberto
208354359Sroberto		case PROTO_MONITOR:
208454359Sroberto		/*
208554359Sroberto		 * Turn on/off monitoring
208654359Sroberto		 */
208754359Sroberto		if (value)
208854359Sroberto			mon_start(MON_ON);
208954359Sroberto		else
209054359Sroberto			mon_stop(MON_ON);
209154359Sroberto		break;
209254359Sroberto
209354359Sroberto		case PROTO_FILEGEN:
209454359Sroberto		/*
209554359Sroberto		 * Turn on/off statistics
209654359Sroberto		 */
209754359Sroberto		stats_control = (int)value;
209854359Sroberto		break;
209954359Sroberto
210054359Sroberto		case PROTO_BROADCLIENT:
210154359Sroberto		/*
210254359Sroberto		 * Turn on/off facility to listen to broadcasts
210354359Sroberto		 */
210454359Sroberto		sys_bclient = (int)value;
210554359Sroberto		if (value)
210654359Sroberto			io_setbclient();
210754359Sroberto		else
210854359Sroberto			io_unsetbclient();
210954359Sroberto		break;
211054359Sroberto
211154359Sroberto		case PROTO_MULTICAST_ADD:
211254359Sroberto		/*
211354359Sroberto		 * Add muliticast group address
211454359Sroberto		 */
211554359Sroberto		io_multicast_add(value);
211654359Sroberto		break;
211754359Sroberto
211854359Sroberto		case PROTO_MULTICAST_DEL:
211954359Sroberto		/*
212054359Sroberto		 * Delete multicast group address
212154359Sroberto		 */
212254359Sroberto		io_multicast_del(value);
212354359Sroberto		break;
212454359Sroberto
212554359Sroberto		case PROTO_BROADDELAY:
212654359Sroberto		/*
212754359Sroberto		 * Set default broadcast delay
212854359Sroberto		 */
212954359Sroberto		sys_bdelay = dvalue;
213054359Sroberto		break;
213154359Sroberto
213254359Sroberto		case PROTO_AUTHENTICATE:
213354359Sroberto		/*
213454359Sroberto		 * Specify the use of authenticated data
213554359Sroberto		 */
213654359Sroberto		sys_authenticate = (int)value;
213754359Sroberto		break;
213854359Sroberto
213954359Sroberto		default:
214054359Sroberto		/*
214154359Sroberto		 * Log this error
214254359Sroberto		 */
214354359Sroberto		msyslog(LOG_ERR, "proto_config: illegal item %d, value %ld",
214454359Sroberto			item, value);
214554359Sroberto		break;
214654359Sroberto	}
214754359Sroberto}
214854359Sroberto
214954359Sroberto
215054359Sroberto/*
215154359Sroberto * proto_clr_stats - clear protocol stat counters
215254359Sroberto */
215354359Srobertovoid
215454359Srobertoproto_clr_stats(void)
215554359Sroberto{
215654359Sroberto	sys_badstratum = 0;
215754359Sroberto	sys_oldversionpkt = 0;
215854359Sroberto	sys_newversionpkt = 0;
215954359Sroberto	sys_unknownversion = 0;
216054359Sroberto	sys_badlength = 0;
216154359Sroberto	sys_processed = 0;
216254359Sroberto	sys_badauth = 0;
216354359Sroberto	sys_stattime = current_time;
216454359Sroberto	sys_limitrejected = 0;
216554359Sroberto}
2166