aboutsummaryrefslogtreecommitdiff
path: root/ntpd/ntp_control.c
diff options
context:
space:
mode:
Diffstat (limited to 'ntpd/ntp_control.c')
-rw-r--r--ntpd/ntp_control.c1602
1 files changed, 914 insertions, 688 deletions
diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c
index 64603d37f527..a2abf0716868 100644
--- a/ntpd/ntp_control.c
+++ b/ntpd/ntp_control.c
@@ -1,8 +1,9 @@
/*
* ntp_control.c - respond to control messages and send async traps
*/
+
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#include "ntpd.h"
@@ -11,73 +12,75 @@
#include "ntp_control.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
+#include "ntp_config.h"
+#include "ntp_crypto.h"
+#include "ntp_assert.h"
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
+#include <sys/stat.h>
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
#include <arpa/inet.h>
/*
* Structure to hold request procedure information
*/
-#define NOAUTH 0
-#define AUTH 1
-
-#define NO_REQUEST (-1)
struct ctl_proc {
short control_code; /* defined request code */
+#define NO_REQUEST (-1)
u_short flags; /* flags word */
- void (*handler) P((struct recvbuf *, int)); /* handle request */
-};
-
-/*
- * Only one flag. Authentication required or not.
- */
+ /* Only one flag. Authentication required or not. */
#define NOAUTH 0
#define AUTH 1
+ void (*handler) (struct recvbuf *, int); /* handle request */
+};
+
/*
* Request processing routines
*/
-static void ctl_error P((int));
+static void ctl_error (int);
#ifdef REFCLOCK
-static u_short ctlclkstatus P((struct refclockstat *));
-#endif
-static void ctl_flushpkt P((int));
-static void ctl_putdata P((const char *, unsigned int, int));
-static void ctl_putstr P((const char *, const char *,
- unsigned int));
-static void ctl_putdbl P((const char *, double));
-static void ctl_putuint P((const char *, u_long));
-static void ctl_puthex P((const char *, u_long));
-static void ctl_putint P((const char *, long));
-static void ctl_putts P((const char *, l_fp *));
-static void ctl_putadr P((const char *, u_int32, struct sockaddr_storage*));
-static void ctl_putid P((const char *, char *));
-static void ctl_putarray P((const char *, double *, int));
-static void ctl_putsys P((int));
-static void ctl_putpeer P((int, struct peer *));
-#ifdef OPENSSL
-static void ctl_putfs P((const char *, tstamp_t));
+static u_short ctlclkstatus (struct refclockstat *);
#endif
+static void ctl_flushpkt (int);
+static void ctl_putdata (const char *, unsigned int, int);
+static void ctl_putstr (const char *, const char *,
+ unsigned int);
+static void ctl_putdbl (const char *, double);
+static void ctl_putuint (const char *, u_long);
+static void ctl_puthex (const char *, u_long);
+static void ctl_putint (const char *, long);
+static void ctl_putts (const char *, l_fp *);
+static void ctl_putadr (const char *, u_int32,
+ sockaddr_u *);
+static void ctl_putrefid (const char *, u_int32);
+static void ctl_putarray (const char *, double *, int);
+static void ctl_putsys (int);
+static void ctl_putpeer (int, struct peer *);
+static void ctl_putfs (const char *, tstamp_t);
#ifdef REFCLOCK
-static void ctl_putclock P((int, struct refclockstat *, int));
+static void ctl_putclock (int, struct refclockstat *, int);
#endif /* REFCLOCK */
-static struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
-static u_long count_var P((struct ctl_var *));
-static void control_unspec P((struct recvbuf *, int));
-static void read_status P((struct recvbuf *, int));
-static void read_variables P((struct recvbuf *, int));
-static void write_variables P((struct recvbuf *, int));
-static void read_clock_status P((struct recvbuf *, int));
-static void write_clock_status P((struct recvbuf *, int));
-static void set_trap P((struct recvbuf *, int));
-static void unset_trap P((struct recvbuf *, int));
-static struct ctl_trap *ctlfindtrap P((struct sockaddr_storage *,
- struct interface *));
+static struct ctl_var *ctl_getitem (struct ctl_var *, char **);
+static u_long count_var (struct ctl_var *);
+static void control_unspec (struct recvbuf *, int);
+static void read_status (struct recvbuf *, int);
+static void read_variables (struct recvbuf *, int);
+static void write_variables (struct recvbuf *, int);
+static void read_clock_status (struct recvbuf *, int);
+static void write_clock_status (struct recvbuf *, int);
+static void set_trap (struct recvbuf *, int);
+static void unset_trap (struct recvbuf *, int);
+static void configure (struct recvbuf *, int);
+static void save_config (struct recvbuf *, int);
+static struct ctl_trap *ctlfindtrap (sockaddr_u *,
+ struct interface *);
static struct ctl_proc control_codes[] = {
{ CTL_OP_UNSPEC, NOAUTH, control_unspec },
@@ -88,6 +91,8 @@ static struct ctl_proc control_codes[] = {
{ CTL_OP_WRITECLOCK, NOAUTH, write_clock_status },
{ CTL_OP_SETTRAP, NOAUTH, set_trap },
{ CTL_OP_UNSETTRAP, NOAUTH, unset_trap },
+ { CTL_OP_SAVECONFIG, AUTH, save_config },
+ { CTL_OP_CONFIGURE, AUTH, configure },
{ NO_REQUEST, 0 }
};
@@ -101,35 +106,36 @@ static struct ctl_var sys_var[] = {
{ CS_STRATUM, RO, "stratum" }, /* 2 */
{ CS_PRECISION, RO, "precision" }, /* 3 */
{ CS_ROOTDELAY, RO, "rootdelay" }, /* 4 */
- { CS_ROOTDISPERSION, RO, "rootdispersion" }, /* 5 */
+ { CS_ROOTDISPERSION, RO, "rootdisp" }, /* 5 */
{ CS_REFID, RO, "refid" }, /* 6 */
{ CS_REFTIME, RO, "reftime" }, /* 7 */
- { CS_POLL, RO, "poll" }, /* 8 */
+ { CS_POLL, RO, "tc" }, /* 8 */
{ CS_PEERID, RO, "peer" }, /* 9 */
- { CS_STATE, RO, "state" }, /* 10 */
- { CS_OFFSET, RO, "offset" }, /* 11 */
- { CS_DRIFT, RO, "frequency" }, /* 12 */
- { CS_JITTER, RO, "jitter" }, /* 13 */
- { CS_ERROR, RO, "noise" }, /* 14 */
- { CS_CLOCK, RO, "clock" }, /* 15 */
- { CS_PROCESSOR, RO, "processor" }, /* 16 */
- { CS_SYSTEM, RO, "system" }, /* 17 */
- { CS_VERSION, RO, "version" }, /* 18 */
- { CS_STABIL, RO, "stability" }, /* 19 */
- { CS_VARLIST, RO, "sys_var_list" }, /* 20 */
+ { CS_OFFSET, RO, "offset" }, /* 10 */
+ { CS_DRIFT, RO, "frequency" }, /* 11 */
+ { CS_JITTER, RO, "sys_jitter" }, /* 12 */
+ { CS_ERROR, RO, "clk_jitter" }, /* 13 */
+ { CS_CLOCK, RO, "clock" }, /* 14 */
+ { CS_PROCESSOR, RO, "processor" }, /* 15 */
+ { CS_SYSTEM, RO, "system" }, /* 16 */
+ { CS_VERSION, RO, "version" }, /* 17 */
+ { CS_STABIL, RO, "clk_wander" }, /* 18 */
+ { CS_VARLIST, RO, "sys_var_list" }, /* 19 */
+ { CS_TAI, RO, "tai" }, /* 20 */
+ { CS_LEAPTAB, RO, "leapsec" }, /* 21 */
+ { CS_LEAPEND, RO, "expire" }, /* 22 */
+ { CS_RATE, RO, "mintc" }, /* 23 */
#ifdef OPENSSL
- { CS_FLAGS, RO, "flags" }, /* 21 */
- { CS_HOST, RO, "hostname" }, /* 22 */
- { CS_PUBLIC, RO, "update" }, /* 23 */
- { CS_CERTIF, RO, "cert" }, /* 24 */
- { CS_REVTIME, RO, "expire" }, /* 25 */
- { CS_LEAPTAB, RO, "leapsec" }, /* 26 */
- { CS_TAI, RO, "tai" }, /* 27 */
- { CS_DIGEST, RO, "signature" }, /* 28 */
- { CS_IDENT, RO, "ident" }, /* 29 */
- { CS_REVOKE, RO, "expire" }, /* 30 */
+ { CS_FLAGS, RO, "flags" }, /* 24 */
+ { CS_HOST, RO, "host" }, /* 25 */
+ { CS_PUBLIC, RO, "update" }, /* 26 */
+ { CS_CERTIF, RO, "cert" }, /* 27 */
+ { CS_SIGNATURE, RO, "signature" }, /* 28 */
+ { CS_REVTIME, RO, "until" }, /* 29 */
+ { CS_GROUP, RO, "group" }, /* 30 */
+ { CS_DIGEST, RO, "digest" }, /* 31 */
#endif /* OPENSSL */
- { 0, EOV, "" } /* 21/31 */
+ { 0, EOV, "" } /* 24/3 2*/
};
static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
@@ -147,25 +153,27 @@ static u_char def_sys_var[] = {
CS_PRECISION,
CS_ROOTDELAY,
CS_ROOTDISPERSION,
- CS_PEERID,
CS_REFID,
CS_REFTIME,
- CS_POLL,
CS_CLOCK,
- CS_STATE,
+ CS_PEERID,
+ CS_POLL,
+ CS_RATE,
CS_OFFSET,
CS_DRIFT,
CS_JITTER,
CS_ERROR,
CS_STABIL,
+ CS_TAI,
+ CS_LEAPTAB,
+ CS_LEAPEND,
#ifdef OPENSSL
CS_HOST,
- CS_DIGEST,
+ CS_GROUP,
CS_FLAGS,
+ CS_DIGEST,
+ CS_SIGNATURE,
CS_PUBLIC,
- CS_IDENT,
- CS_LEAPTAB,
- CS_TAI,
CS_CERTIF,
#endif /* OPENSSL */
0
@@ -191,12 +199,12 @@ static struct ctl_var peer_var[] = {
{ CP_HPOLL, RO, "hpoll" }, /* 12 */
{ CP_PRECISION, RO, "precision" }, /* 13 */
{ CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */
- { CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */
+ { CP_ROOTDISPERSION, RO, "rootdisp" }, /* 15 */
{ CP_REFID, RO, "refid" }, /* 16 */
{ CP_REFTIME, RO, "reftime" }, /* 17 */
{ CP_ORG, RO, "org" }, /* 18 */
{ CP_REC, RO, "rec" }, /* 19 */
- { CP_XMT, RO, "xmt" }, /* 20 */
+ { CP_XMT, RO, "xleave" }, /* 20 */
{ CP_REACH, RO, "reach" }, /* 21 */
{ CP_UNREACH, RO, "unreach" }, /* 22 */
{ CP_TIMER, RO, "timer" }, /* 23 */
@@ -214,17 +222,20 @@ static struct ctl_var peer_var[] = {
{ CP_FLASH, RO, "flash" }, /* 35 */
{ CP_TTL, RO, "ttl" }, /* 36 */
{ CP_VARLIST, RO, "peer_var_list" }, /* 37 */
+ { CP_IN, RO, "in" }, /* 38 */
+ { CP_OUT, RO, "out" }, /* 39 */
+ { CP_RATE, RO, "headway" }, /* 40 */
+ { CP_BIAS, RO, "bias" }, /* 41 */
#ifdef OPENSSL
- { CP_FLAGS, RO, "flags" }, /* 38 */
- { CP_HOST, RO, "hostname" }, /* 39 */
- { CP_VALID, RO, "valid" }, /* 40 */
- { CP_INITSEQ, RO, "initsequence" }, /* 41 */
- { CP_INITKEY, RO, "initkey" }, /* 42 */
- { CP_INITTSP, RO, "timestamp" }, /* 43 */
- { CP_DIGEST, RO, "signature" }, /* 44 */
- { CP_IDENT, RO, "trust" }, /* 45 */
+ { CP_FLAGS, RO, "flags" }, /* 42 */
+ { CP_HOST, RO, "host" }, /* 43 */
+ { CP_VALID, RO, "valid" }, /* 44 */
+ { CP_INITSEQ, RO, "initsequence" }, /* 45 */
+ { CP_INITKEY, RO, "initkey" }, /* 46 */
+ { CP_INITTSP, RO, "timestamp" }, /* 47 */
+ { CP_SIGNATURE, RO, "signature" }, /* 48 */
#endif /* OPENSSL */
- { 0, EOV, "" } /* 38/46 */
+ { 0, EOV, "" } /* 42/49 */
};
@@ -236,18 +247,23 @@ static u_char def_peer_var[] = {
CP_SRCPORT,
CP_DSTADR,
CP_DSTPORT,
+ CP_OUT,
+ CP_IN,
CP_LEAP,
CP_STRATUM,
CP_PRECISION,
CP_ROOTDELAY,
CP_ROOTDISPERSION,
CP_REFID,
+ CP_REFTIME,
+ CP_REC,
CP_REACH,
CP_UNREACH,
CP_HMODE,
CP_PMODE,
CP_HPOLL,
CP_PPOLL,
+ CP_RATE,
CP_FLASH,
CP_KEYID,
CP_TTL,
@@ -255,19 +271,16 @@ static u_char def_peer_var[] = {
CP_DELAY,
CP_DISPERSION,
CP_JITTER,
- CP_REFTIME,
- CP_ORG,
- CP_REC,
CP_XMT,
+ CP_BIAS,
CP_FILTDELAY,
CP_FILTOFFSET,
CP_FILTERROR,
#ifdef OPENSSL
CP_HOST,
- CP_DIGEST,
- CP_VALID,
CP_FLAGS,
- CP_IDENT,
+ CP_SIGNATURE,
+ CP_VALID,
CP_INITSEQ,
#endif /* OPENSSL */
0
@@ -326,7 +339,7 @@ static u_char def_clock_var[] = {
# define STR_SYSTEM "UNIX"
# endif
# ifndef STR_PROCESSOR
-# define STR_PROCESSOR "unknown"
+# define STR_PROCESSOR "unknown"
# endif
static char str_system[] = STR_SYSTEM;
@@ -388,8 +401,8 @@ static u_char clocktypes[] = {
CTL_SST_TS_NTP, /* not used (24) */
CTL_SST_TS_NTP, /* not used (25) */
CTL_SST_TS_UHF, /* REFCLK_GPS_HP (26) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_ARCRON_MSF (27) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_SHM (28) */
+ CTL_SST_TS_LF, /* REFCLK_ARCRON_MSF (27) */
+ CTL_SST_TS_UHF, /* REFCLK_SHM (28) */
CTL_SST_TS_UHF, /* REFCLK_PALISADE (29) */
CTL_SST_TS_UHF, /* REFCLK_ONCORE (30) */
CTL_SST_TS_UHF, /* REFCLK_JUPITER (31) */
@@ -397,7 +410,7 @@ static u_char clocktypes[] = {
CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (33) */
CTL_SST_TS_LF, /* REFCLK_ULINK (34) */
CTL_SST_TS_LF, /* REFCLK_PCF (35) */
- CTL_SST_TS_LF, /* REFCLK_WWV (36) */
+ CTL_SST_TS_HF, /* REFCLK_WWV (36) */
CTL_SST_TS_LF, /* REFCLK_FG (37) */
CTL_SST_TS_UHF, /* REFCLK_HOPF_SERIAL (38) */
CTL_SST_TS_UHF, /* REFCLK_HOPF_PCI (39) */
@@ -456,7 +469,7 @@ static u_char * datapt;
static u_char * dataend;
static int datalinelen;
static int datanotbinflag;
-static struct sockaddr_storage *rmt_addr;
+static sockaddr_u *rmt_addr;
static struct interface *lcl_inter;
static u_char res_authenticate;
@@ -505,16 +518,14 @@ ctl_error(
int errcode
)
{
-#ifdef DEBUG
- if (debug >= 4)
- printf("sending control error %d\n", errcode);
-#endif
+ DPRINTF(3, ("sending control error %d\n", errcode));
+
/*
* Fill in the fields. We assume rpkt.sequence and rpkt.associd
* have already been filled in.
*/
rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode &
- CTL_OP_MASK));
+ CTL_OP_MASK));
rpkt.status = htons((u_short) ((errcode<<8) & 0xff00));
rpkt.count = 0;
@@ -524,19 +535,137 @@ ctl_error(
if (res_authenticate && sys_authenticate) {
int maclen;
- *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) =
- htonl(res_keyid);
maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
- CTL_HEADER_LEN);
+ CTL_HEADER_LEN);
sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt,
- CTL_HEADER_LEN + maclen);
+ CTL_HEADER_LEN + maclen);
} else {
sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt,
- CTL_HEADER_LEN);
+ CTL_HEADER_LEN);
}
numctlerrors++;
}
+/*
+ * save_config - Implements ntpq -c "saveconfig <filename>"
+ * Writes current configuration including any runtime
+ * changes by ntpq's :config or config-from-file
+ */
+void
+save_config(
+ struct recvbuf *rbufp,
+ int restrict_mask
+ )
+{
+ char reply[128];
+#ifdef SAVECONFIG
+ char filespec[128];
+ char filename[128];
+ char fullpath[512];
+ const char savedconfig_eq[] = "savedconfig=";
+ char savedconfig[sizeof(savedconfig_eq) + sizeof(filename)];
+ time_t now;
+ int fd;
+ FILE *fptr;
+#endif
+
+ if (restrict_mask & RES_NOMODIFY) {
+ snprintf(reply, sizeof(reply),
+ "saveconfig prohibited by restrict ... nomodify");
+ ctl_putdata(reply, strlen(reply), 0);
+ ctl_flushpkt(0);
+ msyslog(LOG_NOTICE,
+ "saveconfig from %s rejected due to nomodify restriction",
+ stoa(&rbufp->recv_srcadr));
+ return;
+ }
+
+#ifdef SAVECONFIG
+ if (NULL == saveconfigdir) {
+ snprintf(reply, sizeof(reply),
+ "saveconfig prohibited, no saveconfigdir configured");
+ ctl_putdata(reply, strlen(reply), 0);
+ ctl_flushpkt(0);
+ msyslog(LOG_NOTICE,
+ "saveconfig from %s rejected, no saveconfigdir",
+ stoa(&rbufp->recv_srcadr));
+ return;
+ }
+
+ if (0 == reqend - reqpt)
+ return;
+
+ strncpy(filespec, reqpt, sizeof(filespec));
+ filespec[sizeof(filespec) - 1] = '\0';
+
+ time(&now);
+
+ /*
+ * allow timestamping of the saved config filename with
+ * strftime() format such as:
+ * ntpq -c "saveconfig ntp-%Y%m%d-%H%M%S.conf"
+ */
+ if (0 == strftime(filename, sizeof(filename), filespec,
+ localtime(&now)))
+ strncpy(filename, filespec, sizeof(filename));
+
+ filename[sizeof(filename) - 1] = '\0';
+
+ if (strchr(filename, '\\') || strchr(filename, '/')) {
+ snprintf(reply, sizeof(reply),
+ "saveconfig does not allow directory in filename");
+ ctl_putdata(reply, strlen(reply), 0);
+ ctl_flushpkt(0);
+ msyslog(LOG_NOTICE,
+ "saveconfig with path from %s rejected",
+ stoa(&rbufp->recv_srcadr));
+ return;
+ }
+
+ snprintf(fullpath, sizeof(fullpath), "%s%s",
+ saveconfigdir, filename);
+
+ fd = open(fullpath, O_CREAT | O_TRUNC | O_WRONLY,
+ S_IRUSR | S_IWUSR);
+ if (-1 == fd)
+ fptr = NULL;
+ else
+ fptr = fdopen(fd, "w");
+
+ if (NULL == fptr || -1 == dump_all_config_trees(fptr, 1)) {
+ snprintf(reply, sizeof(reply),
+ "Unable to save configuration to file %s",
+ filename);
+ msyslog(LOG_ERR,
+ "saveconfig %s from %s failed", filename,
+ stoa(&rbufp->recv_srcadr));
+ } else {
+ snprintf(reply, sizeof(reply),
+ "Configuration saved to %s", filename);
+ msyslog(LOG_NOTICE,
+ "Configuration saved to %s (requested by %s)",
+ fullpath, stoa(&rbufp->recv_srcadr));
+ /*
+ * save the output filename in system variable
+ * savedconfig, retrieved with:
+ * ntpq -c "rv 0 savedconfig"
+ */
+ snprintf(savedconfig, sizeof(savedconfig), "%s%s",
+ savedconfig_eq, filename);
+ set_sys_var(savedconfig, strlen(savedconfig) + 1, RO);
+ }
+
+ if (NULL != fptr)
+ fclose(fptr);
+#else /* !SAVECONFIG follows */
+ snprintf(reply, sizeof(reply),
+ "saveconfig unavailable, configured with --disable-saveconfig");
+#endif
+
+ ctl_putdata(reply, strlen(reply), 0);
+ ctl_flushpkt(0);
+}
+
/*
* process_control - process an incoming control message
@@ -554,10 +683,7 @@ process_control(
int properlen;
int maclen;
-#ifdef DEBUG
- if (debug > 2)
- printf("in process_control()\n");
-#endif
+ DPRINTF(3, ("in process_control()\n"));
/*
* Save the addresses for error responses
@@ -574,10 +700,7 @@ process_control(
if (rbufp->recv_length < CTL_HEADER_LEN
|| pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
|| pkt->offset != 0) {
-#ifdef DEBUG
- if (debug)
- printf("invalid format in control packet\n");
-#endif
+ DPRINTF(1, ("invalid format in control packet\n"));
if (rbufp->recv_length < CTL_HEADER_LEN)
numctltooshort++;
if (pkt->r_m_e_op & CTL_RESPONSE)
@@ -592,11 +715,8 @@ process_control(
}
res_version = PKT_VERSION(pkt->li_vn_mode);
if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) {
-#ifdef DEBUG
- if (debug)
- printf("unknown version %d in control packet\n",
- res_version);
-#endif
+ DPRINTF(1, ("unknown version %d in control packet\n",
+ res_version));
numctlbadversion++;
return;
}
@@ -606,7 +726,7 @@ process_control(
* responses
*/
rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
- MODE_CONTROL);
+ MODE_CONTROL);
res_opcode = pkt->r_m_e_op;
rpkt.sequence = pkt->sequence;
rpkt.associd = pkt->associd;
@@ -617,12 +737,16 @@ process_control(
res_authenticate = 0;
res_keyid = 0;
res_authokay = 0;
- req_count = (int)htons(pkt->count);
+ req_count = (int)ntohs(pkt->count);
datanotbinflag = 0;
datalinelen = 0;
datapt = rpkt.data;
dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
+ if ((rbufp->recv_length & 0x3) != 0)
+ DPRINTF(3, ("Control packet length %d unrounded\n",
+ rbufp->recv_length));
+
/*
* We're set up now. Make sure we've got at least enough
* incoming data space to match the count.
@@ -635,46 +759,30 @@ process_control(
}
properlen = req_count + CTL_HEADER_LEN;
-#ifdef DEBUG
- if (debug > 2 && (rbufp->recv_length & 0x3) != 0)
- printf("Packet length %d unrounded\n",
- rbufp->recv_length);
-#endif
/* round up proper len to a 8 octet boundary */
properlen = (properlen + 7) & ~7;
maclen = rbufp->recv_length - properlen;
- if ((rbufp->recv_length & (sizeof(u_long) - 1)) == 0 &&
+ if ((rbufp->recv_length & 3) == 0 &&
maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
sys_authenticate) {
res_authenticate = 1;
res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
- properlen));
-
-#ifdef DEBUG
- if (debug > 2)
- printf(
- "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
- rbufp->recv_length, properlen, res_keyid, maclen);
-#endif
- if (!authistrusted(res_keyid)) {
-#ifdef DEBUG
- if (debug > 2)
- printf("invalid keyid %08x\n",
- res_keyid);
-#endif
- } else if (authdecrypt(res_keyid, (u_int32 *)pkt,
- rbufp->recv_length - maclen, maclen)) {
-#ifdef DEBUG
- if (debug > 2)
- printf("authenticated okay\n");
-#endif
+ properlen));
+
+ DPRINTF(3, ("recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
+ rbufp->recv_length, properlen, res_keyid,
+ maclen));
+
+ if (!authistrusted(res_keyid))
+ DPRINTF(3, ("invalid keyid %08x\n", res_keyid));
+ else if (authdecrypt(res_keyid, (u_int32 *)pkt,
+ rbufp->recv_length - maclen,
+ maclen)) {
+ DPRINTF(3, ("authenticated okay\n"));
res_authokay = 1;
} else {
-#ifdef DEBUG
- if (debug > 2)
- printf("authentication failed\n");
-#endif
+ DPRINTF(3, ("authentication failed\n"));
res_keyid = 0;
}
}
@@ -690,13 +798,11 @@ process_control(
*/
for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
if (cc->control_code == res_opcode) {
-#ifdef DEBUG
- if (debug > 2)
- printf("opcode %d, found command handler\n",
- res_opcode);
-#endif
- if (cc->flags == AUTH && (!res_authokay ||
- res_keyid != ctl_auth_keyid)) {
+ DPRINTF(3, ("opcode %d, found command handler\n",
+ res_opcode));
+ if (cc->flags == AUTH
+ && (!res_authokay
+ || res_keyid != ctl_auth_keyid)) {
ctl_error(CERR_PERMISSION);
return;
}
@@ -722,17 +828,19 @@ ctlpeerstatus(
register struct peer *peer
)
{
- register u_short status;
+ u_short status;
status = peer->status;
- if (peer->flags & FLAG_CONFIG)
+ if (!(peer->flags & FLAG_PREEMPT))
status |= CTL_PST_CONFIG;
- if (peer->flags & FLAG_AUTHENABLE)
+ if (peer->keyid != 0)
status |= CTL_PST_AUTHENABLE;
if (peer->flags & FLAG_AUTHENTIC)
status |= CTL_PST_AUTHENTIC;
if (peer->reach != 0)
status |= CTL_PST_REACH;
+ if (peer->cast_flags & (MDF_BCAST | MDF_MCAST | MDF_ACAST))
+ status |= CTL_PST_BCAST;
return (u_short)CTL_PEER_STATUS(status, peer->num_events,
peer->last_event);
}
@@ -747,8 +855,8 @@ ctlclkstatus(
struct refclockstat *this_clock
)
{
- return ((u_short)(((this_clock->currentstatus) << 8) |
- (this_clock->lastevent)));
+ return (u_short)CTL_PEER_STATUS(0, this_clock->lastevent,
+ this_clock->currentstatus);
}
#endif
@@ -766,16 +874,15 @@ ctlsysstatus(void)
if (sys_peer != 0) {
if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
this_clock = sys_peer->sstclktype;
- if (pps_control)
- this_clock |= CTL_SST_TS_PPS;
} else {
if (sys_peer->refclktype < sizeof(clocktypes))
this_clock =
clocktypes[sys_peer->refclktype];
- if (pps_control)
- this_clock |= CTL_SST_TS_PPS;
}
}
+#else /* REFCLOCK */
+ if (sys_peer != 0)
+ this_clock = CTL_SST_TS_NTP;
#endif /* REFCLOCK */
return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
ctl_sys_num_events, ctl_sys_last_event);
@@ -816,7 +923,7 @@ ctl_flushpkt(
* Fill in the packet with the current info
*/
rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode &
- CTL_OP_MASK));
+ CTL_OP_MASK));
rpkt.count = htons((u_short) dlen);
rpkt.offset = htons( (u_short) res_offset);
if (res_async) {
@@ -826,8 +933,8 @@ ctl_flushpkt(
if (ctl_trap[i].tr_flags & TRAP_INUSE) {
rpkt.li_vn_mode =
PKT_LI_VN_MODE(sys_leap,
- ctl_trap[i].tr_version,
- MODE_CONTROL);
+ ctl_trap[i].tr_version,
+ MODE_CONTROL);
rpkt.sequence =
htons(ctl_trap[i].tr_sequence);
sendpkt(&ctl_trap[i].tr_addr,
@@ -855,12 +962,12 @@ ctl_flushpkt(
}
memcpy(datapt, &keyid, sizeof keyid);
maclen = authencrypt(res_keyid,
- (u_int32 *)&rpkt, totlen);
+ (u_int32 *)&rpkt, totlen);
sendpkt(rmt_addr, lcl_inter, -5,
- (struct pkt *)&rpkt, totlen + maclen);
+ (struct pkt *)&rpkt, totlen + maclen);
} else {
sendpkt(rmt_addr, lcl_inter, -6,
- (struct pkt *)&rpkt, sendlen);
+ (struct pkt *)&rpkt, sendlen);
}
if (more)
numctlfrags++;
@@ -897,7 +1004,7 @@ ctl_putdata(
*datapt++ = ',';
datalinelen++;
if ((dlen + datalinelen + 1) >= MAXDATALINELEN)
- {
+ {
*datapt++ = '\r';
*datapt++ = '\n';
datalinelen = 0;
@@ -972,10 +1079,10 @@ ctl_putdbl(
while (*cq != '\0')
*cp++ = *cq++;
*cp++ = '=';
- (void)sprintf(cp, "%.3f", ts);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "%.3f", ts);
+ cp += strlen(cp);
+ ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
}
/*
@@ -997,16 +1104,15 @@ ctl_putuint(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "%lu", uval);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "%lu", uval);
+ cp += strlen(cp);
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
/*
* ctl_putfs - write a decoded filestamp into the response
*/
-#ifdef OPENSSL
static void
ctl_putfs(
const char *tag,
@@ -1027,20 +1133,20 @@ ctl_putfs(
*cp++ = '=';
fstamp = uval - JAN_1970;
tm = gmtime(&fstamp);
- if (tm == NULL)
+ if (NULL == tm)
return;
-
- sprintf(cp, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
- tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer),
+ "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
+ cp += strlen(cp);
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
-#endif
/*
- * ctl_puthex - write a tagged unsigned integer, in hex, into the response
+ * ctl_puthex - write a tagged unsigned integer, in hex, into the
+ * response
*/
static void
ctl_puthex(
@@ -1058,9 +1164,9 @@ ctl_puthex(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "0x%lx", uval);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "0x%lx", uval);
+ cp += strlen(cp);
ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
}
@@ -1084,9 +1190,9 @@ ctl_putint(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "%ld", ival);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "%ld", ival);
+ cp += strlen(cp);
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -1110,11 +1216,10 @@ ctl_putts(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "0x%08lx.%08lx",
- ts->l_ui & ULONG_CONST(0xffffffff),
- ts->l_uf & ULONG_CONST(0xffffffff));
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "0x%08lx.%08lx",
+ ts->l_ui & 0xffffffffUL, ts->l_uf & 0xffffffffUL);
+ cp += strlen(cp);
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -1126,7 +1231,7 @@ static void
ctl_putadr(
const char *tag,
u_int32 addr32,
- struct sockaddr_storage* addr
+ sockaddr_u *addr
)
{
register char *cp;
@@ -1139,38 +1244,54 @@ ctl_putadr(
*cp++ = *cq++;
*cp++ = '=';
- if (addr == NULL)
+ if (NULL == addr)
cq = numtoa(addr32);
else
cq = stoa(addr);
- while (*cq != '\0')
- *cp++ = *cq++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "%s", cq);
+ cp += strlen(cp);
+ ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
}
+
/*
- * ctl_putid - write a tagged clock ID into the response
+ * ctl_putrefid - send a u_int32 refid as printable text
*/
static void
-ctl_putid(
- const char *tag,
- char *id
+ctl_putrefid(
+ const char * tag,
+ u_int32 refid
)
{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- cq = id;
- while (*cq != '\0' && (cq - id) < 4)
- *cp++ = *cq++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
+ char output[16];
+ char * optr;
+ char * oplim;
+ char * iptr;
+ char * iplim;
+ char * past_eq;
+
+ optr = output;
+ oplim = output + sizeof(output);
+ while (optr < oplim && '\0' != *tag)
+ *optr++ = *tag++;
+ if (optr < oplim) {
+ *optr++ = '=';
+ past_eq = optr;
+ }
+ if (!(optr < oplim))
+ return;
+ iptr = (char *)&refid;
+ iplim = iptr + sizeof(refid);
+ for ( ; optr < oplim && iptr < iplim && '\0' != *iptr;
+ iptr++, optr++)
+ if (isprint(*iptr))
+ *optr = *iptr;
+ else
+ *optr = '.';
+ if (!(optr <= oplim))
+ optr = past_eq;
+ ctl_putdata(output, (u_int)(optr - output), FALSE);
}
@@ -1197,9 +1318,10 @@ ctl_putarray(
if (i == 0)
i = NTP_SHIFT;
i--;
- (void)sprintf(cp, " %.2f", arr[i] * 1e3);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer),
+ " %.2f", arr[i] * 1e3);
+ cp += strlen(cp);
} while(i != start);
ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
}
@@ -1222,237 +1344,239 @@ ctl_putsys(
switch (varid) {
- case CS_LEAP:
+ case CS_LEAP:
ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
break;
- case CS_STRATUM:
+ case CS_STRATUM:
ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
break;
- case CS_PRECISION:
+ case CS_PRECISION:
ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
break;
- case CS_ROOTDELAY:
+ case CS_ROOTDELAY:
ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
- 1e3);
+ 1e3);
break;
- case CS_ROOTDISPERSION:
+ case CS_ROOTDISPERSION:
ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
- sys_rootdispersion * 1e3);
+ sys_rootdisp * 1e3);
break;
- case CS_REFID:
+ case CS_REFID:
if (sys_stratum > 1 && sys_stratum < STRATUM_UNSPEC)
- ctl_putadr(sys_var[CS_REFID].text, sys_refid, NULL);
+ ctl_putadr(sys_var[varid].text, sys_refid, NULL);
else
- ctl_putid(sys_var[CS_REFID].text,
- (char *)&sys_refid);
+ ctl_putrefid(sys_var[varid].text, sys_refid);
break;
- case CS_REFTIME:
+ case CS_REFTIME:
ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime);
break;
- case CS_POLL:
+ case CS_POLL:
ctl_putuint(sys_var[CS_POLL].text, sys_poll);
break;
- case CS_PEERID:
+ case CS_PEERID:
if (sys_peer == NULL)
ctl_putuint(sys_var[CS_PEERID].text, 0);
else
ctl_putuint(sys_var[CS_PEERID].text,
- sys_peer->associd);
+ sys_peer->associd);
break;
- case CS_STATE:
- ctl_putuint(sys_var[CS_STATE].text, (unsigned)state);
- break;
-
- case CS_OFFSET:
+ case CS_OFFSET:
ctl_putdbl(sys_var[CS_OFFSET].text, last_offset * 1e3);
break;
- case CS_DRIFT:
+ case CS_DRIFT:
ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6);
break;
- case CS_JITTER:
+ case CS_JITTER:
ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
break;
- case CS_ERROR:
+ case CS_ERROR:
ctl_putdbl(sys_var[CS_ERROR].text, clock_jitter * 1e3);
break;
- case CS_CLOCK:
+ case CS_CLOCK:
get_systime(&tmp);
ctl_putts(sys_var[CS_CLOCK].text, &tmp);
break;
- case CS_PROCESSOR:
+ case CS_PROCESSOR:
#ifndef HAVE_UNAME
ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
- sizeof(str_processor) - 1);
+ sizeof(str_processor) - 1);
#else
ctl_putstr(sys_var[CS_PROCESSOR].text,
- utsnamebuf.machine, strlen(utsnamebuf.machine));
+ utsnamebuf.machine, strlen(utsnamebuf.machine));
#endif /* HAVE_UNAME */
break;
- case CS_SYSTEM:
+ case CS_SYSTEM:
#ifndef HAVE_UNAME
ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
- sizeof(str_system) - 1);
+ sizeof(str_system) - 1);
#else
- sprintf(str, "%s/%s", utsnamebuf.sysname, utsnamebuf.release);
+ snprintf(str, sizeof(str), "%s/%s", utsnamebuf.sysname,
+ utsnamebuf.release);
ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
#endif /* HAVE_UNAME */
break;
- case CS_VERSION:
+ case CS_VERSION:
ctl_putstr(sys_var[CS_VERSION].text, Version,
- strlen(Version));
+ strlen(Version));
break;
- case CS_STABIL:
+ case CS_STABIL:
ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
- 1e6);
- break;
-
- case CS_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) -
- strlen(sys_var[CS_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name */
-
- strcpy(s, sys_var[CS_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
- for (k = sys_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
- i = strlen(k->text);
- if (s+i+1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
+ 1e6);
+ break;
+
+ case CS_VARLIST:
+ {
+ char buf[CTL_MAX_DATA_LEN];
+ register char *s, *t, *be;
+ register const char *ss;
+ register int i;
+ register struct ctl_var *k;
+
+ s = buf;
+ be = buf + sizeof(buf);
+ if (s + strlen(sys_var[CS_VARLIST].text) + 4 > be)
+ break; /* really long var name */
+
+ snprintf(s, sizeof(buf), "%s=\"",
+ sys_var[CS_VARLIST].text);
+ s += strlen(s);
+ t = s;
+ for (k = sys_var; !(k->flags & EOV); k++) {
+ if (k->flags & PADDING)
+ continue;
+ i = strlen(k->text);
+ if (s+i+1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text, i);
+ s += i;
+ }
+
+ for (k = ext_sys_var; k && !(k->flags & EOV);
+ k++) {
+ if (k->flags & PADDING)
+ continue;
+
+ ss = k->text;
+ if (!ss)
+ continue;
+
+ while (*ss && *ss != '=')
+ ss++;
+ i = ss - k->text;
+ if (s + i + 1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text,
+ (unsigned)i);
+ s += i;
+ }
+ if (s+2 >= be)
+ break;
- for (k = ext_sys_var; k && !(k->flags &EOV);
- k++) {
- if (k->flags & PADDING)
- continue;
+ *s++ = '"';
+ *s = '\0';
- ss = k->text;
- if (!ss)
- continue;
+ ctl_putdata(buf, (unsigned)( s - buf ),
+ 0);
+ }
+ break;
- while (*ss && *ss != '=')
- ss++;
- i = ss - k->text;
- if (s + i + 1 >= be)
- break;
+ case CS_TAI:
+ if (sys_tai > 0)
+ ctl_putuint(sys_var[CS_TAI].text, sys_tai);
+ break;
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text,
- (unsigned)i);
- s += i;
- }
- if (s+2 >= be)
- break;
+ case CS_LEAPTAB:
+ if (leap_sec > 0)
+ ctl_putfs(sys_var[CS_LEAPTAB].text,
+ leap_sec);
+ break;
- *s++ = '"';
- *s = '\0';
+ case CS_LEAPEND:
+ if (leap_expire > 0)
+ ctl_putfs(sys_var[CS_LEAPEND].text,
+ leap_expire);
+ break;
- ctl_putdata(buf, (unsigned)( s - buf ),
- 0);
- }
+ case CS_RATE:
+ ctl_putuint(sys_var[CS_RATE].text, ntp_minpoll);
break;
#ifdef OPENSSL
- case CS_FLAGS:
+ case CS_FLAGS:
+ if (crypto_flags)
+ ctl_puthex(sys_var[CS_FLAGS].text,
+ crypto_flags);
+ break;
+
+ case CS_DIGEST:
if (crypto_flags) {
- ctl_puthex(sys_var[CS_FLAGS].text, crypto_flags);
+ strcpy(str, OBJ_nid2ln(crypto_nid));
+ ctl_putstr(sys_var[CS_DIGEST].text, str,
+ strlen(str));
}
break;
- case CS_DIGEST:
+ case CS_SIGNATURE:
if (crypto_flags) {
const EVP_MD *dp;
dp = EVP_get_digestbynid(crypto_flags >> 16);
strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
- ctl_putstr(sys_var[CS_DIGEST].text, str,
+ ctl_putstr(sys_var[CS_SIGNATURE].text, str,
strlen(str));
}
break;
- case CS_HOST:
+ case CS_HOST:
if (sys_hostname != NULL)
ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
strlen(sys_hostname));
break;
- case CS_CERTIF:
+ case CS_GROUP:
+ if (sys_groupname != NULL)
+ ctl_putstr(sys_var[CS_GROUP].text, sys_groupname,
+ strlen(sys_groupname));
+ break;
+
+ case CS_CERTIF:
for (cp = cinfo; cp != NULL; cp = cp->link) {
- sprintf(cbuf, "%s %s 0x%x", cp->subject,
- cp->issuer, cp->flags);
+ snprintf(cbuf, sizeof(cbuf), "%s %s 0x%x",
+ cp->subject, cp->issuer, cp->flags);
ctl_putstr(sys_var[CS_CERTIF].text, cbuf,
strlen(cbuf));
- ctl_putfs(sys_var[CS_REVOKE].text, cp->last);
+ ctl_putfs(sys_var[CS_REVTIME].text, cp->last);
}
break;
- case CS_PUBLIC:
- if (hostval.fstamp != 0)
- ctl_putfs(sys_var[CS_PUBLIC].text,
- ntohl(hostval.tstamp));
- break;
-
- case CS_REVTIME:
+ case CS_PUBLIC:
if (hostval.tstamp != 0)
- ctl_putfs(sys_var[CS_REVTIME].text,
+ ctl_putfs(sys_var[CS_PUBLIC].text,
ntohl(hostval.tstamp));
break;
-
- case CS_IDENT:
- if (iffpar_pkey != NULL)
- ctl_putstr(sys_var[CS_IDENT].text,
- iffpar_file, strlen(iffpar_file));
- if (gqpar_pkey != NULL)
- ctl_putstr(sys_var[CS_IDENT].text,
- gqpar_file, strlen(gqpar_file));
- if (mvpar_pkey != NULL)
- ctl_putstr(sys_var[CS_IDENT].text,
- mvpar_file, strlen(mvpar_file));
- break;
-
- case CS_LEAPTAB:
- if (tai_leap.fstamp != 0)
- ctl_putfs(sys_var[CS_LEAPTAB].text,
- ntohl(tai_leap.fstamp));
- break;
-
- case CS_TAI:
- ctl_putuint(sys_var[CS_TAI].text, sys_tai);
- break;
#endif /* OPENSSL */
}
}
@@ -1475,32 +1599,32 @@ ctl_putpeer(
switch (varid) {
- case CP_CONFIG:
+ case CP_CONFIG:
ctl_putuint(peer_var[CP_CONFIG].text,
- (unsigned)((peer->flags & FLAG_CONFIG) != 0));
+ (unsigned)((peer->flags & FLAG_PREEMPT) == 0));
break;
- case CP_AUTHENABLE:
+ case CP_AUTHENABLE:
ctl_putuint(peer_var[CP_AUTHENABLE].text,
- (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
+ (unsigned)(peer->keyid != 0));
break;
- case CP_AUTHENTIC:
+ case CP_AUTHENTIC:
ctl_putuint(peer_var[CP_AUTHENTIC].text,
(unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
break;
- case CP_SRCADR:
+ case CP_SRCADR:
ctl_putadr(peer_var[CP_SRCADR].text, 0,
&peer->srcadr);
break;
- case CP_SRCPORT:
+ case CP_SRCPORT:
ctl_putuint(peer_var[CP_SRCPORT].text,
ntohs(((struct sockaddr_in*)&peer->srcadr)->sin_port));
break;
- case CP_DSTADR:
+ case CP_DSTADR:
if (peer->dstadr) {
ctl_putadr(peer_var[CP_DSTADR].text, 0,
&(peer->dstadr->sin));
@@ -1510,226 +1634,251 @@ ctl_putpeer(
}
break;
- case CP_DSTPORT:
+ case CP_DSTPORT:
ctl_putuint(peer_var[CP_DSTPORT].text,
(u_long)(peer->dstadr ?
ntohs(((struct sockaddr_in*)&peer->dstadr->sin)->sin_port) : 0));
break;
- case CP_LEAP:
+ case CP_IN:
+ if (peer->r21 > 0)
+ ctl_putdbl(peer_var[CP_IN].text,
+ peer->r21 / 1e3);
+ break;
+
+ case CP_OUT:
+ if (peer->r34 >0)
+ ctl_putdbl(peer_var[CP_OUT].text,
+ peer->r34 / 1e3);
+ break;
+
+ case CP_RATE:
+ ctl_putuint(peer_var[CP_RATE].text, peer->throttle);
+ break;
+
+ case CP_LEAP:
ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
break;
- case CP_HMODE:
+ case CP_HMODE:
ctl_putuint(peer_var[CP_HMODE].text, peer->hmode);
break;
- case CP_STRATUM:
+ case CP_STRATUM:
ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum);
break;
- case CP_PPOLL:
+ case CP_PPOLL:
ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll);
break;
- case CP_HPOLL:
+ case CP_HPOLL:
ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll);
break;
- case CP_PRECISION:
+ case CP_PRECISION:
ctl_putint(peer_var[CP_PRECISION].text,
- peer->precision);
+ peer->precision);
break;
- case CP_ROOTDELAY:
+ case CP_ROOTDELAY:
ctl_putdbl(peer_var[CP_ROOTDELAY].text,
- peer->rootdelay * 1e3);
+ peer->rootdelay * 1e3);
break;
- case CP_ROOTDISPERSION:
+ case CP_ROOTDISPERSION:
ctl_putdbl(peer_var[CP_ROOTDISPERSION].text,
- peer->rootdispersion * 1e3);
+ peer->rootdisp * 1e3);
break;
- case CP_REFID:
+ case CP_REFID:
+#ifdef REFCLOCK
if (peer->flags & FLAG_REFCLOCK) {
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
- } else {
- if (peer->stratum > 1 && peer->stratum <
- STRATUM_UNSPEC)
- ctl_putadr(peer_var[CP_REFID].text,
- peer->refid, NULL);
- else
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
+ ctl_putrefid(peer_var[varid].text, peer->refid);
+ break;
}
+#endif
+ if (peer->stratum > 1 && peer->stratum < STRATUM_UNSPEC)
+ ctl_putadr(peer_var[varid].text, peer->refid,
+ NULL);
+ else
+ ctl_putrefid(peer_var[varid].text, peer->refid);
break;
- case CP_REFTIME:
+ case CP_REFTIME:
ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime);
break;
- case CP_ORG:
- ctl_putts(peer_var[CP_ORG].text, &peer->org);
+ case CP_ORG:
+ ctl_putts(peer_var[CP_ORG].text, &peer->aorg);
break;
- case CP_REC:
- ctl_putts(peer_var[CP_REC].text, &peer->rec);
+ case CP_REC:
+ ctl_putts(peer_var[CP_REC].text, &peer->dst);
break;
- case CP_XMT:
- ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
+ case CP_XMT:
+ if (peer->xleave != 0)
+ ctl_putdbl(peer_var[CP_XMT].text, peer->xleave *
+ 1e3);
break;
- case CP_REACH:
+ case CP_BIAS:
+ if (peer->bias != 0)
+ ctl_putdbl(peer_var[CP_BIAS].text, peer->bias *
+ 1e3);
+ break;
+
+ case CP_REACH:
ctl_puthex(peer_var[CP_REACH].text, peer->reach);
break;
- case CP_FLASH:
+ case CP_FLASH:
temp = peer->flash;
ctl_puthex(peer_var[CP_FLASH].text, temp);
break;
- case CP_TTL:
- ctl_putint(peer_var[CP_TTL].text, sys_ttl[peer->ttl]);
+ case CP_TTL:
+ if (peer->ttl > 0)
+ ctl_putint(peer_var[CP_TTL].text,
+ sys_ttl[peer->ttl]);
break;
- case CP_UNREACH:
+ case CP_UNREACH:
ctl_putuint(peer_var[CP_UNREACH].text, peer->unreach);
break;
- case CP_TIMER:
+ case CP_TIMER:
ctl_putuint(peer_var[CP_TIMER].text,
peer->nextdate - current_time);
break;
- case CP_DELAY:
+ case CP_DELAY:
ctl_putdbl(peer_var[CP_DELAY].text, peer->delay * 1e3);
break;
- case CP_OFFSET:
+ case CP_OFFSET:
ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset *
- 1e3);
+ 1e3);
break;
- case CP_JITTER:
- ctl_putdbl(peer_var[CP_JITTER].text, peer->jitter * 1e3);
+ case CP_JITTER:
+ ctl_putdbl(peer_var[CP_JITTER].text, peer->jitter *
+ 1e3);
break;
- case CP_DISPERSION:
+ case CP_DISPERSION:
ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp *
- 1e3);
+ 1e3);
break;
- case CP_KEYID:
- ctl_putuint(peer_var[CP_KEYID].text, peer->keyid);
+ case CP_KEYID:
+ if (peer->keyid > NTP_MAXKEY)
+ ctl_puthex(peer_var[CP_KEYID].text,
+ peer->keyid);
+ else
+ ctl_putuint(peer_var[CP_KEYID].text,
+ peer->keyid);
break;
- case CP_FILTDELAY:
+ case CP_FILTDELAY:
ctl_putarray(peer_var[CP_FILTDELAY].text,
peer->filter_delay, (int)peer->filter_nextpt);
break;
- case CP_FILTOFFSET:
+ case CP_FILTOFFSET:
ctl_putarray(peer_var[CP_FILTOFFSET].text,
peer->filter_offset, (int)peer->filter_nextpt);
break;
- case CP_FILTERROR:
+ case CP_FILTERROR:
ctl_putarray(peer_var[CP_FILTERROR].text,
peer->filter_disp, (int)peer->filter_nextpt);
break;
- case CP_PMODE:
+ case CP_PMODE:
ctl_putuint(peer_var[CP_PMODE].text, peer->pmode);
break;
- case CP_RECEIVED:
+ case CP_RECEIVED:
ctl_putuint(peer_var[CP_RECEIVED].text, peer->received);
break;
- case CP_SENT:
+ case CP_SENT:
ctl_putuint(peer_var[CP_SENT].text, peer->sent);
break;
- case CP_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) -
- strlen(peer_var[CP_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name */
-
- strcpy(s, peer_var[CP_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
- for (k = peer_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- i = strlen(k->text);
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
- ctl_putdata(buf, (unsigned)(s - buf), 0);
- }
- break;
+ case CP_VARLIST:
+ {
+ char buf[CTL_MAX_DATA_LEN];
+ register char *s, *t, *be;
+ register int i;
+ register struct ctl_var *k;
+
+ s = buf;
+ be = buf + sizeof(buf);
+ if (s + strlen(peer_var[CP_VARLIST].text) + 4 > be)
+ break; /* really long var name */
+
+ snprintf(s, sizeof(buf), "%s=\"",
+ peer_var[CP_VARLIST].text);
+ s += strlen(s);
+ t = s;
+ for (k = peer_var; !(k->flags & EOV); k++) {
+ if (k->flags & PADDING)
+ continue;
+
+ i = strlen(k->text);
+ if (s + i + 1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text, i);
+ s += i;
+ }
+ if (s+2 >= be)
+ break;
+
+ *s++ = '"';
+ *s = '\0';
+ ctl_putdata(buf, (unsigned)(s - buf), 0);
+ }
+ break;
#ifdef OPENSSL
- case CP_FLAGS:
+ case CP_FLAGS:
if (peer->crypto)
ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
break;
- case CP_DIGEST:
+ case CP_SIGNATURE:
if (peer->crypto) {
const EVP_MD *dp;
dp = EVP_get_digestbynid(peer->crypto >> 16);
strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
- ctl_putstr(peer_var[CP_DIGEST].text, str,
- strlen(str));
+ ctl_putstr(peer_var[CP_SIGNATURE].text, str,
+ strlen(str));
}
break;
- case CP_HOST:
+ case CP_HOST:
if (peer->subject != NULL)
ctl_putstr(peer_var[CP_HOST].text,
peer->subject, strlen(peer->subject));
break;
- case CP_VALID: /* not used */
- break;
-
- case CP_IDENT:
- if (peer->issuer != NULL)
- ctl_putstr(peer_var[CP_IDENT].text,
- peer->issuer, strlen(peer->issuer));
+ case CP_VALID: /* not used */
break;
- case CP_INITSEQ:
+ case CP_INITSEQ:
if ((ap = (struct autokey *)peer->recval.ptr) == NULL)
break;
+
ctl_putint(peer_var[CP_INITSEQ].text, ap->seq);
ctl_puthex(peer_var[CP_INITKEY].text, ap->key);
ctl_putfs(peer_var[CP_INITTSP].text,
- ntohl(peer->recval.tstamp));
+ ntohl(peer->recval.tstamp));
break;
#endif /* OPENSSL */
}
@@ -1749,147 +1898,148 @@ ctl_putclock(
{
switch(varid) {
- case CC_TYPE:
+ case CC_TYPE:
if (mustput || clock_stat->clockdesc == NULL
- || *(clock_stat->clockdesc) == '\0') {
+ || *(clock_stat->clockdesc) == '\0') {
ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type);
}
break;
- case CC_TIMECODE:
+ case CC_TIMECODE:
ctl_putstr(clock_var[CC_TIMECODE].text,
- clock_stat->p_lastcode,
- (unsigned)clock_stat->lencode);
+ clock_stat->p_lastcode,
+ (unsigned)clock_stat->lencode);
break;
- case CC_POLL:
+ case CC_POLL:
ctl_putuint(clock_var[CC_POLL].text, clock_stat->polls);
break;
- case CC_NOREPLY:
+ case CC_NOREPLY:
ctl_putuint(clock_var[CC_NOREPLY].text,
- clock_stat->noresponse);
+ clock_stat->noresponse);
break;
- case CC_BADFORMAT:
+ case CC_BADFORMAT:
ctl_putuint(clock_var[CC_BADFORMAT].text,
- clock_stat->badformat);
+ clock_stat->badformat);
break;
- case CC_BADDATA:
+ case CC_BADDATA:
ctl_putuint(clock_var[CC_BADDATA].text,
- clock_stat->baddata);
+ clock_stat->baddata);
break;
- case CC_FUDGETIME1:
+ case CC_FUDGETIME1:
if (mustput || (clock_stat->haveflags & CLK_HAVETIME1))
ctl_putdbl(clock_var[CC_FUDGETIME1].text,
- clock_stat->fudgetime1 * 1e3);
+ clock_stat->fudgetime1 * 1e3);
break;
- case CC_FUDGETIME2:
- if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) ctl_putdbl(clock_var[CC_FUDGETIME2].text,
- clock_stat->fudgetime2 * 1e3);
+ case CC_FUDGETIME2:
+ if (mustput || (clock_stat->haveflags & CLK_HAVETIME2))
+ ctl_putdbl(clock_var[CC_FUDGETIME2].text,
+ clock_stat->fudgetime2 * 1e3);
break;
- case CC_FUDGEVAL1:
+ case CC_FUDGEVAL1:
if (mustput || (clock_stat->haveflags & CLK_HAVEVAL1))
ctl_putint(clock_var[CC_FUDGEVAL1].text,
- clock_stat->fudgeval1);
+ clock_stat->fudgeval1);
break;
- case CC_FUDGEVAL2:
+ case CC_FUDGEVAL2:
if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) {
if (clock_stat->fudgeval1 > 1)
ctl_putadr(clock_var[CC_FUDGEVAL2].text,
- (u_int32)clock_stat->fudgeval2, NULL);
+ clock_stat->fudgeval2, NULL);
else
- ctl_putid(clock_var[CC_FUDGEVAL2].text,
- (char *)&clock_stat->fudgeval2);
+ ctl_putrefid(clock_var[CC_FUDGEVAL2].text,
+ clock_stat->fudgeval2);
}
break;
- case CC_FLAGS:
+ case CC_FLAGS:
if (mustput || (clock_stat->haveflags & (CLK_HAVEFLAG1 |
- CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
+ CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
ctl_putuint(clock_var[CC_FLAGS].text,
- clock_stat->flags);
+ clock_stat->flags);
break;
- case CC_DEVICE:
+ case CC_DEVICE:
if (clock_stat->clockdesc == NULL ||
*(clock_stat->clockdesc) == '\0') {
if (mustput)
ctl_putstr(clock_var[CC_DEVICE].text,
- "", 0);
+ "", 0);
} else {
ctl_putstr(clock_var[CC_DEVICE].text,
- clock_stat->clockdesc,
- strlen(clock_stat->clockdesc));
+ clock_stat->clockdesc,
+ strlen(clock_stat->clockdesc));
}
break;
- case CC_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf);
- if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
- be)
- break; /* really long var name */
-
- strcpy(s, clock_var[CC_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
-
- for (k = clock_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- i = strlen(k->text);
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
-
- for (k = clock_stat->kv_list; k && !(k->flags &
- EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- ss = k->text;
- if (!ss)
- continue;
-
- while (*ss && *ss != '=')
- ss++;
- i = ss - k->text;
- if (s+i+1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text, (unsigned)i);
- s += i;
- *s = '\0';
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
- ctl_putdata(buf, (unsigned)( s - buf ), 0);
- }
- break;
+ case CC_VARLIST:
+ {
+ char buf[CTL_MAX_DATA_LEN];
+ register char *s, *t, *be;
+ register const char *ss;
+ register int i;
+ register struct ctl_var *k;
+
+ s = buf;
+ be = buf + sizeof(buf);
+ if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
+ be)
+ break; /* really long var name */
+
+ snprintf(s, sizeof(buf), "%s=\"",
+ clock_var[CC_VARLIST].text);
+ s += strlen(s);
+ t = s;
+
+ for (k = clock_var; !(k->flags & EOV); k++) {
+ if (k->flags & PADDING)
+ continue;
+
+ i = strlen(k->text);
+ if (s + i + 1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text, i);
+ s += i;
+ }
+
+ for (k = clock_stat->kv_list; k && !(k->flags &
+ EOV); k++) {
+ if (k->flags & PADDING)
+ continue;
+
+ ss = k->text;
+ if (!ss)
+ continue;
+
+ while (*ss && *ss != '=')
+ ss++;
+ i = ss - k->text;
+ if (s+i+1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text, (unsigned)i);
+ s += i;
+ *s = '\0';
+ }
+ if (s+2 >= be)
+ break;
+
+ *s++ = '"';
+ *s = '\0';
+ ctl_putdata(buf, (unsigned)( s - buf ), 0);
+ }
+ break;
}
}
#endif
@@ -1915,7 +2065,7 @@ ctl_getitem(
* Delete leading commas and white space
*/
while (reqpt < reqend && (*reqpt == ',' ||
- isspace((unsigned char)*reqpt)))
+ isspace((unsigned char)*reqpt)))
reqpt++;
if (reqpt >= reqend)
return (0);
@@ -1933,7 +2083,7 @@ ctl_getitem(
if (!(v->flags & PADDING) && *cp == *(v->text)) {
tp = v->text;
while (*tp != '\0' && *tp != '=' && cp <
- reqend && *cp == *tp) {
+ reqend && *cp == *tp) {
cp++;
tp++;
}
@@ -1961,8 +2111,8 @@ ctl_getitem(
#if 0 /* Avoid possible DOS attack */
/* If we get a smarter msyslog we can re-enable this */
msyslog(LOG_WARNING,
- "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
- stoa(rmt_addr), SRCPORT(rmt_addr)
+ "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
+ stoa(rmt_addr), SRCPORT(rmt_addr)
);
#endif
return (0);
@@ -2050,14 +2200,14 @@ read_status(
rpkt.status = htons(ctlsysstatus());
for (i = 0; i < NTP_HASH_SIZE; i++) {
for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
+ peer = peer->ass_next) {
ass_stat[n++] = htons(peer->associd);
ass_stat[n++] =
htons(ctlpeerstatus(peer));
if (n ==
CTL_MAX_DATA_LEN/sizeof(u_short)) {
ctl_putdata((char *)ass_stat,
- n * sizeof(u_short), 1);
+ n * sizeof(u_short), 1);
n = 0;
}
}
@@ -2065,7 +2215,7 @@ read_status(
if (n != 0)
ctl_putdata((char *)ass_stat, n *
- sizeof(u_short), 1);
+ sizeof(u_short), 1);
ctl_flushpkt(0);
} else {
peer = findpeerbyassoc(res_associd);
@@ -2104,7 +2254,7 @@ read_variables(
char *valuep;
u_char *wants;
unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE +
- 1) : (CP_MAXCODE + 1);
+ 1) : (CP_MAXCODE + 1);
if (res_associd == 0) {
/*
* Wants system variables. Figure out which he wants
@@ -2120,14 +2270,14 @@ read_variables(
while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
if (v->flags & EOV) {
if ((v = ctl_getitem(ext_sys_var,
- &valuep)) != 0) {
+ &valuep)) != 0) {
if (v->flags & EOV) {
ctl_error(CERR_UNKNOWNVAR);
free((char *)wants);
return;
}
wants[CS_MAXCODE + 1 +
- v->code] = 1;
+ v->code] = 1;
gotvar = 1;
continue;
} else {
@@ -2142,11 +2292,11 @@ read_variables(
if (wants[i])
ctl_putsys(i);
for (i = 0; ext_sys_var &&
- !(ext_sys_var[i].flags & EOV); i++)
+ !(ext_sys_var[i].flags & EOV); i++)
if (wants[i + CS_MAXCODE + 1])
ctl_putdata(ext_sys_var[i].text,
- strlen(ext_sys_var[i].text),
- 0);
+ strlen(ext_sys_var[i].text),
+ 0);
} else {
register u_char *cs;
register struct ctl_var *kv;
@@ -2154,10 +2304,10 @@ read_variables(
for (cs = def_sys_var; *cs != 0; cs++)
ctl_putsys((int)*cs);
for (kv = ext_sys_var; kv && !(kv->flags & EOV);
- kv++)
+ kv++)
if (kv->flags & DEF)
ctl_putdata(kv->text,
- strlen(kv->text), 0);
+ strlen(kv->text), 0);
}
free((char *)wants);
} else {
@@ -2255,7 +2405,7 @@ write_variables(
return;
}
if (!ext_var && (*valuep == '\0' || !atoint(valuep,
- &val))) {
+ &val))) {
ctl_error(CERR_BADFMT);
return;
}
@@ -2266,7 +2416,7 @@ write_variables(
if (ext_var) {
char *s = (char *)emalloc(strlen(v->text) +
- strlen(valuep) + 2);
+ strlen(valuep) + 2);
const char *t;
char *tt = s;
@@ -2284,8 +2434,8 @@ write_variables(
*/
switch(v->code) {
- case CS_LEAP:
- default:
+ case CS_LEAP:
+ default:
ctl_error(CERR_UNSPEC); /* really */
return;
}
@@ -2297,15 +2447,103 @@ write_variables(
*/
/*
if (leapind != ~0 || leapwarn != ~0) {
- if (!leap_setleap((int)leapind, (int)leapwarn)) {
- ctl_error(CERR_PERMISSION);
- return;
- }
+ if (!leap_setleap((int)leapind, (int)leapwarn)) {
+ ctl_error(CERR_PERMISSION);
+ return;
+ }
}
*/
ctl_flushpkt(0);
}
+/*
+ * configure() processes ntpq :config/config-from-file, allowing
+ * generic runtime reconfiguration.
+ */
+static void configure(
+ struct recvbuf *rbufp,
+ int restrict_mask
+ )
+{
+ size_t data_count;
+ int retval;
+ int replace_nl;
+
+ /* I haven't yet implemented changes to an existing association.
+ * Hence check if the association id is 0
+ */
+ if (res_associd != 0) {
+ ctl_error(CERR_BADVALUE);
+ return;
+ }
+
+ if (restrict_mask & RES_NOMODIFY) {
+ snprintf(remote_config.err_msg,
+ sizeof(remote_config.err_msg),
+ "runtime configuration prohibited by restrict ... nomodify");
+ ctl_putdata(remote_config.err_msg,
+ strlen(remote_config.err_msg), 0);
+ ctl_flushpkt(0);
+ msyslog(LOG_NOTICE,
+ "runtime config from %s rejected due to nomodify restriction",
+ stoa(&rbufp->recv_srcadr));
+ return;
+ }
+
+ /* Initialize the remote config buffer */
+ data_count = reqend - reqpt;
+ memcpy(remote_config.buffer, reqpt, data_count);
+ if (data_count > 0
+ && '\n' != remote_config.buffer[data_count - 1])
+ remote_config.buffer[data_count++] = '\n';
+ remote_config.buffer[data_count] = '\0';
+ remote_config.pos = 0;
+ remote_config.err_pos = 0;
+ remote_config.no_errors = 0;
+
+ /* do not include terminating newline in log */
+ if (data_count > 0
+ && '\n' == remote_config.buffer[data_count - 1]) {
+ remote_config.buffer[data_count - 1] = '\0';
+ replace_nl = 1;
+ } else
+ replace_nl = 0;
+
+ DPRINTF(1, ("Got Remote Configuration Command: %s\n",
+ remote_config.buffer));
+ msyslog(LOG_NOTICE, "%s config: %s",
+ stoa(&rbufp->recv_srcadr),
+ remote_config.buffer);
+
+ if (replace_nl)
+ remote_config.buffer[data_count - 1] = '\n';
+
+ config_remotely(&rbufp->recv_srcadr);
+
+ /*
+ * Check if errors were reported. If not, output 'Config
+ * Succeeded'. Else output the error count. It would be nice
+ * to output any parser error messages.
+ */
+ if (0 == remote_config.no_errors) {
+ retval = snprintf(remote_config.err_msg,
+ sizeof(remote_config.err_msg),
+ "Config Succeeded");
+ if (retval > 0)
+ remote_config.err_pos += retval;
+ }
+
+ ctl_putdata(remote_config.err_msg, remote_config.err_pos, 0);
+ ctl_flushpkt(0);
+
+ DPRINTF(1, ("Reply: %s\n", remote_config.err_msg));
+
+ if (remote_config.no_errors > 0)
+ msyslog(LOG_NOTICE, "%d error in %s config",
+ remote_config.no_errors,
+ stoa(&rbufp->recv_srcadr));
+}
+
/*
* read_clock_status - return clock radio status
@@ -2339,13 +2577,13 @@ read_clock_status(
* for one.
*/
if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK))
- {
+ {
peer = sys_peer;
} else {
peer = 0;
for (i = 0; peer == 0 && i < NTP_HASH_SIZE; i++) {
for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
+ peer = peer->ass_next) {
if (peer->flags & FLAG_REFCLOCK)
break;
}
@@ -2369,7 +2607,7 @@ read_clock_status(
*/
clock_stat.kv_list = (struct ctl_var *)0;
refclock_control(&peer->srcadr, (struct refclockstat *)0,
- &clock_stat);
+ &clock_stat);
/*
* Look for variables in the packet.
@@ -2382,7 +2620,7 @@ read_clock_status(
while ((v = ctl_getitem(clock_var, &valuep)) != 0) {
if (v->flags & EOV) {
if ((v = ctl_getitem(clock_stat.kv_list,
- &valuep)) != 0) {
+ &valuep)) != 0) {
if (v->flags & EOV) {
ctl_error(CERR_UNKNOWNVAR);
free((char*)wants);
@@ -2403,13 +2641,13 @@ read_clock_status(
if (gotvar) {
for (i = 1; i <= CC_MAXCODE; i++)
if (wants[i])
- ctl_putclock(i, &clock_stat, 1);
+ ctl_putclock(i, &clock_stat, 1);
for (i = 0; clock_stat.kv_list &&
- !(clock_stat.kv_list[i].flags & EOV); i++)
+ !(clock_stat.kv_list[i].flags & EOV); i++)
if (wants[i + CC_MAXCODE + 1])
ctl_putdata(clock_stat.kv_list[i].text,
- strlen(clock_stat.kv_list[i].text),
- 0);
+ strlen(clock_stat.kv_list[i].text),
+ 0);
} else {
register u_char *cc;
register struct ctl_var *kv;
@@ -2417,10 +2655,10 @@ read_clock_status(
for (cc = def_clock_var; *cc != 0; cc++)
ctl_putclock((int)*cc, &clock_stat, 0);
for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV);
- kv++)
+ kv++)
if (kv->flags & DEF)
ctl_putdata(kv->text, strlen(kv->text),
- 0);
+ 0);
}
free((char*)wants);
@@ -2480,7 +2718,7 @@ set_trap(
* an error if it can't assign the trap.
*/
if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype,
- (int)res_version))
+ (int)res_version))
ctl_error(CERR_NORESOURCE);
ctl_flushpkt(0);
}
@@ -2521,7 +2759,7 @@ unset_trap(
*/
int
ctlsettrap(
- struct sockaddr_storage *raddr,
+ sockaddr_u *raddr,
struct interface *linter,
int traptype,
int version
@@ -2537,17 +2775,17 @@ ctlsettrap(
if ((tp = ctlfindtrap(raddr, linter)) != NULL) {
switch (traptype) {
- case TRAP_TYPE_CONFIG:
+ case TRAP_TYPE_CONFIG:
tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED;
break;
- case TRAP_TYPE_PRIO:
+ case TRAP_TYPE_PRIO:
if (tp->tr_flags & TRAP_CONFIGURED)
return (1); /* don't change anything */
tp->tr_flags = TRAP_INUSE;
break;
- case TRAP_TYPE_NONPRIO:
+ case TRAP_TYPE_NONPRIO:
if (tp->tr_flags & TRAP_CONFIGURED)
return (1); /* don't change anything */
tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
@@ -2576,7 +2814,7 @@ ctlsettrap(
} else if (!(tp->tr_flags & TRAP_CONFIGURED)) {
switch (traptype) {
- case TRAP_TYPE_CONFIG:
+ case TRAP_TYPE_CONFIG:
if (tptouse == NULL) {
tptouse = tp;
break;
@@ -2595,18 +2833,18 @@ ctlsettrap(
tptouse = tp;
break;
- case TRAP_TYPE_PRIO:
+ case TRAP_TYPE_PRIO:
if (tp->tr_flags & TRAP_NONPRIO) {
if (tptouse == NULL ||
(tptouse->tr_flags &
- TRAP_INUSE &&
- tptouse->tr_origtime <
- tp->tr_origtime))
+ TRAP_INUSE &&
+ tptouse->tr_origtime <
+ tp->tr_origtime))
tptouse = tp;
}
break;
- case TRAP_TYPE_NONPRIO:
+ case TRAP_TYPE_NONPRIO:
break;
}
}
@@ -2642,7 +2880,7 @@ ctlsettrap(
*/
int
ctlclrtrap(
- struct sockaddr_storage *raddr,
+ sockaddr_u *raddr,
struct interface *linter,
int traptype
)
@@ -2653,7 +2891,7 @@ ctlclrtrap(
return (0);
if (tp->tr_flags & TRAP_CONFIGURED
- && traptype != TRAP_TYPE_CONFIG)
+ && traptype != TRAP_TYPE_CONFIG)
return (0);
tp->tr_flags = 0;
@@ -2667,7 +2905,7 @@ ctlclrtrap(
*/
static struct ctl_trap *
ctlfindtrap(
- struct sockaddr_storage *raddr,
+ sockaddr_u *raddr,
struct interface *linter
)
{
@@ -2676,9 +2914,9 @@ ctlfindtrap(
for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
if ((tp->tr_flags & TRAP_INUSE)
&& (NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr))
- && SOCKCMP(raddr, &tp->tr_addr)
+ && SOCK_EQ(raddr, &tp->tr_addr)
&& (linter == tp->tr_localaddr) )
- return (tp);
+ return (tp);
}
return (struct ctl_trap *)NULL;
}
@@ -2689,69 +2927,80 @@ ctlfindtrap(
*/
void
report_event(
- int err,
- struct peer *peer
+ int err, /* error code */
+ struct peer *peer, /* peer structure pointer */
+ const char *str /* protostats string */
)
{
- register int i;
+ char statstr[NTP_MAXSTRLEN];
+ int i;
+ size_t len;
/*
- * Record error code in proper spots, but have mercy on the
- * log file.
+ * Report the error to the protostats file, system log and
+ * trappers.
*/
- if (!(err & (PEER_EVENT | CRPT_EVENT))) {
- if (ctl_sys_num_events < CTL_SYS_MAXEVENTS)
- ctl_sys_num_events++;
- if (ctl_sys_last_event != (u_char)err) {
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()), ctlsysstatus());
-#ifdef DEBUG
- if (debug)
- printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()),
- ctlsysstatus());
-#endif
- ctl_sys_last_event = (u_char)err;
+ if (peer == NULL) {
+
+ /*
+ * Discard a system report if the number of reports of
+ * the same type exceeds the maximum.
+ */
+ if (ctl_sys_last_event != (u_char)err)
+ ctl_sys_num_events= 0;
+ if (ctl_sys_num_events >= CTL_SYS_MAXEVENTS)
+ return;
+
+ ctl_sys_last_event = (u_char)err;
+ ctl_sys_num_events++;
+ snprintf(statstr, NTP_MAXSTRLEN,
+ "0.0.0.0 %04x %02x %s",
+ ctlsysstatus(), err, eventstr(err));
+ if (str != NULL) {
+ len = strlen(statstr);
+ snprintf(statstr + len, sizeof(statstr) - len,
+ " %s", str);
}
- } else if (peer != 0) {
- char *src;
+ NLOG(NLOG_SYSEVENT)
+ msyslog(LOG_INFO, statstr);
+ } else {
-#ifdef REFCLOCK
+ /*
+ * Discard a peer report if the number of reports of
+ * the same type exceeds the maximum for that peer.
+ */
+ char *src;
+ u_char errlast;
+
+ errlast = (u_char)err & ~PEER_EVENT;
+ if (peer->last_event == errlast)
+ peer->num_events = 0;
+ if (peer->num_events >= CTL_PEER_MAXEVENTS)
+ return;
+
+ peer->last_event = errlast;
+ peer->num_events++;
if (ISREFCLOCKADR(&peer->srcadr))
src = refnumtoa(&peer->srcadr);
else
-#endif
src = stoa(&peer->srcadr);
- peer->last_event = (u_char)(err & ~PEER_EVENT);
- if (peer->num_events < CTL_PEER_MAXEVENTS)
- peer->num_events++;
+ snprintf(statstr, NTP_MAXSTRLEN,
+ "%s %04x %02x %s", src,
+ ctlpeerstatus(peer), err, eventstr(err));
+ if (str != NULL) {
+ len = strlen(statstr);
+ snprintf(statstr + len, sizeof(statstr) - len,
+ " %s", str);
+ }
NLOG(NLOG_PEEREVENT)
- msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)),
- ctlpeerstatus(peer));
-#ifdef DEBUG
- if (debug)
- printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)),
- ctlpeerstatus(peer));
-#endif
- } else {
- msyslog(LOG_ERR,
- "report_event: err '%s' (0x%02x), no peer",
- eventstr(err), err);
-#ifdef DEBUG
- printf(
- "report_event: peer event '%s' (0x%02x), no peer\n",
- eventstr(err), err);
-#endif
- return;
+ msyslog(LOG_INFO, statstr);
}
+ record_proto_stats(statstr);
+#if DEBUG
+ if (debug)
+ printf("event at %lu %s\n", current_time, statstr);
+#endif
/*
* If no trappers, return.
@@ -2783,31 +3032,8 @@ report_event(
#endif /* OPENSSL */
ctl_putsys(i);
}
-#ifdef REFCLOCK
- /*
- * for clock exception events: add clock variables to
- * reflect info on exception
- */
- if (err == EVNT_CLOCKEXCPT) {
- struct refclockstat clock_stat;
- struct ctl_var *kv;
-
- clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&peer->srcadr,
- (struct refclockstat *)0, &clock_stat);
- ctl_puthex("refclockstatus",
- ctlclkstatus(&clock_stat));
- for (i = 1; i <= CC_MAXCODE; i++)
- ctl_putclock(i, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv &&
- !(kv->flags & EOV); kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text,
- strlen(kv->text), 0);
- free_varlist(clock_stat.kv_list);
- }
-#endif /* REFCLOCK */
} else {
+ NTP_INSIST(peer != NULL);
rpkt.associd = htons(peer->associd);
rpkt.status = htons(ctlpeerstatus(peer));
@@ -2826,24 +3052,24 @@ report_event(
* for clock exception events: add clock variables to
* reflect info on exception
*/
- if (err == EVNT_PEERCLOCK) {
+ if (err == PEVNT_CLOCK) {
struct refclockstat clock_stat;
struct ctl_var *kv;
clock_stat.kv_list = (struct ctl_var *)0;
refclock_control(&peer->srcadr,
- (struct refclockstat *)0, &clock_stat);
+ (struct refclockstat *)0, &clock_stat);
ctl_puthex("refclockstatus",
- ctlclkstatus(&clock_stat));
+ ctlclkstatus(&clock_stat));
for (i = 1; i <= CC_MAXCODE; i++)
ctl_putclock(i, &clock_stat, 0);
for (kv = clock_stat.kv_list; kv &&
- !(kv->flags & EOV); kv++)
+ !(kv->flags & EOV); kv++)
if (kv->flags & DEF)
ctl_putdata(kv->text,
- strlen(kv->text), 0);
+ strlen(kv->text), 0);
free_varlist(clock_stat.kv_list);
}
#endif /* REFCLOCK */
@@ -2912,7 +3138,7 @@ add_var(
*kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var));
if (k) {
memmove((char *)*kv, (char *)k,
- sizeof(struct ctl_var)*c);
+ sizeof(struct ctl_var)*c);
free((char *)k);
}
(*kv)[c].code = (u_short) c;