Browse Source

Add ntpctl(8), which allows us to query the locally running ntpd(8) process

diff from Mike Miller <mmiller mgm51 com> (many thanks!)
OK phessler@, henning@, todd@
OPENBSD_5_5
phessler 11 years ago
parent
commit
36ee6e401f
9 changed files with 967 additions and 22 deletions
  1. +5
    -3
      src/usr.sbin/ntpd/Makefile
  2. +3
    -2
      src/usr.sbin/ntpd/client.c
  3. +427
    -0
      src/usr.sbin/ntpd/control.c
  4. +33
    -6
      src/usr.sbin/ntpd/ntp.c
  5. +81
    -0
      src/usr.sbin/ntpd/ntpctl.8
  6. +6
    -2
      src/usr.sbin/ntpd/ntpd.8
  7. +312
    -4
      src/usr.sbin/ntpd/ntpd.c
  8. +98
    -3
      src/usr.sbin/ntpd/ntpd.h
  9. +2
    -2
      src/usr.sbin/ntpd/sensors.c

+ 5
- 3
src/usr.sbin/ntpd/Makefile View File

@ -1,8 +1,9 @@
# $OpenBSD: Makefile,v 1.11 2010/05/26 16:44:32 nicm Exp $
# $OpenBSD: Makefile,v 1.12 2013/10/04 14:28:15 phessler Exp $
PROG= ntpd
SRCS= ntpd.c log.c ntp.c ntp_msg.c parse.y config.c \
server.c client.c sensors.c util.c ntp_dns.c
server.c client.c sensors.c util.c ntp_dns.c \
control.c
CFLAGS+= -Wall -I${.CURDIR}
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
@ -11,6 +12,7 @@ CFLAGS+= -Wsign-compare
YFLAGS=
LDADD+= -lutil
DPADD+= ${LIBUTIL}
MAN= ntpd.8 ntpd.conf.5
LINKS= ${BINDIR}/ntpd ${BINDIR}/ntpctl
MAN= ntpd.8 ntpd.conf.5 ntpctl.8
.include <bsd.prog.mk>

+ 3
- 2
src/usr.sbin/ntpd/client.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: client.c,v 1.90 2013/04/30 11:42:56 mglocker Exp $ */
/* $OpenBSD: client.c,v 1.91 2013/10/04 14:28:16 phessler Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -36,6 +36,7 @@ set_next(struct ntp_peer *p, time_t t)
{
p->next = getmonotime() + t;
p->deadline = 0;
p->poll = t;
}
void
@ -328,6 +329,7 @@ client_dispatch(struct ntp_peer *p, u_int8_t settime)
p->reply[p->shift].offset = ((T2 - T1) + (T3 - T4)) / 2;
p->reply[p->shift].delay = (T4 - T1) - (T3 - T2);
p->reply[p->shift].status.stratum = msg.stratum;
if (p->reply[p->shift].delay < 0) {
interval = error_interval();
set_next(p, interval);
@ -348,7 +350,6 @@ client_dispatch(struct ntp_peer *p, u_int8_t settime)
p->reply[p->shift].status.refid = msg.refid;
p->reply[p->shift].status.reftime = lfp_to_d(msg.reftime);
p->reply[p->shift].status.poll = msg.ppoll;
p->reply[p->shift].status.stratum = msg.stratum;
if (p->addr->ss.ss_family == AF_INET) {
p->reply[p->shift].status.send_refid =


+ 427
- 0
src/usr.sbin/ntpd/control.c View File

@ -0,0 +1,427 @@
/* $OpenBSD: control.c,v 1.1 2013/10/04 14:28:16 phessler Exp $ */
/*
* 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
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
#include "ntpd.h"
#define CONTROL_BACKLOG 5
int
control_init(char *path)
{
struct sockaddr_un sun;
int fd;
mode_t old_umask;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
log_warn("control_init: socket");
return (-1);
}
bzero(&sun, sizeof(sun));
sun.sun_family = AF_UNIX;
if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
sizeof(sun.sun_path))
errx(1, "ctl socket name too long");
if (unlink(path) == -1)
if (errno != ENOENT) {
log_warn("control_init: unlink %s", path);
close(fd);
return (-1);
}
old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
log_warn("control_init: bind: %s", path);
close(fd);
umask(old_umask);
return (-1);
}
umask(old_umask);
if (chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
log_warn("control_init: chmod");
close(fd);
(void)unlink(path);
return (-1);
}
session_socket_blockmode(fd, BM_NONBLOCK);
return (fd);
}
int
control_listen(int fd)
{
if (fd != -1 && listen(fd, CONTROL_BACKLOG) == -1) {
log_warn("control_listen: listen");
return (-1);
}
return (0);
}
void
control_shutdown(int fd)
{
close(fd);
}
void
control_cleanup(const char *path)
{
if (path)
unlink(path);
}
int
control_accept(int listenfd)
{
int connfd;
socklen_t len;
struct sockaddr_un sun;
struct ctl_conn *ctl_conn;
len = sizeof(sun);
if ((connfd = accept(listenfd,
(struct sockaddr *)&sun, &len)) == -1) {
if (errno != EWOULDBLOCK && errno != EINTR)
log_warn("control_accept: accept");
return (0);
}
session_socket_blockmode(connfd, BM_NONBLOCK);
if ((ctl_conn = calloc(1, sizeof(struct ctl_conn))) == NULL) {
log_warn("control_accept");
close(connfd);
return (0);
}
imsg_init(&ctl_conn->ibuf, connfd);
TAILQ_INSERT_TAIL(&ctl_conns, ctl_conn, entry);
return (1);
}
struct ctl_conn *
control_connbyfd(int fd)
{
struct ctl_conn *c;
for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->ibuf.fd != fd;
c = TAILQ_NEXT(c, entry))
; /* nothing */
return (c);
}
int
control_close(int fd)
{
struct ctl_conn *c;
if ((c = control_connbyfd(fd)) == NULL) {
log_warn("control_close: fd %d: not found", fd);
return (0);
}
msgbuf_clear(&c->ibuf.w);
TAILQ_REMOVE(&ctl_conns, c, entry);
close(c->ibuf.fd);
free(c);
return (1);
}
int
control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
{
struct imsg imsg;
struct ctl_conn *c;
struct ntp_peer *p;
struct ntp_sensor *s;
struct ctl_show_status c_status;
struct ctl_show_peer c_peer;
struct ctl_show_sensor c_sensor;
int cnt;
ssize_t n;
if ((c = control_connbyfd(pfd->fd)) == NULL) {
log_warn("control_dispatch_msg: fd %d: not found", pfd->fd);
return (0);
}
if (pfd->revents & POLLOUT)
if (msgbuf_write(&c->ibuf.w) < 0) {
*ctl_cnt -= control_close(pfd->fd);
return (1);
}
if (!(pfd->revents & POLLIN))
return (0);
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) {
*ctl_cnt -= control_close(pfd->fd);
return (1);
}
for (;;) {
if ((n = imsg_get(&c->ibuf, &imsg)) == -1) {
*ctl_cnt -= control_close(pfd->fd);
return (1);
}
if (n == 0)
break;
switch (imsg.hdr.type) {
case IMSG_CTL_SHOW_STATUS:
build_show_status(&c_status);
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_STATUS, 0, 0, -1,
&c_status, sizeof (c_status));
break;
case IMSG_CTL_SHOW_PEERS:
cnt = 0;
TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
build_show_peer(&c_peer, p);
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_PEERS,
0, 0, -1, &c_peer, sizeof(c_peer));
cnt++;
}
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_PEERS_END,
0, 0, -1, &cnt, sizeof(cnt));
break;
case IMSG_CTL_SHOW_SENSORS:
cnt = 0;
TAILQ_FOREACH(s, &conf->ntp_sensors, entry) {
build_show_sensor(&c_sensor, s);
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_SENSORS,
0, 0, -1, &c_sensor, sizeof(c_sensor));
cnt++;
}
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_SENSORS_END,
0, 0, -1, &cnt, sizeof(cnt));
break;
case IMSG_CTL_SHOW_ALL:
build_show_status(&c_status);
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_STATUS, 0, 0, -1,
&c_status, sizeof (c_status));
cnt = 0;
TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
build_show_peer(&c_peer, p);
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_PEERS,
0, 0, -1, &c_peer, sizeof(c_peer));
cnt++;
}
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_PEERS_END,
0, 0, -1, &cnt, sizeof(cnt));
cnt = 0;
TAILQ_FOREACH(s, &conf->ntp_sensors, entry) {
build_show_sensor(&c_sensor, s);
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_SENSORS,
0, 0, -1, &c_sensor, sizeof(c_sensor));
cnt++;
}
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_SENSORS_END,
0, 0, -1, &cnt, sizeof(cnt));
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_ALL_END,
0, 0, -1, NULL, 0);
break;
default:
break;
}
imsg_free(&imsg);
}
return (0);
}
void
session_socket_blockmode(int fd, enum blockmodes bm)
{
int flags;
if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
fatal("fcntl F_GETFL");
if (bm == BM_NONBLOCK)
flags |= O_NONBLOCK;
else
flags &= ~O_NONBLOCK;
if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
fatal("fcntl F_SETFL");
}
void
build_show_status(struct ctl_show_status *cs)
{
struct ntp_peer *p;
struct ntp_sensor *s;
cs->peercnt = cs->valid_peers = 0;
cs->sensorcnt = cs->valid_sensors = 0;
TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
cs->peercnt++;
if (p->trustlevel >= TRUSTLEVEL_BADPEER)
cs->valid_peers++;
}
TAILQ_FOREACH(s, &conf->ntp_sensors, entry) {
cs->sensorcnt++;
if (s->update.good)
cs->valid_sensors++;
}
cs->synced = conf->status.synced;
cs->stratum = conf->status.stratum;
cs->clock_offset = getoffset() * 1000.0;
}
void
build_show_peer(struct ctl_show_peer *cp, struct ntp_peer *p)
{
const char *a = "not resolved";
const char *pool = "", *addr_head_name = "";
u_int8_t shift, best, validdelaycnt, jittercnt;
time_t now;
now = getmonotime();
if (p->addr)
a = log_sockaddr((struct sockaddr *)&p->addr->ss);
if (p->addr_head.pool)
pool = "from pool ";
if (0 != strcmp(a, p->addr_head.name))
addr_head_name = p->addr_head.name;
snprintf(cp->peer_desc, sizeof(cp->peer_desc),
"%s %s%s %s", a, pool, addr_head_name,
print_rtable(p->rtable) );
validdelaycnt = best = 0;
cp->offset = cp->delay = 0.0;
for (shift = 0; shift < OFFSET_ARRAY_SIZE; shift++) {
if (p->reply[shift].delay > 0.0) {
cp->offset += p->reply[shift].offset;
cp->delay += p->reply[shift].delay;
if (p->reply[shift].delay < p->reply[best].delay)
best = shift;
validdelaycnt++;
}
}
if (validdelaycnt > 1) {
cp->offset /= validdelaycnt;
cp->delay /= validdelaycnt;
}
/*
* use simple average for jitter calculation, as the
* RFC5905-recommended RMS average needs the math library
*/
jittercnt = 0;
cp->jitter = 0.0;
for (shift = 0; shift < OFFSET_ARRAY_SIZE; shift++) {
if (p->reply[shift].delay > 0.0 && shift != best) {
cp->jitter += p->reply[shift].delay -
p->reply[best].delay;
jittercnt++;
}
}
if (jittercnt > 1)
cp->jitter /= jittercnt;
if (p->shift == 0)
shift = OFFSET_ARRAY_SIZE - 1;
else
shift = p->shift - 1;
if (conf->status.synced == 1 &&
p->reply[shift].status.send_refid == conf->status.refid)
cp->syncedto = 1;
else
cp->syncedto = 0;
/* milliseconds to reduce number of leading zeroes */
cp->offset *= 1000.0;
cp->delay *= 1000.0;
cp->jitter *= 1000.0;
cp->weight = p->weight;
cp->trustlevel = p->trustlevel;
cp->stratum = p->reply[shift].status.stratum;
cp->next = p->next - now < 0 ? 0 : p->next - now;
cp->poll = p->poll;
}
void
build_show_sensor(struct ctl_show_sensor *cs, struct ntp_sensor *s)
{
time_t now;
u_int8_t shift;
u_int32_t refid;
now = getmonotime();
memcpy(&refid, SENSOR_DEFAULT_REFID, sizeof(refid));
refid = refid == s->refid ? 0 : s->refid;
snprintf(cs->sensor_desc, sizeof(cs->sensor_desc),
"%s %.4s", s->device, (char *)&refid);
if (s->shift == 0)
shift = SENSOR_OFFSETS - 1;
else
shift = s->shift - 1;
if (conf->status.synced == 1 &&
s->offsets[shift].status.send_refid == conf->status.refid)
cs->syncedto = 1;
else
cs->syncedto = 0;
cs->weight = s->weight;
cs->good = s->update.good;
cs->stratum = s->offsets[shift].status.stratum;
cs->next = s->next - now < 0 ? 0 : s->next - now;
cs->poll = SENSOR_QUERY_INTERVAL;
cs->offset = s->offsets[shift].offset * 1000.0;
cs->correction = (double)s->correction / 1000.0;
}

+ 33
- 6
src/usr.sbin/ntpd/ntp.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: ntp.c,v 1.118 2013/09/28 12:18:05 phessler Exp $ */
/* $OpenBSD: ntp.c,v 1.119 2013/10/04 14:28:16 phessler Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -36,13 +36,15 @@
#define PFD_PIPE_MAIN 0
#define PFD_HOTPLUG 1
#define PFD_PIPE_DNS 2
#define PFD_MAX 3
#define PFD_SOCK_CTL 3
#define PFD_MAX 4
volatile sig_atomic_t ntp_quit = 0;
volatile sig_atomic_t ntp_report = 0;
struct imsgbuf *ibuf_main;
struct imsgbuf *ibuf_dns;
struct ntpd_conf *conf;
struct ctl_conns ctl_conns;
u_int peer_cnt;
u_int sensors_cnt;
time_t lastreport;
@ -69,12 +71,14 @@ ntp_sighdlr(int sig)
}
pid_t
ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
ntp_main(int pipe_prnt[2], int fd_ctl, struct ntpd_conf *nconf,
struct passwd *pw)
{
int a, b, nfds, i, j, idx_peers, timeout;
int hotplugfd, nullfd, pipe_dns[2];
int hotplugfd, nullfd, pipe_dns[2], idx_clients;
u_int pfd_elms = 0, idx2peer_elms = 0;
u_int listener_cnt, new_cnt, sent_cnt, trial_cnt;
u_int ctl_cnt;
pid_t pid, dns_pid;
struct pollfd *pfd = NULL;
struct servent *se;
@ -84,6 +88,7 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
struct ntp_sensor *s, *next_s;
struct timespec tp;
struct stat stb;
struct ctl_conn *cc;
time_t nextaction, last_sensor_scan = 0;
void *newp;
@ -179,10 +184,12 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
conf->status.precision = a;
conf->scale = 1;
TAILQ_INIT(&ctl_conns);
sensor_init();
log_info("ntp engine ready");
ctl_cnt = 0;
peer_cnt = 0;
TAILQ_FOREACH(p, &conf->ntp_peers, entry)
peer_cnt++;
@ -203,7 +210,7 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
idx2peer_elms = peer_cnt;
}
new_cnt = PFD_MAX + peer_cnt + listener_cnt;
new_cnt = PFD_MAX + peer_cnt + listener_cnt + ctl_cnt;
if (new_cnt > pfd_elms) {
if ((newp = realloc(pfd, sizeof(struct pollfd) *
new_cnt)) == NULL) {
@ -225,6 +232,8 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
pfd[PFD_HOTPLUG].events = POLLIN;
pfd[PFD_PIPE_DNS].fd = ibuf_dns->fd;
pfd[PFD_PIPE_DNS].events = POLLIN;
pfd[PFD_SOCK_CTL].fd = fd_ctl;
pfd[PFD_SOCK_CTL].events = POLLIN;
i = PFD_MAX;
TAILQ_FOREACH(la, &conf->listen_addrs, entry) {
@ -278,6 +287,7 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
i++;
}
}
idx_clients = i;
if (last_sensor_scan == 0 ||
last_sensor_scan + SENSOR_SCAN_INTERVAL < getmonotime()) {
@ -306,6 +316,14 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
if (ibuf_dns->w.queued > 0)
pfd[PFD_PIPE_DNS].events |= POLLOUT;
TAILQ_FOREACH(cc, &ctl_conns, entry) {
pfd[i].fd = cc->ibuf.fd;
pfd[i].events = POLLIN;
if (cc->ibuf.w.queued > 0)
pfd[i].events |= POLLOUT;
i++;
}
timeout = nextaction - getmonotime();
if (timeout < 0)
timeout = 0;
@ -340,6 +358,11 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
ntp_quit = 1;
}
if (nfds > 0 && pfd[PFD_SOCK_CTL].revents & (POLLIN|POLLERR)) {
nfds--;
ctl_cnt += control_accept(fd_ctl);
}
if (nfds > 0 && pfd[PFD_HOTPLUG].revents & (POLLIN|POLLERR)) {
nfds--;
sensor_hotplugevent(hotplugfd);
@ -352,13 +375,17 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw)
ntp_quit = 1;
}
for (; nfds > 0 && j < i; j++)
for (; nfds > 0 && j < idx_clients; j++) {
if (pfd[j].revents & (POLLIN|POLLERR)) {
nfds--;
if (client_dispatch(idx2peer[j - idx_peers],
conf->settime) == -1)
ntp_quit = 1;
}
}
for (; nfds > 0 && j < i; j++)
nfds -= control_dispatch_msg(&pfd[j], &ctl_cnt);
for (s = TAILQ_FIRST(&conf->ntp_sensors); s != NULL;
s = next_s) {


+ 81
- 0
src/usr.sbin/ntpd/ntpctl.8 View File

@ -0,0 +1,81 @@
.\" $OpenBSD: ntpctl.8,v 1.1 2013/10/04 14:28:16 phessler Exp $
.\"
.\" Copyright (c) 2012 Mike Miller <mmiller@mgm51.com>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
.\" AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: October 4 2013 $
.Dt NTPCTL 8
.Os
.Sh NAME
.Nm ntpctl
.Nd "control program for the Network Time Protocol daemon"
.Sh SYNOPSIS
.Nm ntpctl
.Bk -words
.Op Fl s Ar modifier
.Ek
.Sh DESCRIPTION
The
.Nm
program displays information about the running
.Xr ntpd 8
daemon.
.Pp
The options are as follows:
.Bl -tag -width "-s modifierX"
.It Fl s Ar modifier
Show the data specified by
.Ar modifier :
.Bl -tag -width XXXXXXXXXX -compact
.Pp
.It Fl s Cm status
Show the status of peers and sensors, and whether the system clock is
synced. When the system clock is synced, the stratum is displayed.
When the system clock is not synced, the offset of the system clock,
as reported by the
.Xr adjtime 2
system call, is displayed.
.Pp
.It Fl s Cm peers
Shows the following information about each peer: weight, trustlevel,
stratum, number of seconds until the next poll, polling interval
in seconds, and offset, network delay and network jitter in
milliseconds. When the system clock is synced to a peer, an asterisk
is displayed to the left of the weight column for that peer.
.Pp
.It Fl s Cm sensors
Shows the following information about each sensor: weight, sensor "good"
status, stratum, and offset and the configured correction in
milliseconds.
When the system clock is synced to a sensor, an asterisk
is displayed to the left of the weight column for that sensor.
.Pp
.It Fl s Cm all
Shows all of the above.
.El
.Sh FILES
.Bl -tag -width "/var/db/ntpd.driftXXX" -compact
.It Pa /var/run/ntpd.sock
Socket file for communication with
.Xr ntpd 8 .
.El
.Sh SEE ALSO
.Xr adjtime 2 ,
.Xr ntpd 8 ,
.Xr ntpd.conf 5
.Sh HISTORY
The
.Nm
program first appeared in
.Ox 5.3 .

+ 6
- 2
src/usr.sbin/ntpd/ntpd.8 View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ntpd.8,v 1.35 2013/08/14 06:32:37 jmc Exp $
.\" $OpenBSD: ntpd.8,v 1.36 2013/10/04 14:28:16 phessler Exp $
.\"
.\" Copyright (c) 2003, 2004, 2006 Henning Brauer <henning@openbsd.org>
.\"
@ -14,7 +14,7 @@
.\" AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: August 14 2013 $
.Dd $Mdocdate: October 4 2013 $
.Dt NTPD 8
.Os
.Sh NAME
@ -130,12 +130,16 @@ signal, it writes its peer and sensor status to
Default configuration file.
.It Pa /var/db/ntpd.drift
Drift file.
.It Pa /var/run/ntpd.sock
Socket file for communication with
.Xr ntpctl 8 .
.El
.Sh SEE ALSO
.Xr date 1 ,
.Xr adjfreq 2 ,
.Xr adjtime 2 ,
.Xr ntpd.conf 5 ,
.Xr ntpctl 8 ,
.Xr rc 8 ,
.Xr rc.conf 8 ,
.Xr rdate 8


+ 312
- 4
src/usr.sbin/ntpd/ntpd.c View File

@ -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) 2012 Mike Miller <mmiller@mgm51.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -19,6 +20,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <errno.h>
#include <poll.h>
@ -37,12 +39,17 @@ __dead void usage(void);
int main(int, char *[]);
int check_child(pid_t, const char *);
int dispatch_imsg(struct ntpd_conf *);
int dispatch_imsg_ctl(struct ntpd_conf *);
void reset_adjtime(void);
int ntpd_adjtime(double);
void ntpd_adjfreq(double, int);
void ntpd_settime(double);
void readfreq(void);
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 reconfig = 0;
@ -73,7 +80,13 @@ usage(void)
{
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);
}
@ -87,9 +100,15 @@ main(int argc, char *argv[])
struct pollfd pfd[POLL_MAX];
pid_t chld_pid = 0, pid;
const char *conffile;
int ch, nfds;
int fd_ctl, ch, nfds;
int pipe_chld[2];
struct passwd *pw;
extern char *__progname;
if (strcmp(__progname, "ntpctl") == 0) {
ctl_main (argc, argv);
/* NOTREACHED */
}
conffile = CONFFILE;
@ -154,9 +173,14 @@ main(int argc, char *argv[])
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1)
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);
/* fork child process */
chld_pid = ntp_main(pipe_chld, &lconf, pw);
chld_pid = ntp_main(pipe_chld, fd_ctl, &lconf, pw);
setproctitle("[priv]");
readfreq();
@ -489,3 +513,287 @@ writefreq(double d)
}
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");
}

+ 98
- 3
src/usr.sbin/ntpd/ntpd.h View File

@ -1,7 +1,8 @@
/* $OpenBSD: ntpd.h,v 1.107 2013/04/30 11:42:56 mglocker Exp $ */
/* $OpenBSD: ntpd.h,v 1.108 2013/10/04 14:28:16 phessler Exp $ */
/*
* 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
* purpose with or without fee is hereby granted, provided that the above
@ -28,6 +29,8 @@
#include <netdb.h>
#include <pwd.h>
#include <stdarg.h>
#include <event.h>
#include <poll.h>
#include "ntp.h"
#include <imsg.h>
@ -35,6 +38,7 @@
#define NTPD_USER "_ntp"
#define CONFFILE "/etc/ntpd.conf"
#define DRIFTFILE "/var/db/ntpd.drift"
#define CTLSOCKET "/var/run/ntpd.sock"
#define INTERVAL_QUERY_NORMAL 30 /* sync to peers every n secs */
#define INTERVAL_QUERY_PATHETIC 60
@ -60,6 +64,7 @@
#define MAX_FREQUENCY_ADJUST 128e-5 /* max correction per iteration */
#define REPORT_INTERVAL (24*60*60) /* interval between status reports */
#define MAX_SEND_ERRORS 3 /* max send errors before reconnect */
#define MAX_DISPLAY_WIDTH 80 /* max chars in ctl_show report line */
#define FILTER_ADJFREQ 0x01 /* set after doing adjfreq */
@ -67,6 +72,7 @@
#define SENSOR_QUERY_INTERVAL 15
#define SENSOR_QUERY_INTERVAL_SETTIME (SETTIME_TIMEOUT/3)
#define SENSOR_SCAN_INTERVAL (5*60)
#define SENSOR_DEFAULT_REFID "HARD"
enum client_state {
STATE_NONE,
@ -128,6 +134,7 @@ struct ntp_peer {
enum client_state state;
time_t next;
time_t deadline;
time_t poll;
u_int32_t id;
u_int8_t shift;
u_int8_t trustlevel;
@ -184,12 +191,83 @@ struct ntpd_conf {
u_int8_t filters;
};
struct imsgev {
struct imsgbuf ibuf;
void (*handler)(int, short, void *);
struct event ev;
void *data;
short events;
};
struct ctl_show_status {
u_int peercnt;
u_int sensorcnt;
u_int valid_peers;
u_int valid_sensors;
u_int8_t synced;
u_int8_t stratum;
double clock_offset;
};
struct ctl_show_peer {
char peer_desc[MAX_DISPLAY_WIDTH];
u_int8_t syncedto;
u_int8_t weight;
u_int8_t trustlevel;
u_int8_t stratum;
time_t next;
time_t poll;
double offset;
double delay;
double jitter;
};
struct ctl_show_sensor {
char sensor_desc[MAX_DISPLAY_WIDTH];
u_int8_t syncedto;
u_int8_t weight;
u_int8_t good;
u_int8_t stratum;
time_t next;
time_t poll;
double offset;
double correction;
};
enum blockmodes {
BM_NORMAL,
BM_NONBLOCK
};
struct ctl_conn {
TAILQ_ENTRY(ctl_conn) entry;
struct imsgev iev;
struct imsgbuf ibuf;
};
TAILQ_HEAD(ctl_conns, ctl_conn) ;
enum imsg_type {
IMSG_NONE,
IMSG_ADJTIME,
IMSG_ADJFREQ,
IMSG_SETTIME,
IMSG_HOST_DNS
IMSG_HOST_DNS,
IMSG_CTL_SHOW_STATUS,
IMSG_CTL_SHOW_PEERS,
IMSG_CTL_SHOW_PEERS_END,
IMSG_CTL_SHOW_SENSORS,
IMSG_CTL_SHOW_SENSORS_END,
IMSG_CTL_SHOW_ALL,
IMSG_CTL_SHOW_ALL_END
};
enum ctl_actions {
CTL_SHOW,
CTL_SHOW_STATUS,
CTL_SHOW_PEERS,
CTL_SHOW_SENSORS,
CTL_SHOW_ALL
};
/* prototypes */
@ -205,7 +283,7 @@ void fatalx(const char *);
const char *log_sockaddr(struct sockaddr *);
/* ntp.c */
pid_t ntp_main(int[2], struct ntpd_conf *, struct passwd *);
pid_t ntp_main(int[2], int, struct ntpd_conf *, struct passwd *);
int priv_adjtime(void);
void priv_settime(double);
void priv_host_dns(char *, u_int32_t);
@ -214,6 +292,7 @@ void update_scale(double);
time_t scale_interval(time_t);
time_t error_interval(void);
extern struct ntpd_conf *conf;
extern struct ctl_conns ctl_conns;
/* parse.y */
int parse_config(const char *, struct ntpd_conf *);
@ -263,3 +342,19 @@ void sensor_hotplugevent(int);
/* ntp_dns.c */
pid_t ntp_dns(int[2], struct ntpd_conf *, struct passwd *);
/* control.c */
int control_init(char *);
int control_listen(int);
void control_shutdown(int);
void control_cleanup(const char *);
int control_accept(int);
struct ctl_conn *control_connbyfd(int);
int control_close(int);
int control_dispatch_msg(struct pollfd *, u_int *);
void session_socket_blockmode(int, enum blockmodes);
void build_show_status(struct ctl_show_status *);
void build_show_peer(struct ctl_show_peer *,
struct ntp_peer *);
void build_show_sensor(struct ctl_show_sensor *,
struct ntp_sensor *);

+ 2
- 2
src/usr.sbin/ntpd/sensors.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: sensors.c,v 1.46 2012/09/20 12:43:16 patrick Exp $ */
/* $OpenBSD: sensors.c,v 1.47 2013/10/04 14:28:16 phessler Exp $ */
/*
* Copyright (c) 2006 Henning Brauer <henning@openbsd.org>
@ -140,7 +140,7 @@ sensor_add(int sensordev, char *dxname)
s->sensordevid = sensordev;
if (cs->refstr == NULL)
memcpy(&s->refid, "HARD", sizeof(s->refid));
memcpy(&s->refid, SENSOR_DEFAULT_REFID, sizeof(s->refid));
else {
s->refid = 0;
strncpy((char *)&s->refid, cs->refstr, sizeof(s->refid));


Loading…
Cancel
Save