summaryrefslogtreecommitdiff
path: root/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'client.c')
-rw-r--r--client.c100
1 files changed, 54 insertions, 46 deletions
diff --git a/client.c b/client.c
index 5c3a99e..4fa7d2d 100644
--- a/client.c
+++ b/client.c
@@ -1109,6 +1109,7 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
(data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0) |
(data.params.iburst ? REQ_ADDSRC_IBURST : 0) |
(data.params.interleaved ? REQ_ADDSRC_INTERLEAVED : 0) |
+ (data.params.burst ? REQ_ADDSRC_BURST : 0) |
(data.params.sel_options & SRC_SELECT_PREFER ? REQ_ADDSRC_PREFER : 0) |
(data.params.sel_options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0) |
(data.params.sel_options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0) |
@@ -1245,6 +1246,7 @@ give_help(void)
"cyclelogs\0Close and re-open log files\0"
"dump\0Dump all measurements to save files\0"
"rekey\0Re-read keys from key file\0"
+ "shutdown\0Stop daemon\0"
"\0\0"
"Client commands:\0\0"
"dns -n|+n\0Disable/enable resolving IP addresses to hostnames\0"
@@ -1279,9 +1281,9 @@ command_name_generator(const char *text, int state)
"maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll",
"maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online",
"polltarget", "quit", "refresh", "rekey", "reselect", "reselectdist",
- "retries", "rtcdata", "serverstats", "settime", "smoothing", "smoothtime",
- "sources", "sources -v", "sourcestats", "sourcestats -v", "timeout",
- "tracking", "trimrtc", "waitsync", "writertc",
+ "retries", "rtcdata", "serverstats", "settime", "shutdown", "smoothing",
+ "smoothtime", "sources", "sources -v", "sourcestats", "sourcestats -v",
+ "timeout", "tracking", "trimrtc", "waitsync", "writertc",
NULL
};
static int list_index, len;
@@ -1324,18 +1326,16 @@ static int proto_version = PROTO_VERSION_NUMBER;
static int
submit_request(CMD_Request *request, CMD_Reply *reply)
{
- int bad_length, bad_sequence, bad_header;
int select_status;
int recv_status;
int read_length;
- int expected_length;
int command_length;
int padding_length;
struct timespec ts_now, ts_start;
struct timeval tv;
int n_attempts, new_attempt;
double timeout;
- fd_set rdfd, wrfd, exfd;
+ fd_set rdfd;
request->pkt_type = PKT_TYPE_CMD_REQUEST;
request->res1 = 0;
@@ -1347,15 +1347,15 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
new_attempt = 1;
do {
+ if (gettimeofday(&tv, NULL))
+ return 0;
+
if (new_attempt) {
new_attempt = 0;
if (n_attempts > max_retries)
return 0;
- if (gettimeofday(&tv, NULL))
- return 0;
-
UTI_TimevalToTimespec(&tv, &ts_start);
UTI_GetRandomBytes(&request->sequence, sizeof (request->sequence));
@@ -1383,9 +1383,6 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
DEBUG_LOG("Sent %d bytes", command_length);
}
- if (gettimeofday(&tv, NULL))
- return 0;
-
UTI_TimevalToTimespec(&tv, &ts_now);
/* Check if the clock wasn't stepped back */
@@ -1394,22 +1391,27 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
timeout = initial_timeout / 1000.0 * (1U << (n_attempts - 1)) -
UTI_DiffTimespecsToDouble(&ts_now, &ts_start);
- UTI_DoubleToTimeval(timeout, &tv);
DEBUG_LOG("Timeout %f seconds", timeout);
- FD_ZERO(&rdfd);
- FD_ZERO(&wrfd);
- FD_ZERO(&exfd);
+ /* Avoid calling select() with an invalid timeout */
+ if (timeout <= 0.0) {
+ new_attempt = 1;
+ continue;
+ }
+
+ UTI_DoubleToTimeval(timeout, &tv);
+ FD_ZERO(&rdfd);
FD_SET(sock_fd, &rdfd);
if (quit)
return 0;
- select_status = select(sock_fd + 1, &rdfd, &wrfd, &exfd, &tv);
+ select_status = select(sock_fd + 1, &rdfd, NULL, NULL, &tv);
if (select_status < 0) {
DEBUG_LOG("select failed : %s", strerror(errno));
+ return 0;
} else if (select_status == 0) {
/* Timeout must have elapsed, try a resend? */
new_attempt = 1;
@@ -1425,34 +1427,18 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
DEBUG_LOG("Received %d bytes", recv_status);
read_length = recv_status;
- if (read_length >= offsetof(CMD_Reply, data)) {
- expected_length = PKL_ReplyLength(reply);
- } else {
- expected_length = 0;
- }
-
- bad_length = (read_length < expected_length ||
- expected_length < offsetof(CMD_Reply, data));
-
- if (!bad_length) {
- bad_sequence = reply->sequence != request->sequence;
- } else {
- bad_sequence = 0;
- }
-
- if (bad_length || bad_sequence) {
- continue;
- }
-
- bad_header = ((reply->version != proto_version &&
- !(reply->version >= PROTO_VERSION_MISMATCH_COMPAT_CLIENT &&
- ntohs(reply->status) == STT_BADPKTVERSION)) ||
- (reply->pkt_type != PKT_TYPE_CMD_REPLY) ||
- (reply->res1 != 0) ||
- (reply->res2 != 0) ||
- (reply->command != request->command));
- if (bad_header) {
+ /* Check if the header is valid */
+ if (read_length < offsetof(CMD_Reply, data) ||
+ (reply->version != proto_version &&
+ !(reply->version >= PROTO_VERSION_MISMATCH_COMPAT_CLIENT &&
+ ntohs(reply->status) == STT_BADPKTVERSION)) ||
+ reply->pkt_type != PKT_TYPE_CMD_REPLY ||
+ reply->res1 != 0 ||
+ reply->res2 != 0 ||
+ reply->command != request->command ||
+ reply->sequence != request->sequence) {
+ DEBUG_LOG("Invalid reply");
continue;
}
@@ -1471,6 +1457,15 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
#error unknown compatibility with PROTO_VERSION - 1
#endif
+ /* Check that the packet contains all data it is supposed to have.
+ Unknown responses will always pass this test as their expected
+ length is zero. */
+ if (read_length < PKL_ReplyLength(reply)) {
+ DEBUG_LOG("Reply too short");
+ new_attempt = 1;
+ continue;
+ }
+
/* Good packet received, print out results */
DEBUG_LOG("Reply cmd=%d reply=%d stat=%d",
ntohs(reply->command), ntohs(reply->reply), ntohs(reply->status));
@@ -1577,6 +1572,9 @@ request_reply(CMD_Request *request, CMD_Reply *reply, int requested_reply, int v
return 0;
}
+ /* Make sure an unknown response was not requested */
+ assert(PKL_ReplyLength(reply));
+
return 1;
}
@@ -2540,7 +2538,7 @@ process_cmd_manual_list(const char *line)
struct timespec when;
request.command = htons(REQ_MANUAL_LIST);
- if (!request_reply(&request, &reply, RPY_MANUAL_LIST, 0))
+ if (!request_reply(&request, &reply, RPY_MANUAL_LIST2, 0))
return 0;
n_samples = ntohl(reply.data.manual_list.n_samples);
@@ -2548,7 +2546,7 @@ process_cmd_manual_list(const char *line)
print_header("# Date Time(UTC) Slewed Original Residual");
- for (i = 0; i < n_samples; i++) {
+ for (i = 0; i < n_samples && i < MAX_MANUAL_LIST_SAMPLES; i++) {
sample = &reply.data.manual_list.samples[i];
UTI_TimespecNetworkToHost(&sample->when, &when);
@@ -2709,6 +2707,14 @@ process_cmd_refresh(CMD_Request *msg, char *line)
/* ================================================== */
+static void
+process_cmd_shutdown(CMD_Request *msg, char *line)
+{
+ msg->command = htons(REQ_SHUTDOWN);
+}
+
+/* ================================================== */
+
static int
process_cmd_waitsync(char *line)
{
@@ -3004,6 +3010,8 @@ process_line(char *line)
} else if (!strcmp(command, "settime")) {
do_normal_submit = 0;
ret = process_cmd_settime(line);
+ } else if (!strcmp(command, "shutdown")) {
+ process_cmd_shutdown(&tx_message, line);
} else if (!strcmp(command, "smoothing")) {
do_normal_submit = 0;
ret = process_cmd_smoothing(line);