|
@ -1,7 +1,8 @@ |
|
|
/* $OpenBSD: ntpd.c,v 1.69 2011/03/19 23:40:11 okan Exp $ */ |
|
|
|
|
|
|
|
|
/* $OpenBSD: ntpd.c,v 1.70 2013/10/04 14:28:16 phessler Exp $ */ |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> |
|
|
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> |
|
|
|
|
|
* Copyright (c) 2012 Mike Miller <mmiller@mgm51.com> |
|
|
* |
|
|
* |
|
|
* Permission to use, copy, modify, and distribute this software for any |
|
|
* Permission to use, copy, modify, and distribute this software for any |
|
|
* purpose with or without fee is hereby granted, provided that the above |
|
|
* purpose with or without fee is hereby granted, provided that the above |
|
@ -19,6 +20,7 @@ |
|
|
#include <sys/types.h> |
|
|
#include <sys/types.h> |
|
|
#include <sys/socket.h> |
|
|
#include <sys/socket.h> |
|
|
#include <sys/wait.h> |
|
|
#include <sys/wait.h> |
|
|
|
|
|
#include <sys/un.h> |
|
|
#include <netinet/in.h> |
|
|
#include <netinet/in.h> |
|
|
#include <errno.h> |
|
|
#include <errno.h> |
|
|
#include <poll.h> |
|
|
#include <poll.h> |
|
@ -37,12 +39,17 @@ __dead void usage(void); |
|
|
int main(int, char *[]); |
|
|
int main(int, char *[]); |
|
|
int check_child(pid_t, const char *); |
|
|
int check_child(pid_t, const char *); |
|
|
int dispatch_imsg(struct ntpd_conf *); |
|
|
int dispatch_imsg(struct ntpd_conf *); |
|
|
|
|
|
int dispatch_imsg_ctl(struct ntpd_conf *); |
|
|
void reset_adjtime(void); |
|
|
void reset_adjtime(void); |
|
|
int ntpd_adjtime(double); |
|
|
int ntpd_adjtime(double); |
|
|
void ntpd_adjfreq(double, int); |
|
|
void ntpd_adjfreq(double, int); |
|
|
void ntpd_settime(double); |
|
|
void ntpd_settime(double); |
|
|
void readfreq(void); |
|
|
void readfreq(void); |
|
|
int writefreq(double); |
|
|
int writefreq(double); |
|
|
|
|
|
void ctl_main(int, char*[]); |
|
|
|
|
|
void show_status_msg(struct imsg *); |
|
|
|
|
|
void show_peer_msg(struct imsg *, int); |
|
|
|
|
|
void show_sensor_msg(struct imsg *, int); |
|
|
|
|
|
|
|
|
volatile sig_atomic_t quit = 0; |
|
|
volatile sig_atomic_t quit = 0; |
|
|
volatile sig_atomic_t reconfig = 0; |
|
|
volatile sig_atomic_t reconfig = 0; |
|
@ -73,7 +80,13 @@ usage(void) |
|
|
{ |
|
|
{ |
|
|
extern char *__progname; |
|
|
extern char *__progname; |
|
|
|
|
|
|
|
|
fprintf(stderr, "usage: %s [-dnSsv] [-f file]\n", __progname); |
|
|
|
|
|
|
|
|
if (strcmp(__progname, "ntpd") == 0) |
|
|
|
|
|
fprintf(stderr, "usage: %s [-dnSsv] [-f file]\n", |
|
|
|
|
|
__progname); |
|
|
|
|
|
else if (strcmp(__progname, "ntpctl") == 0) |
|
|
|
|
|
fprintf(stderr, "usage: %s [-s modifier]\n", __progname); |
|
|
|
|
|
else |
|
|
|
|
|
fprintf(stderr, "Invalid program name: %s\n", __progname); |
|
|
exit(1); |
|
|
exit(1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -87,9 +100,15 @@ main(int argc, char *argv[]) |
|
|
struct pollfd pfd[POLL_MAX]; |
|
|
struct pollfd pfd[POLL_MAX]; |
|
|
pid_t chld_pid = 0, pid; |
|
|
pid_t chld_pid = 0, pid; |
|
|
const char *conffile; |
|
|
const char *conffile; |
|
|
int ch, nfds; |
|
|
|
|
|
|
|
|
int fd_ctl, ch, nfds; |
|
|
int pipe_chld[2]; |
|
|
int pipe_chld[2]; |
|
|
struct passwd *pw; |
|
|
struct passwd *pw; |
|
|
|
|
|
extern char *__progname; |
|
|
|
|
|
|
|
|
|
|
|
if (strcmp(__progname, "ntpctl") == 0) { |
|
|
|
|
|
ctl_main (argc, argv); |
|
|
|
|
|
/* NOTREACHED */ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
conffile = CONFFILE; |
|
|
conffile = CONFFILE; |
|
|
|
|
|
|
|
@ -154,9 +173,14 @@ main(int argc, char *argv[]) |
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1) |
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1) |
|
|
fatal("socketpair"); |
|
|
fatal("socketpair"); |
|
|
|
|
|
|
|
|
|
|
|
if ((fd_ctl = control_init(CTLSOCKET)) == -1) |
|
|
|
|
|
fatalx("control socket init failed"); |
|
|
|
|
|
if (control_listen(fd_ctl) == -1) |
|
|
|
|
|
fatalx("control socket listen failed"); |
|
|
|
|
|
|
|
|
signal(SIGCHLD, sighdlr); |
|
|
signal(SIGCHLD, sighdlr); |
|
|
/* fork child process */ |
|
|
/* fork child process */ |
|
|
chld_pid = ntp_main(pipe_chld, &lconf, pw); |
|
|
|
|
|
|
|
|
chld_pid = ntp_main(pipe_chld, fd_ctl, &lconf, pw); |
|
|
|
|
|
|
|
|
setproctitle("[priv]"); |
|
|
setproctitle("[priv]"); |
|
|
readfreq(); |
|
|
readfreq(); |
|
@ -489,3 +513,287 @@ writefreq(double d) |
|
|
} |
|
|
} |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
ctl_main(int argc, char *argv[]) |
|
|
|
|
|
{ |
|
|
|
|
|
struct sockaddr_un sun; |
|
|
|
|
|
struct imsg imsg; |
|
|
|
|
|
struct imsgbuf *ibuf_ctl; |
|
|
|
|
|
int fd, n, done, ch; |
|
|
|
|
|
int do_what, action; |
|
|
|
|
|
char *sockname, *show_what; |
|
|
|
|
|
|
|
|
|
|
|
sockname = CTLSOCKET; |
|
|
|
|
|
|
|
|
|
|
|
if (argc < 2) { |
|
|
|
|
|
usage(); |
|
|
|
|
|
/* NOTREACHED */ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
do_what = -1; |
|
|
|
|
|
while ((ch = getopt(argc, argv, "s:")) != -1) { |
|
|
|
|
|
switch (ch) { |
|
|
|
|
|
case 's': |
|
|
|
|
|
do_what = CTL_SHOW; |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
usage(); |
|
|
|
|
|
/* NOTREACHED */ |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
action = -1; |
|
|
|
|
|
if (do_what == CTL_SHOW) { |
|
|
|
|
|
show_what = argv[argc - 1]; |
|
|
|
|
|
if (strcmp(show_what, "peers") == 0) |
|
|
|
|
|
action = CTL_SHOW_PEERS; |
|
|
|
|
|
else if (strcmp(show_what, "sensors") == 0) |
|
|
|
|
|
action = CTL_SHOW_SENSORS; |
|
|
|
|
|
else if (strcmp(show_what, "status") == 0) |
|
|
|
|
|
action = CTL_SHOW_STATUS; |
|
|
|
|
|
else if (strcmp(show_what, "all") == 0) |
|
|
|
|
|
action = CTL_SHOW_ALL; |
|
|
|
|
|
else { |
|
|
|
|
|
usage(); |
|
|
|
|
|
/* NOTREACHED */ |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
errx (1, "invalid do_what"); |
|
|
|
|
|
|
|
|
|
|
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) |
|
|
|
|
|
err(1, "ntpctl: socket"); |
|
|
|
|
|
|
|
|
|
|
|
bzero(&sun, sizeof(sun)); |
|
|
|
|
|
sun.sun_family = AF_UNIX; |
|
|
|
|
|
if (strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path)) >= |
|
|
|
|
|
sizeof(sun.sun_path)) |
|
|
|
|
|
errx(1, "ctl socket name too long"); |
|
|
|
|
|
if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) |
|
|
|
|
|
err(1, "connect: %s", sockname); |
|
|
|
|
|
|
|
|
|
|
|
if ((ibuf_ctl = malloc(sizeof(struct imsgbuf))) == NULL) |
|
|
|
|
|
err(1, NULL); |
|
|
|
|
|
imsg_init(ibuf_ctl, fd); |
|
|
|
|
|
|
|
|
|
|
|
switch (action) { |
|
|
|
|
|
case CTL_SHOW_STATUS: |
|
|
|
|
|
imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_STATUS, |
|
|
|
|
|
0, 0, -1, NULL, 0); |
|
|
|
|
|
break; |
|
|
|
|
|
case CTL_SHOW_PEERS: |
|
|
|
|
|
imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_PEERS, |
|
|
|
|
|
0, 0, -1, NULL, 0); |
|
|
|
|
|
break; |
|
|
|
|
|
case CTL_SHOW_SENSORS: |
|
|
|
|
|
imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_SENSORS, |
|
|
|
|
|
0, 0, -1, NULL, 0); |
|
|
|
|
|
break; |
|
|
|
|
|
case CTL_SHOW_ALL: |
|
|
|
|
|
imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_ALL, |
|
|
|
|
|
0, 0, -1, NULL, 0); |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
errx(1, "invalid action"); |
|
|
|
|
|
break; /* NOTREACHED */ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
while (ibuf_ctl->w.queued) |
|
|
|
|
|
if (msgbuf_write(&ibuf_ctl->w) < 0) |
|
|
|
|
|
err(1, "ibuf_ctl: msgbuf_write error"); |
|
|
|
|
|
|
|
|
|
|
|
done = 0; |
|
|
|
|
|
while (!done) { |
|
|
|
|
|
if ((n = imsg_read(ibuf_ctl)) == -1) |
|
|
|
|
|
err(1, "ibuf_ctl: imsg_read error"); |
|
|
|
|
|
if (n == 0) |
|
|
|
|
|
errx(1, "ntpctl: pipe closed"); |
|
|
|
|
|
|
|
|
|
|
|
while (!done) { |
|
|
|
|
|
if ((n = imsg_get(ibuf_ctl, &imsg)) == -1) |
|
|
|
|
|
err(1, "ibuf_ctl: imsg_get error"); |
|
|
|
|
|
if (n == 0) |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
switch (action) { |
|
|
|
|
|
case CTL_SHOW_STATUS: |
|
|
|
|
|
show_status_msg(&imsg); |
|
|
|
|
|
done = 1; |
|
|
|
|
|
break; |
|
|
|
|
|
case CTL_SHOW_PEERS: |
|
|
|
|
|
show_peer_msg(&imsg, 0); |
|
|
|
|
|
if (imsg.hdr.type == |
|
|
|
|
|
IMSG_CTL_SHOW_PEERS_END) |
|
|
|
|
|
done = 1; |
|
|
|
|
|
break; |
|
|
|
|
|
case CTL_SHOW_SENSORS: |
|
|
|
|
|
show_sensor_msg(&imsg, 0); |
|
|
|
|
|
if (imsg.hdr.type == |
|
|
|
|
|
IMSG_CTL_SHOW_SENSORS_END) |
|
|
|
|
|
done = 1; |
|
|
|
|
|
break; |
|
|
|
|
|
case CTL_SHOW_ALL: |
|
|
|
|
|
switch (imsg.hdr.type) { |
|
|
|
|
|
case IMSG_CTL_SHOW_STATUS: |
|
|
|
|
|
show_status_msg(&imsg); |
|
|
|
|
|
break; |
|
|
|
|
|
case IMSG_CTL_SHOW_PEERS: |
|
|
|
|
|
show_peer_msg(&imsg, 1); |
|
|
|
|
|
break; |
|
|
|
|
|
case IMSG_CTL_SHOW_SENSORS: |
|
|
|
|
|
show_sensor_msg(&imsg, 1); |
|
|
|
|
|
break; |
|
|
|
|
|
case IMSG_CTL_SHOW_PEERS_END: |
|
|
|
|
|
case IMSG_CTL_SHOW_SENSORS_END: |
|
|
|
|
|
/* do nothing */ |
|
|
|
|
|
break; |
|
|
|
|
|
case IMSG_CTL_SHOW_ALL_END: |
|
|
|
|
|
done=1; |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
/* no action taken */ |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
default: |
|
|
|
|
|
/* no action taken */ |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
imsg_free(&imsg); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
close(fd); |
|
|
|
|
|
free(ibuf_ctl); |
|
|
|
|
|
exit (0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
show_status_msg(struct imsg *imsg) |
|
|
|
|
|
{ |
|
|
|
|
|
struct ctl_show_status *cstatus; |
|
|
|
|
|
double clock_offset; |
|
|
|
|
|
|
|
|
|
|
|
if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_status)) |
|
|
|
|
|
fatalx("invalid IMSG_CTL_SHOW_STATUS received"); |
|
|
|
|
|
|
|
|
|
|
|
cstatus = (struct ctl_show_status *)imsg->data; |
|
|
|
|
|
|
|
|
|
|
|
if (cstatus->peercnt > 0) |
|
|
|
|
|
printf("%d of %d peers valid\n", |
|
|
|
|
|
cstatus->valid_peers, cstatus->peercnt); |
|
|
|
|
|
|
|
|
|
|
|
if (cstatus->sensorcnt > 0) |
|
|
|
|
|
printf("%d of %d sensors valid\n", |
|
|
|
|
|
cstatus->valid_sensors, cstatus->sensorcnt); |
|
|
|
|
|
|
|
|
|
|
|
if (cstatus->peercnt + cstatus->sensorcnt == 0) |
|
|
|
|
|
printf("no peers and no sensors configured\n"); |
|
|
|
|
|
|
|
|
|
|
|
if (cstatus->synced == 1) |
|
|
|
|
|
printf("clock is synced, stratum %u\n", cstatus->stratum); |
|
|
|
|
|
else { |
|
|
|
|
|
printf("clock is unsynced"); |
|
|
|
|
|
clock_offset = cstatus->clock_offset < 0 ? |
|
|
|
|
|
-1.0 * cstatus->clock_offset : cstatus->clock_offset; |
|
|
|
|
|
if (clock_offset > 5e-7) |
|
|
|
|
|
printf(", clock offset is %.3fms\n", |
|
|
|
|
|
cstatus->clock_offset); |
|
|
|
|
|
else |
|
|
|
|
|
printf("\n"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
show_peer_msg(struct imsg *imsg, int calledfromshowall) |
|
|
|
|
|
{ |
|
|
|
|
|
struct ctl_show_peer *cpeer; |
|
|
|
|
|
int cnt; |
|
|
|
|
|
char stratum[3]; |
|
|
|
|
|
static int firsttime = 1; |
|
|
|
|
|
|
|
|
|
|
|
if (imsg->hdr.type == IMSG_CTL_SHOW_PEERS_END) { |
|
|
|
|
|
if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(cnt)) |
|
|
|
|
|
fatalx("invalid IMSG_CTL_SHOW_PEERS_END received"); |
|
|
|
|
|
memcpy(&cnt, imsg->data, sizeof(cnt)); |
|
|
|
|
|
if (cnt == 0) |
|
|
|
|
|
printf("no peers configured\n"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_peer)) |
|
|
|
|
|
fatalx("invalid IMSG_CTL_SHOW_PEERS received"); |
|
|
|
|
|
|
|
|
|
|
|
cpeer = (struct ctl_show_peer *)imsg->data; |
|
|
|
|
|
|
|
|
|
|
|
if (strlen(cpeer->peer_desc) > MAX_DISPLAY_WIDTH - 1) |
|
|
|
|
|
fatalx("peer_desc is too long"); |
|
|
|
|
|
|
|
|
|
|
|
if (firsttime) { |
|
|
|
|
|
firsttime = 0; |
|
|
|
|
|
if (calledfromshowall) |
|
|
|
|
|
printf("\n"); |
|
|
|
|
|
printf("peer\n wt tl st next poll " |
|
|
|
|
|
"offset delay jitter\n"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (cpeer->stratum > 0) |
|
|
|
|
|
snprintf(stratum, sizeof(stratum), "%2u", cpeer->stratum); |
|
|
|
|
|
else |
|
|
|
|
|
strlcpy (stratum, " -", sizeof (stratum)); |
|
|
|
|
|
|
|
|
|
|
|
printf("%s\n %1s %2u %2u %2s %4ds %4ds", |
|
|
|
|
|
cpeer->peer_desc, cpeer->syncedto == 1 ? "*" : " ", |
|
|
|
|
|
cpeer->weight, cpeer->trustlevel, stratum, cpeer->next, |
|
|
|
|
|
cpeer->poll); |
|
|
|
|
|
|
|
|
|
|
|
if (cpeer->trustlevel >= TRUSTLEVEL_BADPEER) |
|
|
|
|
|
printf(" %12.3fms %9.3fms %8.3fms\n", cpeer->offset, |
|
|
|
|
|
cpeer->delay, cpeer->jitter); |
|
|
|
|
|
else |
|
|
|
|
|
printf(" ---- peer not valid ----\n"); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
show_sensor_msg(struct imsg *imsg, int calledfromshowall) |
|
|
|
|
|
{ |
|
|
|
|
|
struct ctl_show_sensor *csensor; |
|
|
|
|
|
int cnt; |
|
|
|
|
|
static int firsttime = 1; |
|
|
|
|
|
|
|
|
|
|
|
if (imsg->hdr.type == IMSG_CTL_SHOW_SENSORS_END) { |
|
|
|
|
|
if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(cnt)) |
|
|
|
|
|
fatalx("invalid IMSG_CTL_SHOW_SENSORS_END received"); |
|
|
|
|
|
memcpy(&cnt, imsg->data, sizeof(cnt)); |
|
|
|
|
|
if (cnt == 0) |
|
|
|
|
|
printf("no sensors configured\n"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_sensor)) |
|
|
|
|
|
fatalx("invalid IMSG_CTL_SHOW_SENSORS received"); |
|
|
|
|
|
|
|
|
|
|
|
csensor = (struct ctl_show_sensor *)imsg->data; |
|
|
|
|
|
|
|
|
|
|
|
if (strlen(csensor->sensor_desc) > MAX_DISPLAY_WIDTH - 1) |
|
|
|
|
|
fatalx("sensor_desc is too long"); |
|
|
|
|
|
|
|
|
|
|
|
if (firsttime) { |
|
|
|
|
|
firsttime = 0; |
|
|
|
|
|
if (calledfromshowall) |
|
|
|
|
|
printf("\n"); |
|
|
|
|
|
printf("sensor\n wt gd st next poll " |
|
|
|
|
|
"offset correction\n"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
printf("%s\n %1s %2u %2u %2u %4ds %4ds", csensor->sensor_desc, |
|
|
|
|
|
csensor->syncedto == 1 ? "*" : " ", csensor->weight, csensor->good, |
|
|
|
|
|
csensor->stratum, csensor->next, csensor->poll); |
|
|
|
|
|
|
|
|
|
|
|
if (csensor->good == 1) |
|
|
|
|
|
printf(" %11.3fms %9.3fms\n", |
|
|
|
|
|
csensor->offset, csensor->correction); |
|
|
|
|
|
else |
|
|
|
|
|
printf(" - sensor not valid -\n"); |
|
|
|
|
|
|
|
|
|
|
|
} |