cmdmon: specify name instead of address in add request

Modify the request for adding a source to provide the name of the source
instead of its address (resolved in chronyc) in order to enable chronyd
to replace the source, support an "add pool" command, and enable an NTS
client to verify the server's certificate.

The name resolving does not block the response. Success is indicated
even if the name cannot be resolved, or a source with the same address
is already present.

To prevent unresolvable names from getting to chronyd, chronyc does not
send the request if it could not resolve the name itself (assuming they
are both running on the same host using the same resolver).
This commit is contained in:
Miroslav Lichvar 2019-12-04 12:04:19 +01:00
parent 00fff161cf
commit 02914ac637
4 changed files with 37 additions and 16 deletions

View file

@ -263,7 +263,7 @@ typedef struct {
typedef struct {
uint32_t type;
IPAddr ip_addr;
int8_t name[256];
uint32_t port;
int32_t minpoll;
int32_t maxpoll;
@ -503,6 +503,7 @@ typedef struct {
#define STT_INVALIDAF 17
#define STT_BADPKTVERSION 18
#define STT_BADPKTLENGTH 19
#define STT_INVALIDNAME 21
typedef struct {
int32_t EOR;

View file

@ -1080,7 +1080,10 @@ process_cmd_add_source(CMD_Request *msg, char *line)
LOG(LOGS_ERR, "Invalid syntax for add command");
break;
default:
if (DNS_Name2IPAddress(data.name, &ip_addr, 1) != DNS_Success) {
/* Verify that the address is resolvable (chronyc and chronyd are
assumed to be running on the same host) */
if (strlen(data.name) >= sizeof (msg->data.ntp_source.name) ||
DNS_Name2IPAddress(data.name, &ip_addr, 1) != DNS_Success) {
LOG(LOGS_ERR, "Invalid host/IP address");
break;
}
@ -1092,8 +1095,11 @@ process_cmd_add_source(CMD_Request *msg, char *line)
}
msg->data.ntp_source.type = htonl(type);
if (strlen(data.name) >= sizeof (msg->data.ntp_source.name))
assert(0);
strncpy((char *)msg->data.ntp_source.name, data.name,
sizeof (msg->data.ntp_source.name));
msg->data.ntp_source.port = htonl((unsigned long) data.port);
UTI_IPHostToNetwork(&ip_addr, &msg->data.ntp_source.ip_addr);
msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll);
msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll);
@ -1186,8 +1192,8 @@ give_help(void)
"NTP sources:\0\0"
"activity\0Check how many NTP sources are online/offline\0"
"ntpdata [<address>]\0Display information about last valid measurement\0"
"add server <address> [options]\0Add new NTP server\0"
"add peer <address> [options]\0Add new NTP peer\0"
"add server <name> [options]\0Add new NTP server\0"
"add peer <name> [options]\0Add new NTP peer\0"
"delete <address>\0Remove server or peer\0"
"burst <n-good>/<n-max> [<mask>/<address>]\0Start rapid set of measurements\0"
"maxdelay <address> <delay>\0Modify maximum valid sample delay\0"
@ -1579,6 +1585,9 @@ request_reply(CMD_Request *request, CMD_Reply *reply, int requested_reply, int v
case STT_INACTIVE:
printf("519 Client logging is not active in the daemon");
break;
case STT_INVALIDNAME:
printf("521 Invalid name");
break;
default:
printf("520 Got unexpected error from daemon");
}

View file

@ -678,10 +678,11 @@ handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message)
{
NTP_Remote_Address rem_addr;
NTP_Source_Type type;
SourceParameters params;
NSR_Status status;
char *name;
int port;
switch (ntohl(rx_message->data.ntp_source.type)) {
case REQ_ADDSRC_SERVER:
@ -695,8 +696,15 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message)
return;
}
UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
name = (char *)rx_message->data.ntp_source.name;
/* Make sure the name is terminated */
if (name[sizeof (rx_message->data.ntp_source.name) - 1] != '\0') {
tx_message->status = htons(STT_INVALIDNAME);
return;
}
port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
params.presend_minpoll = ntohl(rx_message->data.ntp_source.presend_minpoll);
@ -729,22 +737,25 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message)
(ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_TRUST ? SRC_SELECT_TRUST : 0) |
(ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_REQUIRE ? SRC_SELECT_REQUIRE : 0);
status = NSR_AddSource(&rem_addr, type, &params);
status = NSR_AddSourceByName(name, port, 0, type, &params);
switch (status) {
case NSR_Success:
break;
case NSR_UnresolvedName:
/* Try to resolve the name now */
NSR_ResolveSources();
break;
case NSR_AlreadyInUse:
tx_message->status = htons(STT_SOURCEALREADYKNOWN);
break;
case NSR_TooManySources:
tx_message->status = htons(STT_TOOMANYSOURCES);
break;
case NSR_InvalidAF:
tx_message->status = htons(STT_INVALIDAF);
break;
case NSR_NoSuchSource:
case NSR_InvalidName:
case NSR_UnresolvedName:
tx_message->status = htons(STT_INVALIDNAME);
break;
case NSR_InvalidAF:
case NSR_NoSuchSource:
assert(0);
break;
}

View file

@ -526,7 +526,7 @@ The number of all packets received from the source.
*Total valid RX*:::
The number of valid packets received from the source.
[[add_peer]]*add peer* _address_ [_option_]...::
[[add_peer]]*add peer* _name_ [_option_]...::
The *add peer* command allows a new NTP peer to be added whilst
*chronyd* is running.
+
@ -540,7 +540,7 @@ An example of using this command is shown below.
add peer foo.example.net minpoll 6 maxpoll 10 key 25
----
[[add_server]]*add server* _address_ [_option_]...::
[[add_server]]*add server* _name_ [_option_]...::
The *add server* command allows a new NTP server to be added whilst
*chronyd* is running.
+