diff options
Diffstat (limited to 'ntpd/ntp_control.c')
-rw-r--r-- | ntpd/ntp_control.c | 1602 |
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; |