From: Dave Hart Date: Sat, 29 Aug 2009 21:22:45 +0000 (+0000) Subject: [Bug 1293] make configuration dumper ready for release, specifically: X-Git-Tag: NTP_4_2_5P208~1^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=50f9402dc903f2ea721f9961252a0da5d36c1a1b;p=thirdparty%2Fntp.git [Bug 1293] make configuration dumper ready for release, specifically: rename ntpq dumpcfg command to "saveconfig". require authentication for saveconfig. "restrict ... nomodify" prevents saveconfig and :config. "saveconfig ." shorthand to save to startup configuration file. support strftime() substitution in saveconfig arg to timestamp the output filename, for example "saveconfig %Y%m%d-%H%M%S.conf". display saveconfig response message from ntpd in ntpq. save output filename in "savedconfig" variable, fetched with ntpq -c "rv 0 savedconfig". document saveconfig in html/ntpq.html. add ./configure --disable-saveconfig to build a smaller ntpd. log saveconfig failures and successes to syslog. bk: 4a999c25yGmWAgeJeMYlLfjAR9MezQ --- diff --git a/ChangeLog b/ChangeLog index aebcf9be1..c216d20e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +* [Bug 1293] make configuration dumper ready for release, specifically: +* rename ntpq dumpcfg command to "saveconfig". +* require authentication for saveconfig. +* "restrict ... nomodify" prevents saveconfig and :config. +* "saveconfig ." shorthand to save to startup configuration file. +* support strftime() substitution in saveconfig arg to timestamp + the output filename, for example "saveconfig %Y%m%d-%H%M%S.conf". +* display saveconfig response message from ntpd in ntpq. +* save output filename in "savedconfig" variable, fetched with ntpq -c + "rv 0 savedconfig". +* document saveconfig in html/ntpq.html. +* add ./configure --disable-saveconfig to build a smaller ntpd. +* log saveconfig failures and successes to syslog. (4.2.5p206) 2009/08/26 Released by Harlan Stenn * accopt.html typo fixes from Dave Mills. * [Bug 1283] default to remembering KoD in sntp. diff --git a/html/ntpq.html b/html/ntpq.html index f42c5481f..45d72cc8b 100644 --- a/html/ntpq.html +++ b/html/ntpq.html @@ -48,7 +48,7 @@

Interactive format commands consist of a keyword followed by zero to four arguments. Only enough characters of the full keyword to uniquely identify the command need be typed. The output of a command is normally sent to the standard output, but optionally the output of individual commands may be sent to a file by appending a >, followed by a file name, to the command line. A number of interactive format commands are executed entirely within the ntpq program itself and do not result in NTP mode-6 requests being sent to a server. These are described following.

? [command_keyword]
- helpl [command_keyword] + help [command_keyword]
A ? by itself will print a list of all the command keywords known to ntpq. A ? followed by a command keyword will print function and usage information about the command.
addvars name [ = value] [...]
rmvars name [...]
@@ -120,9 +120,13 @@ event count (see peer status word) -
clockvar [assocID] [name [ = value [...]] [...] -
cv [assocID] [name [ = value [...] ][...] +
clockvar [assocID] [name [ = value [...]] [...]
+ cv [assocID] [name [ = value [...] ][...]
Display a list of clock variables for those assocations supporting a reference clock. +
:config [...] +
Send the remainder of the command line, including whitespace, to the server as a run-time configuration command in the same format as the configuration file. This command is experimental until further notice and clarification. Authentication is of course required. +
config-from-file filename +
Send the each line of filename to the server as run-time configuration commands in the same format as the configuration file. This command is experimental until further notice and clarification. Authentication is of course required.
keyid
Specify the key ID to use for write requests.
lassociations
Perform the same function as the associations command, execept display mobilized and unmobilized associations.
mreadvar assocID assocID [ variable_name [ = value[ ... ]
@@ -184,15 +188,16 @@
readvar assocID name [ = value ] [,...]
rv assocID [ name ] [,...] -
Display the specified variables. If the association ID is omitted or is given as zero, the variables are from the system variables name space, otherwise they are from the peer variables name space. If no name is included, all operative variables in the name space are displayed. Multiple names are specified with comma separators and without whitespace. Note that time values are represented in milliseconds and frequency values in parts-per-million (PPM). Some NTP timestamps are represented in the format YYYYMMDDTTTT, where YYYY is the year, MM the month of year, DD the day of month and TTTT the time of day.
writevar assocID name = value [,...] -
Write the specified variables. If the association ID is omitted or is given as zero, the variables are from the system variables name space, otherwise they are from the peer variables name space. -
:config [...] -
Send the remainder of the command line, including whitespace, to the server as a run-time configuration command in the same format as the configuration file. This command is experimental until further notice and clarification. Authentication is of course required.
+
Display the specified variables. If the association ID is omitted or is given as zero, the variables are from the system variables name space, otherwise they are from the peer variables name space. If no name is included, all operative variables in the name space are displayed. Multiple names are specified with comma separators and without whitespace. Note that time values are represented in milliseconds and frequency values in parts-per-million (PPM). Some NTP timestamps are represented in the format YYYYMMDDTTTT, where YYYY is the year, MM the month of year, DD the day of month and TTTT the time of day. +
saveconfig filename +
Write the current configuration, including any runtime modifications given with :config or config-from-file, to the ntpd host's file filename. A single period given for filename is shorthand for the startup configuration file. filename can use strftime() format specifiers to substitute the current date and time, for example, saveconfig ntp-%Y%m%d-%H%M%S.conf. The filename used is stored in system variable savedconfig. Authentication is required. +
writevar assocID name = value [,...] +
Write the specified variables. If the association ID is omitted or is given as zero, the variables are from the system variables name space, otherwise they are from the peer variables name space.

Status Words and Kiss Codes

The current state of the operating program is shown in a set of status words maintained by the system and each association separately. These words are displayed in the rv and as commands both in hexadecimal and decoded short tip strings. The codes, tips and short explanations are on the Event Messages and Status Words page. The page also includes a list of system and peer messages, the code for the latest of which is included in the status word.

Information resulting from protocol machine state transitions is displayed using an informal set of ASCII strings called kiss codes. The original purpose was for kiss-o'-death (KoD) packets sent by the server to advise the client of an unusual condition. They are now displayed, when appropriate, in the reference identifier field in various billboards.

System Variables

-

The following system variables apear in the rv billboard. Not all variables are displayed in some configurations.

+

The following system variables appear in the rv billboard. Not all variables are displayed in some configurations.

diff --git a/include/ntp_config.h b/include/ntp_config.h index 25f93631a..5a3d41610 100644 --- a/include/ntp_config.h +++ b/include/ntp_config.h @@ -205,8 +205,9 @@ server_info *create_sim_server(struct address_node *addr, double server_offset, extern struct REMOTE_CONFIG_INFO remote_config; void config_remotely(sockaddr_u *); +#ifdef SAVECONFIG int dump_config_tree(struct config_tree *ptree, FILE *df); int dump_all_config_trees(FILE *df); - +#endif #endif /* !defined(NTP_CONFIG_H) */ diff --git a/include/ntp_control.h b/include/ntp_control.h index dd0f86557..59b98b940 100644 --- a/include/ntp_control.h +++ b/include/ntp_control.h @@ -53,9 +53,9 @@ struct ntp_control { #define CTL_OP_WRITECLOCK 5 /* write clock variables */ #define CTL_OP_SETTRAP 6 /* set trap address */ #define CTL_OP_ASYNCMSG 7 /* asynchronous message */ -#define CTL_OP_CONFIGURE 8 /* configuration message */ +#define CTL_OP_CONFIGURE 8 /* runtime configuration */ +#define CTL_OP_SAVECONFIG 9 /* save config to file */ #define CTL_OP_UNSETTRAP 31 /* unset trap */ -#define CTL_OP_DUMPCONFIG 9 /* * {En,De}coding of the system status word diff --git a/include/ntpd.h b/include/ntpd.h index ff3820237..261fe4b0c 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -260,8 +260,8 @@ extern char *sys_phone[]; /* ACTS phone numbers */ extern int config_priority_override; extern int config_priority; #endif - extern char *ntp_signd_socket; +extern struct config_tree *cfg_tree_history; /* ntp_control.c */ extern int num_ctl_traps; diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index f9fb0de71..c84f43fc4 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -463,6 +463,8 @@ free_config_tree(struct config_tree *ptree) } #endif /* DEBUG */ + +#ifdef SAVECONFIG /* Dump all trees */ int dump_all_config_trees ( @@ -1463,7 +1465,7 @@ dump_config_tree( return 0; } - +#endif /* SAVECONFIG */ /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE @@ -4392,7 +4394,9 @@ abort_resolve(void) static void do_resolve_internal(void) { +#ifndef SYS_WINNT int i; +#endif if (res_fp == NULL) { /* belch */ diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c index 7479997d2..8aac4bc86 100644 --- a/ntpd/ntp_control.c +++ b/ntpd/ntp_control.c @@ -75,7 +75,7 @@ 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 dump_config (struct recvbuf *, int); +static void save_config (struct recvbuf *, int); static struct ctl_trap *ctlfindtrap (sockaddr_u *, struct interface *); @@ -88,7 +88,7 @@ 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_DUMPCONFIG, NOAUTH, dump_config }, + { CTL_OP_SAVECONFIG, AUTH, save_config }, { CTL_OP_CONFIGURE, AUTH, configure }, { NO_REQUEST, 0 } }; @@ -546,54 +546,107 @@ ctl_error( } /* - * Call the config dumper + * save_config - Implements ntpq -c "saveconfig " + * Writes current configuration including any runtime + * changes by ntpq's :config or config-from-file */ void -dump_config( - struct recvbuf *rbufp, - int restrict_mask - ) +save_config( + struct recvbuf *rbufp, + int restrict_mask + ) { - /* Dump config to file (for now) to ntp_dumpXXXXXXXXXX.conf */ - char fullpath[256]; - char filename[80]; - char reply[80]; + char reply[128]; +#ifdef SAVECONFIG + char filespec[256]; + char filename[256]; + time_t now; int fd; FILE *fptr; + const char savedconfig_eq[] = "savedconfig="; + size_t octets; + char *savedconfig; +#endif - if (reqend - reqpt) { - strncpy(filename, reqpt, sizeof(filename)); - filename[sizeof(filename) - 1] = 0; - if (NULL != strchr(filename, '/') - || NULL != strchr(filename, '\\')) - snprintf(filename, sizeof(filename), - "ntp_dump%i.conf", time(NULL)); - } else - snprintf(filename, sizeof(filename), "ntp_dump%i.conf", - time(NULL)); + 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; + } -#ifndef SYS_WINNT - snprintf(fullpath, sizeof(fullpath), "/var/tmp/%s", filename); -#else - snprintf(fullpath, sizeof(fullpath), "%s\\%s", getenv("TEMP"), - filename); -#endif +#ifdef SAVECONFIG + if (0 == reqend - reqpt) + return; + + strncpy(filespec, reqpt, sizeof(filespec)); + filespec[sizeof(filespec) - 1] = '\0'; - fd = open(fullpath, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); + time(&now); + + /* + * "saveconfig ." is shorthand for replacing the startup + * configuration file. + */ + if ('.' == filespec[0] && '\0' == filespec[1] + && NULL != cfg_tree_history) + strncpy(filename, cfg_tree_history->source.value.s, + sizeof(filename)); + /* + * allow timestamping of the saved config filename with + * strftime() format such as: + * ntpq -c "saveconfig ntp-%Y%m%d-%H%M%S.conf" + */ + else if (0 == strftime(filename, sizeof(filename), filespec, + localtime(&now))) + strncpy(filename, filespec, sizeof(filename)); + + filename[sizeof(filename) - 1] = '\0'; + + + fd = open(filename, O_CREAT | 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)) - snprintf(reply, sizeof(reply), "Couldn't dump to file %s", - fullpath); - else - snprintf(reply, sizeof(reply), "Dumped to config file %s", - fullpath); + if (NULL == fptr || -1 == dump_all_config_trees(fptr)) { + 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)", + filename, stoa(&rbufp->recv_srcadr)); + /* + * save the output filename in system variable + * savedconfig, retrieved with: + * ntpq -c "rv 0 savedconfig" + */ + octets = sizeof(savedconfig_eq) + strlen(filename) + 1; + savedconfig = emalloc(sizeof(savedconfig_eq) + + strlen(filename) + 1); + snprintf(savedconfig, octets, "%s%s", + savedconfig_eq, filename); + set_sys_var(savedconfig, octets, RO); + } if (NULL != fptr) fclose(fptr); +#else /* !SAFECONFIG follows */ + snprintf(reply, sizeof(reply), + "saveconfig unavailable, configured with --disable-saveconfig"); +#endif ctl_putdata(reply, strlen(reply), 0); ctl_flushpkt(0); @@ -2406,6 +2459,19 @@ static void configure( 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); diff --git a/ntpd/ntp_intres.c b/ntpd/ntp_intres.c index eb88b24ed..9180af59b 100644 --- a/ntpd/ntp_intres.c +++ b/ntpd/ntp_intres.c @@ -210,12 +210,12 @@ void ntp_intres(void) { FILE *in; - struct timeval tv; - fd_set fdset; #ifdef SYS_WINNT DWORD rc; #else int rc; + struct timeval tv; + fd_set fdset; #endif #ifdef DEBUG diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index af3389f09..43e92febd 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -1704,9 +1704,8 @@ set_reuseaddr( int flag ) { - struct interface *interf; - #ifndef SO_EXCLUSIVEADDRUSE + struct interface *interf; for (interf = inter_list; interf != NULL; diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index b39843f99..d50353616 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -62,8 +62,8 @@ static void lpeers (struct parse *, FILE *); static void doopeers (int, FILE *, int); static void opeers (struct parse *, FILE *); static void lopeers (struct parse *, FILE *); -static void config (struct parse *, FILE *); -static void dumpcfg (struct parse *, FILE *); +static void config (struct parse *, FILE *); +static void saveconfig (struct parse *, FILE *); static void config_from_file (struct parse *, FILE *); @@ -71,9 +71,9 @@ static void config_from_file (struct parse *, FILE *); * Commands we understand. Ntpdc imports this. */ struct xcmd opcmds[] = { - { "dumpcfg", dumpcfg, { NTP_STR, NO, NO, NO }, - { "dumpfile", "", "", ""}, - "dump ntp server configuration"}, + { "saveconfig", saveconfig, { NTP_STR, NO, NO, NO }, + { "filename", "", "", ""}, + "save ntpd configuration to file, . for current config file"}, { "associations", associations, { NO, NO, NO, NO }, { "", "", "", "" }, "print list of association ID's and statuses for the server's peers" }, @@ -1148,7 +1148,7 @@ lpassociations( * * dumpcfg - dump ntp server configuration */ static void -dumpcfg( +saveconfig( struct parse *pcmd, FILE *fp ) @@ -1158,14 +1158,22 @@ dumpcfg( int dsize; u_short rstatus; - /* Is there a way to make an argument optional? */ - if(pcmd->nargs > 0) - res = doquery(CTL_OP_DUMPCONFIG, 0, 0, strlen(pcmd->argval[0].string), - pcmd->argval[0].string, &rstatus, &dsize, &datap); + if (0 == pcmd->nargs) + return; + + res = doquery(CTL_OP_SAVECONFIG, 0, 1, + strlen(pcmd->argval[0].string), + pcmd->argval[0].string, &rstatus, &dsize, + &datap); + + if (res != 0) + return; + + if (0 == dsize) + fprintf(fp, "(no response message, curiously)"); else { - res = doquery(CTL_OP_DUMPCONFIG, 0, 0, 0, (char *) 0, - &rstatus, &dsize, &datap); - printf("No filename supplied\n"); + datap[dsize] = '\0'; + fprintf(fp, "%s", datap); } } diff --git a/ports/winnt/include/config.h b/ports/winnt/include/config.h index 7108cfc0a..9fd6c7eef 100644 --- a/ports/winnt/include/config.h +++ b/ports/winnt/include/config.h @@ -203,7 +203,6 @@ typedef int socklen_t; */ #pragma warning(disable: 4100) /* unreferenced formal parameter */ -#pragma warning(disable: 4101) /* unreferenced local variable */ #pragma warning(disable: 4127) /* conditional expression is constant */ #pragma warning(disable: 4996) /* more secure replacement available */ @@ -224,6 +223,7 @@ typedef int socklen_t; #define HAVE_RANDOM #define MAXHOSTNAMELEN 64 #define AUTOKEY +#define SAVECONFIG 1 /* * Multimedia timer enable diff --git a/ports/winnt/ntpd/ntp_iocompletionport.c b/ports/winnt/ntpd/ntp_iocompletionport.c index c0329bb61..731613eda 100644 --- a/ports/winnt/ntpd/ntp_iocompletionport.c +++ b/ports/winnt/ntpd/ntp_iocompletionport.c @@ -444,7 +444,6 @@ OnSerialWaitComplete(ULONG_PTR i, IoCompletionInfo *lpo, DWORD Bytes, int errsta DWORD comm_mask; DWORD modem_status; static const l_fp zero_time = { 0 }; - DWORD dwBytesReturned; BOOL rc; get_systime(&arrival_time); @@ -686,7 +685,6 @@ OnSocketRecv(ULONG_PTR i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus) { struct recvbuf *buff = NULL; recvbuf_t *newbuff; - isc_boolean_t ignore_this; l_fp arrival_time; struct interface * inter = (struct interface *) i;
Variable