#define NTP_MAXKEY 65535 /* maximum authentication key number */
#define NTP_MAXSESSION 100 /* maximum session key list entries */
#define NTP_MAXEXTEN 1024 /* maximum extension field size */
+#define NTP_MAXSTRLEN 256 /* maximum string length */
#define NTP_AUTOMAX 13 /* log2 default max session key lifetime */
#define KEY_REVOKE 16 /* log2 default key revoke timeout */
#define NTP_FWEIGHT .5 /* clock filter weight */
#define BURST_INTERVAL2 1 /* succeeding interburst intervals (log2) */
#define HUFFPUFF 900 /* huff-n'-puff sample interval (s) */
#define HYST .5 /* anti-clockhop hysteresis */
-#define HYST_TC .5 /* anti-clockhop hysteresis decay factor */
+#define HYST_TC .875 /* anti-clockhop hysteresis decay factor */
/*
* Operations for jitter calculations (these use doubles).
u_char *digest; /* message digest (EVP_MD) */
keyid_t pkeyid; /* previous key ID */
keyid_t pcookie; /* peer cookie */
- keyid_t hcookie; /* host cookie */
struct value cookval; /* cookie values */
struct value recval; /* receive autokey values */
struct value tai_leap; /* leapseconds values */
#define CP_HOST 40
#define CP_CERTIF 41
#define CP_SESKEY 42
-#define CP_SASKEY 43
-#define CP_INITSEQ 44
-#define CP_INITKEY 45
-#define CP_INITTSP 46
-#define CP_DIGEST 47
+#define CP_INITSEQ 43
+#define CP_INITKEY 44
+#define CP_INITTSP 45
+#define CP_DIGEST 46
#define CP_MAXCODE CP_DIGEST
#else
#define CP_MAXCODE CP_VARLIST
/* ntp_timer.c */
extern volatile int alarm_flag; /* alarm flag */
-extern u_long sys_revoke; /* keys revoke timeout */
+extern u_char sys_revoke; /* keys revoke timeout (log2 s) */
extern volatile u_long alarm_overflow;
extern u_long current_time; /* current time (s) */
extern u_long timer_timereset;
#ifdef OPENSSL
case CONFIG_REVOKE:
if (ntokens >= 2)
- sys_revoke = 1 << max(atoi(tokens[1]), 10);
+ sys_revoke = max(atoi(tokens[1]), KEY_REVOKE);
break;
case CONFIG_AUTOMAX:
{ CP_FLAGS, RO, "flags" }, /* 38 */
{ CP_HOST, RO, "hostname" }, /* 39 */
{ CP_CERTIF, RO, "certificate" }, /* 40 */
- { CP_SESKEY, RO, "pcookie" }, /* 41 */
- { CP_SASKEY, RO, "hcookie" }, /* 42 */
- { CP_INITSEQ, RO, "initsequence" }, /* 43 */
- { CP_INITKEY, RO, "initkey" }, /* 44 */
- { CP_INITTSP, RO, "timestamp" }, /* 45 */
- { CP_DIGEST, RO, "signature" }, /* 46 */
+ { CP_SESKEY, RO, "cookie" }, /* 41 */
+ { CP_INITSEQ, RO, "initsequence" }, /* 42 */
+ { CP_INITKEY, RO, "initkey" }, /* 43 */
+ { CP_INITTSP, RO, "timestamp" }, /* 44 */
+ { CP_DIGEST, RO, "signature" }, /* 45 */
#endif /* OPENSSL */
- { 0, EOV, "" } /* 47 */
+ { 0, EOV, "" } /* 46 */
};
if (peer->pcookie != 0)
ctl_puthex(peer_var[CP_SESKEY].text,
peer->pcookie);
- if (peer->hcookie != 0)
- ctl_puthex(peer_var[CP_SASKEY].text,
- peer->hcookie);
break;
case CP_INITSEQ:
*/
#define TAI_1972 10 /* initial TAI offset (s) */
#define MAX_LEAP 100 /* max UTC leapseconds (s) */
-#define MAX_LINLEN 1024 /* max line length */
#define MIN_HOSTLEN 4 /* min host name length */
#define MAX_HOSTLEN 256 /* max host name length */
-#define MAX_STATLEN 256 /* max statistics string length */
#define DIGESTNAME "MD5" /* message digest algorithm name */
#define VALUE_LEN (6 * 4) /* min response field length */
*/
lifetime = min(sys_automax, NTP_MAXSESSION * (1 <<
(peer->kpoll)));
- peer->hcookie = session_key(&dstadr->sin, &peer->srcadr, 0,
- sys_private, 0);
if (peer->hmode == MODE_BROADCAST)
cookie = 0;
else
u_int code; /* extension field opcode */
u_int vallen; /* value length */
u_int siglen; /* signature length */
- u_char statstr[MAX_STATLEN]; /* statistics for filegen */
+ u_char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
keyid_t cookie; /* crumbles */
int j, rval;
u_int32 temp32;
/*
* Install the new table if there is no stored
- * table or the new table is more recent that
+ * table or the new table is more recent than
* the stored table. Since a filestamp may have
* changed, recompute the signatures.
*/
tstamp_t fstamp; /* filestamp */
u_int vallen; /* value length */
u_int siglen; /* signature length */
- u_char statstr[MAX_STATLEN];
+ u_char statstr[NTP_MAXSTRLEN];
u_int code, len;
int rval;
int i;
crypto_sign(void)
{
EVP_MD_CTX ctx; /* signature context */
- u_char statstr[MAX_STATLEN]; /* statistics for filegen */
+ u_char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
l_fp tstamp; /* NTP timestamp */
u_int len;
EVP_PKEY *pkey; /* public/private key */
char filename[MAXFILENAME]; /* name of rsa key file */
char linkname[MAXFILENAME]; /* file link (for filestamp) */
- u_char statstr[MAX_STATLEN]; /* statistics for filegen */
+ u_char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
tstamp_t fstamp; /* filestamp */
int rval;
u_char *ptr;
FILE *str; /* file handle */
char filename[MAXFILENAME]; /* name of certificate file */
char linkname[MAXFILENAME]; /* file link (for filestamp) */
- u_char statstr[MAX_STATLEN]; /* statistics for filegen */
+ u_char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
tstamp_t fstamp; /* filestamp */
int rval;
u_int len;
)
{
FILE *str; /* file handle */
- u_char buf[MAX_LINLEN]; /* file line buffer */
+ u_char buf[NTP_MAXSTRLEN]; /* file line buffer */
u_int leapsec[MAX_LEAP]; /* NTP time at leaps */
u_int offset; /* offset at leap (s) */
char filename[MAXFILENAME]; /* name of leapseconds file */
char linkname[MAXFILENAME]; /* file link (for filestamp) */
- u_char statstr[MAX_STATLEN]; /* statistics for filegen */
+ u_char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
tstamp_t fstamp; /* filestamp */
u_int len;
u_char *ptr;
i = 0;
rval = XEVNT_OK;
while (i < MAX_LEAP) {
- ptr = fgets(buf, MAX_LINLEN - 1, str);
+ ptr = fgets(buf, NTP_MAXSTRLEN - 1, str);
if (ptr == NULL)
break;
if (strlen(buf) < 1)
#define CLOCK_PGATE 4. /* poll-adjust gate */
#define CLOCK_ALLAN 1024. /* min Allan intercept (s) */
#define CLOCK_ADF 1e11 /* Allan deviation factor */
+#define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */
/*
* Clock discipline state machine. This is used to control the
* also a signal for the external clock driver to discipline the system
* clock.
*/
-#define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */
-
/*
* Program variables that can be tinkered.
*/
/*
* Compute the FLL and PLL frequency adjustments
* conditioned on intricate weighting factors.
- * For the FLL, the averaging interval is
- * clamped to a minimum of 1024 s and the gain
- * is decreased from unity for mu above 1024 s
- * to zero below 256 s. For the PLL, the
- * averaging interval is clamped not to exceed
- * the sustem poll interval. No gain factor is
- * necessary, since the frequency steering above
- * 1024 s is negligible. Particularly for the
+ * The gain factors depend on the poll interval
+ * and Allan intercept. For the FLL, the
+ * averaging interval is clamped to a minimum of
+ * 1024 s and the gain increased in stages from
+ * zero for poll intervals below half the Allan
+ * intercept to unity above twice the Allan
+ * intercept. For the PLL, the averaging
+ * interval is clamped not to exceed the poll
+ * interval. No gain factor is necessary, since
+ * the frequency steering above the Allan
+ * intercept is negligible. Particularly for the
* PLL, these measures allow oversampling, but
* not undersampling and insure stability even
* when the rules of fair engagement are broken.
*/
+ dtemp = ULOGTOD(sys_poll);
+ if (dtemp >= 2 * allan_xpt)
+ etemp = 1.;
+ else if (dtemp >= allan_xpt)
+ etemp = .5;
+ else if (dtemp > allan_xpt / 2)
+ etemp = .125;
+ else
+ etemp = 0;
dtemp = max(mu, allan_xpt);
- etemp = min(max(0, mu - CLOCK_MINSEC) /
- allan_xpt, 1.);
flladj = fp_offset * etemp / (dtemp *
CLOCK_AVG);
dtemp = ULOGTOD(SHIFT_PLL + 2 + sys_poll);
)
{
double adjustment;
+ double dtemp, etemp;
/*
* Update the dispersion since the last update. In contrast to
sys_peer->flags & FLAG_PREFER)
return;
}
- adjustment = clock_offset / ULOGTOD(SHIFT_PLL + sys_poll);
+
+ /*
+ * This ugly bit of business is necessary in order to move the
+ * poll higher during and after the transition between PLL and
+ * FLL modes.
+ */
+ dtemp = ULOGTOD(sys_poll);
+ if (dtemp >= 2 * allan_xpt)
+ etemp = 32.;
+ else if (dtemp >= allan_xpt)
+ etemp = 16.;
+ else if (dtemp > allan_xpt / 2)
+ etemp = 8;
+ else
+ etemp = 1;
+ adjustment = clock_offset / (etemp * ULOGTOD(SHIFT_PLL +
+ sys_poll));
clock_offset -= adjustment;
adj_systime(adjustment + drift_comp);
}
)
{
int hash;
+ u_char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
+#ifdef OPENSSL
+ if (peer_to_remove->flags & FLAG_SKEY) {
+ sprintf(statstr, "unpeer %d", peer_to_remove->associd);
+ record_crypto_stats(&peer_to_remove->srcadr, statstr);
+#ifdef DEBUG
+ if (debug)
+ printf("peer: %s\n", statstr);
+#endif
+ }
+#endif /* OPENSSL */
peer_associations--;
#ifdef DEBUG
if (debug)
peer->version = (u_char)version;
peer->minpoll = (u_char)minpoll;
peer->maxpoll = (u_char)maxpoll;
- peer->hpoll = peer->kpoll = peer->minpoll;
- peer->ppoll = peer->maxpoll;
peer->flags = flags | FLAG_CONFIG |
(peer->flags & FLAG_REFCLOCK);
peer->cast_flags = cast_flags;
peer->ttlmax = ttl;
peer->keyid = key;
+ peer->precision = sys_precision;
+ peer_clear(peer);
return (peer);
}
{
register struct peer *peer;
register int i;
+ u_char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
/*
* Allocate a new peer structure. Some dirt here, since some of
peer->ass_next = assoc_hash[i];
assoc_hash[i] = peer;
assoc_hash_count[i]++;
+#ifdef OPENSSL
+ if (peer->flags & FLAG_SKEY) {
+ sprintf(statstr, "newpeer %d", peer->associd);
+ record_crypto_stats(&peer->srcadr, statstr);
+#ifdef DEBUG
+ if (debug)
+ printf("peer: %s\n", statstr);
+#endif
+#endif /* OPENSSL */
+ }
#ifdef DEBUG
if (debug)
printf(
next_peer = peer->next;
if (peer->cast_flags & MDF_ACAST) {
peer_clear(peer);
- } else {
+ } else if (peer->hmode == MODE_ACTIVE ||
+ peer->hmode == MODE_PASSIVE) {
key_expire(peer);
peer->cookval.tstamp = 0;
+ peer->crypto &= ~(CRYPTO_FLAG_AUTO |
+ CRYPTO_FLAG_AGREE);
}
}
}
sys_private = (u_int32)RANDOM & 0xffffffff;
crypto_sign();
-#ifdef DEBUG
- if (debug)
- printf("expire_all: at %lu\n", current_time);
-#endif
}
#endif /* OPENSSL */
peer->next) {
if (peer->cast_flags & MDF_ACAST) {
peer->ttl = 0;
- poll_update(peer, peer->hpoll);
+ poll_update(peer, 0);
}
}
}
/*
* ntp_proto.c - NTP version 4 protocol machinery
*/
-#ifdef HAVEy_CONFIG_H
+#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
peer->unreach++;
} else if (!(peer->flags & FLAG_CONFIG)) {
unpeer(peer);
- clock_select();
return;
-
} else {
peer_clear(peer);
hpoll++;
peer->timereachable = current_time;
if (!(peer->flags & FLAG_CONFIG)) {
unpeer(peer);
- clock_select();
return;
} else {
peer_clear(peer);
- hpoll = peer->minpoll;
}
}
if (peer->flags & FLAG_IBURST)
* sent and is a crypto-NAK, the server has either
* restarted or refreshed the private value, so we
* start over.
- * off.
*/
case MODE_SERVER:
if (is_org && has_mac == 4 && pkt->exten[0] ==
- 0)
- peer_clear(peer);
+ 0) {
+ if (!(peer->flags & FLAG_CONFIG)) {
+ unpeer(peer);
+ return;
+ } else {
+ peer_clear(peer);
+ }
+ }
break;
/*
case MODE_ACTIVE:
case MODE_PASSIVE:
if (is_org) {
- if (!(peer->flags & FLAG_CONFIG))
+ if (!(peer->flags & FLAG_CONFIG)) {
unpeer(peer);
- else
+ return;
+ } else {
peer_clear(peer);
+ }
}
break;
}
if (crypto_flags && (peer->flags & FLAG_SKEY)) {
peer->flash |= TEST10;
crypto_recv(peer, rbufp, is_org);
+ if (peer->cmmd != 0) {
+ peer->ppoll = pkt->ppoll;
+ poll_update(peer, 0);
+ }
if (peer->flash & TEST12) {
/* fall through */
if (peer->flash && is_org) {
poll_update(peer, peer->minpoll);
if (peer->crypto & CRYPTO_FLAG_PROV) {
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer);
- else
- unpeer(peer);
#ifdef DEBUG
if (debug)
printf("packet: bad crypto %03x\n",
peer->flash);
#endif
+ if (!(peer->flags & FLAG_CONFIG)) {
+ unpeer(peer);
+ return;
+ } else {
+ peer_clear(peer);
+ }
return;
+ } else {
+ poll_update(peer, peer->minpoll);
}
}
if (!(peer->crypto & CRYPTO_FLAG_PROV))
}
peer->reach |= 1;
peer->unreach = 0;
- poll_update(peer, peer->hpoll);
+ poll_update(peer, 0);
/*
* If running in a client/server association, calculate the
#ifdef OPENSSL
oldpoll = peer->kpoll;
#endif /* OPENSSL */
- if (hpoll > peer->maxpoll)
- peer->hpoll = peer->maxpoll;
- else if (hpoll < peer->minpoll)
- peer->hpoll = peer->minpoll;
- else
- peer->hpoll = hpoll;
+ if (hpoll != 0) {
+ if (hpoll > peer->maxpoll)
+ peer->hpoll = peer->maxpoll;
+ else if (hpoll < peer->minpoll)
+ peer->hpoll = peer->minpoll;
+ else
+ peer->hpoll = hpoll;
+ }
/*
* Bit of adventure here. If during a burst and not timeout,
)
{
register int i;
- u_long u_rand;
/*
* If cryptographic credentials have been acquired, toss them to
/*
* If he dies as a broadcast client, he comes back to life as
* a broadcast client in client mode in order to recover the
- * initial autokey values. Note that there is no need to call
- * clock_select(), since the perp has already been voted off
- * the island at this point.
+ * initial autokey values.
*/
- if (peer->cast_flags & MDF_BCLNT) {
- peer->flags |= FLAG_MCAST;
- peer->hmode = MODE_CLIENT;
- }
+ if (peer == sys_peer)
+ sys_peer = NULL;
peer->estbdelay = sys_bdelay;
peer->hpoll = peer->kpoll = peer->minpoll;
peer->ppoll = peer->maxpoll;
}
/*
- * Randomize the first poll over 1-16s to avoid bunching.
+ * Randomize the first poll to avoid bunching.
*/
- peer->update = peer->outdate = current_time;
- u_rand = RANDOM;
- peer->nextdate = current_time + (u_rand & ((1 <<
- BURST_INTERVAL1) - 1)) + 1;
+ peer->nextdate = peer->update = peer->outdate = current_time;
+ if (peer->cast_flags & MDF_BCLNT) {
+ peer->flags |= FLAG_MCAST;
+ peer->hmode = MODE_CLIENT;
+ peer->nextdate += RANDOM & ((1 << BURST_INTERVAL1) - 1);
+ } else {
+ peer->nextdate += RANDPOLL(BURST_INTERVAL2);
+ }
}
continue;
}
peer->status = CTL_PST_SEL_DISTSYSPEER;
- d = (1. - peer->hyst) * root_distance(peer) +
- peer->stratum * MAXDISPERSE;
+ d = (1. - peer->hyst) * (root_distance(peer) +
+ peer->stratum * MAXDISTANCE);
if (j >= NTP_MAXCLOCK) {
if (d >= synch[j - 1])
continue;
#ifdef DEBUG
if (debug > 2)
- printf("select: %s distance %.6f\n",
- ntoa(&peer_list[i]->srcadr), synch[i]);
+ printf("select: %s stratum %d weight %.6f error %.6f\n",
+ ntoa(&peer_list[i]->srcadr), peer->stratum,
+ synch[i], SQRT(error[i]));
#endif
}
}
}
+ if (nlist <= NTP_MINCLOCK || sys_selerr <= d ||
+ peer_list[k]->flags & FLAG_PREFER)
+ break;
#ifdef DEBUG
if (debug > 2)
printf(
- "select: survivors %d select %.6f peer %.6f\n",
- k, SQRT(sys_selerr), SQRT(d));
+ "select: %s select %.6f error %.6f\n",
+ ntoa(&peer_list[k]->srcadr),
+ SQRT(sys_selerr), SQRT(d));
#endif
- if (nlist <= NTP_MINCLOCK || sys_selerr <= d ||
- peer_list[k]->flags & FLAG_PREFER)
- break;
if (!(peer_list[k]->flags & FLAG_CONFIG))
unpeer(peer_list[k]);
for (j = k + 1; j < nlist; j++) {
sys_survivors = nlist;
#ifdef DEBUG
- if (debug > 2) {
+ if (debug > 1) {
for (i = 0; i < nlist; i++)
printf(
- "select: %s offset %.6f, distance %.6f poll %d\n",
+ "select: %s offset %.6f, weight %.6f poll %d\n",
ntoa(&peer_list[i]->srcadr),
peer_list[i]->offset, synch[i],
peer_list[i]->pollsw);
peer->status = CTL_PST_SEL_SYNCCAND;
peer->flags |= FLAG_SYSPEER;
peer->hyst = HYST;
- poll_update(peer, peer->hpoll);
if (peer->stratum == peer_list[0]->stratum) {
leap_consensus |= peer->leap;
if (peer->refclktype == REFCLK_ATOM_PPS &&
cmmd = 0;
if (peer->cmmd != NULL) {
sendlen += crypto_xmit(&xpkt, sendlen,
- peer->cmmd, peer->hcookie,
- peer->associd);
+ peer->cmmd, 0, peer->associd);
free(peer->cmmd);
peer->cmmd = NULL;
}
if (cmmd & CRYPTO_RESP) {
cmmd = htonl(cmmd);
sendlen += crypto_xmit(&xpkt,
- sendlen, &cmmd,
- peer->hcookie,
+ sendlen, &cmmd, 0,
peer->associd);
} else {
cmmd = htonl(cmmd);
sendlen += crypto_xmit(&xpkt,
- sendlen, &cmmd,
- peer->hcookie, peer->assoc);
+ sendlen, &cmmd, 0,
+ peer->assoc);
}
}
break;
cmmd = 0;
if (peer->cmmd != NULL) {
sendlen += crypto_xmit(&xpkt, sendlen,
- peer->cmmd, peer->hcookie,
- peer->associd);
+ peer->cmmd, 0, peer->associd);
free(peer->cmmd);
peer->cmmd = NULL;
}
cmmd = CRYPTO_TAI;
if ((cmmd = htonl(cmmd)) != 0)
sendlen += crypto_xmit(&xpkt, sendlen,
- &cmmd, peer->hcookie, peer->assoc);
+ &cmmd, 0, peer->assoc);
break;
}
{
u_char clktype;
int unit;
- int hpoll;
u_long next;
clktype = peer->refclktype;
* specialized for reference clocks. We do a little less
* protocol here and call the driver-specific transmit routine.
*/
- hpoll = peer->hpoll;
next = peer->outdate;
if (peer->burst == 0) {
u_char oreach;
clock_filter(peer, 0., 0., MAXDISPERSE);
clock_select();
}
- if (!(oreach & 0x0f)) {
- hpoll--;
- } else if ((oreach & 0x0f) == 0x0f)
- hpoll++;
if (peer->flags & FLAG_BURST)
peer->burst = NSTAGE;
}
peer->outdate = next;
if (peer->burst > 0)
peer->burst--;
- poll_update(peer, hpoll);
+ poll_update(peer, 0);
}
static u_long huffpuff_timer; /* huff-n'-puff timer */
#ifdef OPENSSL
static u_long revoke_timer; /* keys revoke timer */
-u_long sys_revoke = 1 << KEY_REVOKE; /* keys revoke timeout */
+u_char sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */
#endif /* OPENSSL */
/*
timer(void)
{
register struct peer *peer, *next_peer;
+#ifdef OPENSSL
+ u_char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
+#endif /* OPENSSL */
u_int n;
current_time += (1<<EVENT_TIMEOUT);
* Garbage collect old keys and generate new private value
*/
if (revoke_timer <= current_time) {
- revoke_timer += sys_revoke;
+ revoke_timer += RANDPOLL(sys_revoke);
expire_all();
+ sprintf(statstr, "refresh ts %u", ntohl(host.tstamp));
+ record_crypto_stats(NULL, statstr);
#ifdef DEBUG
if (debug)
- printf("key expire: at %lu next %lu\n",
- current_time, revoke_timer);
+ printf("timer: %s\n", statstr);
#endif
}
#endif /* OPENSSL */