/* ================================================== */
+static int
+parse_source_address_or_refid(char *s, IPAddr *address, uint32_t *ref_id)
+{
+ address->family = IPADDR_UNSPEC;
+ *ref_id = 0;
+
+ /* Don't allow hostnames to avoid conflicts with reference IDs */
+ if (UTI_StringToIdIP(s, address) || UTI_StringToIP(s, address))
+ return 1;
+
+ if (CPS_ParseRefid(s, ref_id) > 0)
+ return 1;
+
+ return 0;
+}
+
+/* ================================================== */
+
static int
read_mask_address(char *line, IPAddr *mask, IPAddr *address)
{
"selectopts <address|refid> <+|-options>\0Modify selection options\0"
"reselect\0Force reselecting synchronisation source\0"
"reselectdist <dist>\0Modify reselection distance\0"
+ "offset <address|refid> <offset>\0Modify offset correction\0"
"\0\0"
"NTP sources:\0\0"
"activity\0Check how many NTP sources are online/offline\0"
"clients", "cmdaccheck", "cmdallow", "cmddeny", "cyclelogs", "delete",
"deny", "dns", "dump", "exit", "help", "keygen", "local", "makestep",
"manual", "maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll",
- "maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online", "onoffline",
+ "maxupdateskew", "minpoll", "minstratum", "ntpdata",
+ "offline", "offset", "online", "onoffline",
"polltarget", "quit", "refresh", "rekey", "reload", "reselect", "reselectdist", "reset",
"retries", "rtcdata", "selectdata", "selectopts", "serverstats", "settime",
"shutdown", "smoothing", "smoothtime", "sourcename", "sources", "sourcestats",
/* ================================================== */
+static int
+process_cmd_offset(CMD_Request *msg, char *line)
+{
+ uint32_t ref_id;
+ IPAddr ip_addr;
+ double offset;
+ char *src;
+
+ src = line;
+ line = CPS_SplitWord(line);
+
+ if (!parse_source_address_or_refid(src, &ip_addr, &ref_id) ||
+ sscanf(line, "%lf", &offset) != 1) {
+ LOG(LOGS_ERR, "Invalid syntax for offset command");
+ return 0;
+ }
+
+ UTI_IPHostToNetwork(&ip_addr, &msg->data.modify_offset.address);
+ msg->data.modify_offset.ref_id = htonl(ref_id);
+ msg->data.modify_offset.new_offset = UTI_FloatHostToNetwork(offset);
+
+ msg->command = htons(REQ_MODIFY_OFFSET);
+
+ return 1;
+}
+
+/* ================================================== */
+
static int
process_cmd_reselectdist(CMD_Request *msg, char *line)
{
src = line;
line = CPS_SplitWord(line);
- ref_id = 0;
- /* Don't allow hostnames to avoid conflicts with reference IDs */
- if (!UTI_StringToIdIP(src, &ip_addr) && !UTI_StringToIP(src, &ip_addr)) {
- ip_addr.family = IPADDR_UNSPEC;
- if (CPS_ParseRefid(src, &ref_id) == 0) {
- LOG(LOGS_ERR, "Invalid syntax for selectopts command");
- return 0;
- }
+ if (!parse_source_address_or_refid(src, &ip_addr, &ref_id)) {
+ LOG(LOGS_ERR, "Invalid syntax for selectopts command");
+ return 0;
}
mask = options = 0;
ret = process_cmd_ntpdata(line);
} else if (!strcmp(command, "offline")) {
do_normal_submit = process_cmd_offline(&tx_message, line);
+ } else if (!strcmp(command, "offset")) {
+ do_normal_submit = process_cmd_offset(&tx_message, line);
} else if (!strcmp(command, "online")) {
do_normal_submit = process_cmd_online(&tx_message, line);
} else if (!strcmp(command, "onoffline")) {
PERMIT_AUTH, /* RELOAD_SOURCES */
PERMIT_AUTH, /* DOFFSET2 */
PERMIT_AUTH, /* MODIFY_SELECTOPTS */
+ PERMIT_AUTH, /* MODIFY_OFFSET */
};
/* ================================================== */
tx_message->status = htons(STT_NOSUCHSOURCE);
}
+/* ================================================== */
+
+static void
+handle_modify_offset(CMD_Request *rx_message, CMD_Reply *tx_message)
+{
+ uint32_t ref_id;
+ IPAddr ip_addr;
+ double offset;
+
+ UTI_IPNetworkToHost(&rx_message->data.modify_offset.address, &ip_addr);
+ ref_id = ntohl(rx_message->data.modify_offset.ref_id);
+ offset = UTI_FloatNetworkToHost(rx_message->data.modify_offset.new_offset);
+
+ if ((ip_addr.family != IPADDR_UNSPEC && !NSR_ModifyOffset(&ip_addr, offset)) ||
+ (ip_addr.family == IPADDR_UNSPEC && !RCL_ModifyOffset(ref_id, offset)))
+ tx_message->status = htons(STT_NOSUCHSOURCE);
+}
+
/* ================================================== */
/* Read a packet and process it */
handle_modify_selectopts(&rx_message, &tx_message);
break;
+ case REQ_MODIFY_OFFSET:
+ handle_modify_offset(&rx_message, &tx_message);
+ break;
+
default:
DEBUG_LOG("Unhandled command %d", rx_command);
tx_message.status = htons(STT_FAILED);