it is just capable of answering (s)ntp4 requests with the local time for now. imsg/buffer and logging framework from bgpd, ntp protocol hackery with Alexander GuyOPENBSD_3_6
@ -0,0 +1,15 @@ | |||
# $OpenBSD: Makefile,v 1.1 2004/05/31 13:46:16 henning Exp $ | |||
.PATH: ${.CURDIR}/.. | |||
PROG= ntpd | |||
SRCS= ntpd.c buffer.c log.c imsg.c ntp.c | |||
CFLAGS+= -Wall -I${.CURDIR} | |||
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes | |||
CFLAGS+= -Wmissing-declarations | |||
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual | |||
CFLAGS+= -Wsign-compare | |||
YFLAGS= | |||
NOMAN= | |||
.include <bsd.prog.mk> |
@ -0,0 +1,182 @@ | |||
/* $OpenBSD: buffer.c,v 1.1 2004/05/31 13:46:16 henning Exp $ */ | |||
/* | |||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> | |||
* | |||
* 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. | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/uio.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <err.h> | |||
#include <errno.h> | |||
#include <limits.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include "ntpd.h" | |||
int buf_write(int, struct buf *); | |||
void buf_enqueue(struct msgbuf *, struct buf *); | |||
void buf_dequeue(struct msgbuf *, struct buf *); | |||
struct buf * | |||
buf_open(ssize_t len) | |||
{ | |||
struct buf *buf; | |||
if ((buf = calloc(1, sizeof(struct buf))) == NULL) | |||
return (NULL); | |||
if ((buf->buf = malloc(len)) == NULL) { | |||
free(buf); | |||
return (NULL); | |||
} | |||
buf->size = len; | |||
return (buf); | |||
} | |||
int | |||
buf_add(struct buf *buf, void *data, ssize_t len) | |||
{ | |||
if (buf->wpos + len > buf->size) | |||
return (-1); | |||
memcpy(buf->buf + buf->wpos, data, len); | |||
buf->wpos += len; | |||
return (0); | |||
} | |||
int | |||
buf_close(struct msgbuf *msgbuf, struct buf *buf) | |||
{ | |||
buf_enqueue(msgbuf, buf); | |||
return (1); | |||
} | |||
int | |||
buf_write(int sock, struct buf *buf) | |||
{ | |||
ssize_t n; | |||
if ((n = write(sock, buf->buf + buf->rpos, | |||
buf->size - buf->rpos)) == -1) { | |||
if (errno == EAGAIN) /* cannot write immediately */ | |||
return (0); | |||
else | |||
return (-1); | |||
} | |||
if (n == 0) { /* connection closed */ | |||
errno = 0; | |||
return (-2); | |||
} | |||
if (n < buf->size - buf->rpos) { /* not all data written yet */ | |||
buf->rpos += n; | |||
return (0); | |||
} else | |||
return (1); | |||
} | |||
void | |||
buf_free(struct buf *buf) | |||
{ | |||
free(buf->buf); | |||
free(buf); | |||
} | |||
void | |||
msgbuf_init(struct msgbuf *msgbuf) | |||
{ | |||
msgbuf->queued = 0; | |||
msgbuf->fd = -1; | |||
TAILQ_INIT(&msgbuf->bufs); | |||
} | |||
void | |||
msgbuf_clear(struct msgbuf *msgbuf) | |||
{ | |||
struct buf *buf; | |||
while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL) | |||
buf_dequeue(msgbuf, buf); | |||
} | |||
int | |||
msgbuf_write(struct msgbuf *msgbuf) | |||
{ | |||
/* | |||
* possible race here | |||
* when we cannot write out data completely from a buffer, | |||
* we MUST return and NOT try to write out stuff from later buffers - | |||
* the socket might have become writeable again | |||
*/ | |||
struct iovec iov[IOV_MAX]; | |||
struct buf *buf, *next; | |||
int i = 0; | |||
ssize_t n; | |||
bzero(&iov, sizeof(iov)); | |||
TAILQ_FOREACH(buf, &msgbuf->bufs, entries) { | |||
if (i >= IOV_MAX) | |||
break; | |||
iov[i].iov_base = buf->buf + buf->rpos; | |||
iov[i].iov_len = buf->size - buf->rpos; | |||
i++; | |||
} | |||
if ((n = writev(msgbuf->fd, iov, i)) == -1) { | |||
if (errno == EAGAIN) /* cannot write immediately */ | |||
return (0); | |||
else | |||
return (-1); | |||
} | |||
if (n == 0) { /* connection closed */ | |||
errno = 0; | |||
return (-2); | |||
} | |||
for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; | |||
buf = next) { | |||
next = TAILQ_NEXT(buf, entries); | |||
if (n >= buf->size - buf->rpos) { | |||
n -= buf->size - buf->rpos; | |||
buf_dequeue(msgbuf, buf); | |||
} else { | |||
buf->rpos += n; | |||
n = 0; | |||
} | |||
} | |||
return (0); | |||
} | |||
void | |||
buf_enqueue(struct msgbuf *msgbuf, struct buf *buf) | |||
{ | |||
TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entries); | |||
msgbuf->queued++; | |||
} | |||
void | |||
buf_dequeue(struct msgbuf *msgbuf, struct buf *buf) | |||
{ | |||
TAILQ_REMOVE(&msgbuf->bufs, buf, entries); | |||
msgbuf->queued--; | |||
buf_free(buf); | |||
} |
@ -0,0 +1,215 @@ | |||
/* $OpenBSD: imsg.c,v 1.1 2004/05/31 13:46:16 henning Exp $ */ | |||
/* | |||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> | |||
* | |||
* 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. | |||
*/ | |||
#include <sys/types.h> | |||
#include <errno.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include "ntpd.h" | |||
int imsg_compose_core(struct imsgbuf *, int, u_int32_t, void *, | |||
u_int16_t, pid_t); | |||
struct buf *imsg_create_core(struct imsgbuf *, int, u_int32_t, u_int16_t, | |||
pid_t); | |||
void | |||
imsg_init(struct imsgbuf *ibuf, int fd) | |||
{ | |||
msgbuf_init(&ibuf->w); | |||
bzero(&ibuf->r, sizeof(ibuf->r)); | |||
ibuf->fd = fd; | |||
ibuf->w.fd = fd; | |||
ibuf->pid = getpid(); | |||
} | |||
int | |||
imsg_read(struct imsgbuf *ibuf) | |||
{ | |||
ssize_t n; | |||
if ((n = read(ibuf->fd, ibuf->r.buf + ibuf->r.wpos, | |||
sizeof(ibuf->r.buf) - ibuf->r.wpos)) == -1) { | |||
if (errno != EINTR && errno != EAGAIN) { | |||
log_warn("imsg_read: pipe read error"); | |||
return (-1); | |||
} | |||
return (0); | |||
} | |||
ibuf->r.wpos += n; | |||
return (n); | |||
} | |||
int | |||
imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) | |||
{ | |||
ssize_t datalen = 0; | |||
size_t av, left; | |||
av = ibuf->r.wpos; | |||
if (IMSG_HEADER_SIZE > av) | |||
return (0); | |||
memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); | |||
if (imsg->hdr.len < IMSG_HEADER_SIZE || | |||
imsg->hdr.len > MAX_IMSGSIZE) { | |||
log_warnx("imsg_get: imsg hdr len out of bounds"); | |||
return (-1); | |||
} | |||
if (imsg->hdr.len > av) | |||
return (0); | |||
datalen = imsg->hdr.len - IMSG_HEADER_SIZE; | |||
ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE; | |||
if ((imsg->data = malloc(datalen)) == NULL) { | |||
log_warn("imsg_get"); | |||
return (-1); | |||
} | |||
memcpy(imsg->data, ibuf->r.rptr, datalen); | |||
if (imsg->hdr.len < av) { | |||
left = av - imsg->hdr.len; | |||
memcpy(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left); | |||
ibuf->r.wpos = left; | |||
} else | |||
ibuf->r.wpos = 0; | |||
return (datalen + IMSG_HEADER_SIZE); | |||
} | |||
int | |||
imsg_compose(struct imsgbuf *ibuf, int type, u_int32_t peerid, void *data, | |||
u_int16_t dlen) | |||
{ | |||
return (imsg_compose_core(ibuf, type, peerid, data, dlen, ibuf->pid)); | |||
} | |||
int | |||
imsg_compose_pid(struct imsgbuf *ibuf, int type, pid_t pid, void *data, | |||
u_int16_t datalen) | |||
{ | |||
return (imsg_compose_core(ibuf, type, 0, data, datalen, pid)); | |||
} | |||
int | |||
imsg_compose_core(struct imsgbuf *ibuf, int type, u_int32_t peerid, void *data, | |||
u_int16_t datalen, pid_t pid) | |||
{ | |||
struct buf *wbuf; | |||
struct imsg_hdr hdr; | |||
int n; | |||
hdr.len = datalen + IMSG_HEADER_SIZE; | |||
hdr.type = type; | |||
hdr.peerid = peerid; | |||
hdr.pid = pid; | |||
wbuf = buf_open(hdr.len); | |||
if (wbuf == NULL) { | |||
log_warn("imsg_compose: buf_open"); | |||
return (-1); | |||
} | |||
if (buf_add(wbuf, &hdr, sizeof(hdr)) == -1) { | |||
log_warnx("imsg_compose: buf_add error"); | |||
buf_free(wbuf); | |||
return (-1); | |||
} | |||
if (datalen) | |||
if (buf_add(wbuf, data, datalen) == -1) { | |||
log_warnx("imsg_compose: buf_add error"); | |||
buf_free(wbuf); | |||
return (-1); | |||
} | |||
if ((n = buf_close(&ibuf->w, wbuf)) < 0) { | |||
log_warnx("imsg_compose: buf_add error"); | |||
buf_free(wbuf); | |||
return (-1); | |||
} | |||
return (n); | |||
} | |||
struct buf * | |||
imsg_create(struct imsgbuf *ibuf, int type, u_int32_t peerid, u_int16_t dlen) | |||
{ | |||
return (imsg_create_core(ibuf, type, peerid, dlen, ibuf->pid)); | |||
} | |||
struct buf * | |||
imsg_create_pid(struct imsgbuf *ibuf, int type, pid_t pid, u_int16_t datalen) | |||
{ | |||
return (imsg_create_core(ibuf, type, 0, datalen, pid)); | |||
} | |||
struct buf * | |||
imsg_create_core(struct imsgbuf *ibuf, int type, u_int32_t peerid, | |||
u_int16_t datalen, pid_t pid) | |||
{ | |||
struct buf *wbuf; | |||
struct imsg_hdr hdr; | |||
hdr.len = datalen + IMSG_HEADER_SIZE; | |||
hdr.type = type; | |||
hdr.peerid = peerid; | |||
hdr.pid = pid; | |||
wbuf = buf_open(hdr.len); | |||
if (wbuf == NULL) { | |||
log_warn("imsg_create: buf_open"); | |||
return (NULL); | |||
} | |||
if (buf_add(wbuf, &hdr, sizeof(hdr)) == -1) { | |||
log_warnx("imsg_create: buf_add error"); | |||
buf_free(wbuf); | |||
return (NULL); | |||
} | |||
return (wbuf); | |||
} | |||
int | |||
imsg_add(struct buf *msg, void *data, u_int16_t datalen) | |||
{ | |||
if (datalen) | |||
if (buf_add(msg, data, datalen) == -1) { | |||
log_warnx("imsg_add: buf_add error"); | |||
buf_free(msg); | |||
return (-1); | |||
} | |||
return (datalen); | |||
} | |||
int | |||
imsg_close(struct imsgbuf *ibuf, struct buf *msg) | |||
{ | |||
int n; | |||
if ((n = buf_close(&ibuf->w, msg)) < 0) { | |||
log_warnx("imsg_close: buf_add error"); | |||
buf_free(msg); | |||
return (-1); | |||
} | |||
return (n); | |||
} | |||
void | |||
imsg_free(struct imsg *imsg) | |||
{ | |||
free(imsg->data); | |||
} |
@ -0,0 +1,154 @@ | |||
/* $OpenBSD: log.c,v 1.1 2004/05/31 13:46:16 henning Exp $ */ | |||
/* | |||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> | |||
* | |||
* 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. | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/socket.h> | |||
#include <netinet/in.h> | |||
#include <arpa/inet.h> | |||
#include <err.h> | |||
#include <errno.h> | |||
#include <stdarg.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <syslog.h> | |||
#include <unistd.h> | |||
#include "ntpd.h" | |||
int debug; | |||
void logit(int, const char *, ...); | |||
void | |||
log_init(int n_debug) | |||
{ | |||
extern char *__progname; | |||
debug = n_debug; | |||
if (!debug) | |||
openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); | |||
} | |||
void | |||
logit(int pri, const char *fmt, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, fmt); | |||
vlog(pri, fmt, ap); | |||
va_end(ap); | |||
} | |||
void | |||
vlog(int pri, const char *fmt, va_list ap) | |||
{ | |||
char *nfmt; | |||
if (debug) { | |||
/* best effort in out of mem situations */ | |||
if (asprintf(&nfmt, "%s\n", fmt) == -1) { | |||
vfprintf(stderr, fmt, ap); | |||
fprintf(stderr, "\n"); | |||
} else { | |||
vfprintf(stderr, nfmt, ap); | |||
free(nfmt); | |||
} | |||
fflush(stderr); | |||
} else | |||
vsyslog(pri, fmt, ap); | |||
} | |||
void | |||
log_warn(const char *emsg, ...) | |||
{ | |||
char *nfmt; | |||
va_list ap; | |||
/* best effort to even work in out of memory situations */ | |||
if (emsg == NULL) | |||
logit(LOG_CRIT, "%s", strerror(errno)); | |||
else { | |||
va_start(ap, emsg); | |||
if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) { | |||
/* we tried it... */ | |||
vlog(LOG_CRIT, emsg, ap); | |||
logit(LOG_CRIT, "%s", strerror(errno)); | |||
} else { | |||
vlog(LOG_CRIT, nfmt, ap); | |||
free(nfmt); | |||
} | |||
va_end(ap); | |||
} | |||
} | |||
void | |||
log_warnx(const char *emsg, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, emsg); | |||
vlog(LOG_CRIT, emsg, ap); | |||
va_end(ap); | |||
} | |||
void | |||
log_info(const char *emsg, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, emsg); | |||
vlog(LOG_INFO, emsg, ap); | |||
va_end(ap); | |||
} | |||
void | |||
log_debug(const char *emsg, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, emsg); | |||
vlog(LOG_DEBUG, emsg, ap); | |||
va_end(ap); | |||
} | |||
void | |||
fatal(const char *emsg) | |||
{ | |||
if (emsg == NULL) | |||
logit(LOG_CRIT, "fatal: %s", strerror(errno)); | |||
else | |||
if (errno) | |||
logit(LOG_CRIT, "fatal: %s: %s", | |||
emsg, strerror(errno)); | |||
else | |||
logit(LOG_CRIT, "fatal: %s", emsg); | |||
exit(1); | |||
} | |||
void | |||
fatalx(const char *emsg) | |||
{ | |||
errno = 0; | |||
fatal(emsg); | |||
} |
@ -0,0 +1,385 @@ | |||
/* $OpenBSD: ntp.c,v 1.1 2004/05/31 13:46:16 henning Exp $ */ | |||
/* | |||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> | |||
* Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org> | |||
* | |||
* 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. | |||
*/ | |||
#include <sys/param.h> | |||
#include <errno.h> | |||
#include <netdb.h> | |||
#include <poll.h> | |||
#include <pwd.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include "ntpd.h" | |||
#include "ntp.h" | |||
#define PFD_LISTEN 0 | |||
#define PFD_PIPE_MAIN 1 | |||
#define PFD_MAX 2 | |||
volatile sig_atomic_t ntp_quit = 0; | |||
struct imsgbuf ibuf_main; | |||
struct l_fixedpt ref_ts; | |||
void ntp_sighdlr(int); | |||
int setup_listener(struct servent *); | |||
int ntp_dispatch_imsg(void); | |||
int ntp_dispatch(int fd); | |||
int parse_ntp_msg(char *, ssize_t, struct ntp_msg *); | |||
int ntp_reply(int, struct sockaddr *, struct ntp_msg *, int); | |||
int ntp_send(int, struct sockaddr *, struct ntp_msg *, ssize_t, int); | |||
void get_ts(struct l_fixedpt *); | |||
void | |||
ntp_sighdlr(int sig) | |||
{ | |||
switch (sig) { | |||
case SIGINT: | |||
case SIGTERM: | |||
ntp_quit = 1; | |||
break; | |||
} | |||
} | |||
pid_t | |||
ntp_main(int pipe_prnt[2]) | |||
{ | |||
int nfds; | |||
int sock = -1; | |||
pid_t pid; | |||
struct pollfd pfd[PFD_MAX]; | |||
struct passwd *pw; | |||
struct servent *se; | |||
switch (pid = fork()) { | |||
case -1: | |||
fatal("cannot fork"); | |||
case 0: | |||
break; | |||
default: | |||
return (pid); | |||
} | |||
if ((se = getservbyname("ntp", "udp")) == NULL) | |||
fatal("getservbyname"); | |||
if ((pw = getpwnam(NTPD_USER)) == NULL) | |||
fatal(NULL); | |||
if (chroot(pw->pw_dir) == -1) | |||
fatal("chroot"); | |||
if (chdir("/") == -1) | |||
fatal("chdir(\"/\")"); | |||
setproctitle("ntp engine"); | |||
sock = setup_listener(se); | |||
if (setgroups(1, &pw->pw_gid) || | |||
setegid(pw->pw_gid) || setgid(pw->pw_gid) || | |||
seteuid(pw->pw_uid) || setuid(pw->pw_uid)) | |||
fatal("can't drop privileges"); | |||
endpwent(); | |||
endservent(); | |||
signal(SIGTERM, ntp_sighdlr); | |||
signal(SIGINT, ntp_sighdlr); | |||
signal(SIGPIPE, SIG_IGN); | |||
close(pipe_prnt[0]); | |||
imsg_init(&ibuf_main, pipe_prnt[1]); | |||
log_info("ntp engine ready"); | |||
while (ntp_quit == 0) { | |||
get_ts(&ref_ts); /* XXX */ | |||
bzero(&pfd, sizeof(pfd)); | |||
pfd[PFD_LISTEN].fd = sock; | |||
pfd[PFD_LISTEN].events = POLLIN; | |||
pfd[PFD_PIPE_MAIN].fd = ibuf_main.fd; | |||
pfd[PFD_PIPE_MAIN].events = POLLIN; | |||
if (ibuf_main.w.queued > 0) | |||
pfd[PFD_PIPE_MAIN].events |= POLLOUT; | |||
if ((nfds = poll(pfd, 2, INFTIM)) == -1) | |||
if (errno != EINTR) { | |||
log_warn("poll error"); | |||
ntp_quit = 1; | |||
} | |||
if (nfds > 0 && (pfd[PFD_PIPE_MAIN].revents & POLLOUT)) | |||
if (msgbuf_write(&ibuf_main.w) < 0) { | |||
log_warn("pipe write error (to parent)"); | |||
ntp_quit = 1; | |||
} | |||
if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLIN) { | |||
nfds--; | |||
if (ntp_dispatch_imsg() == -1) | |||
ntp_quit = 1; | |||
} | |||
if (nfds > 0 && pfd[PFD_LISTEN].revents & POLLIN) { | |||
nfds--; | |||
if (ntp_dispatch(sock) == -1) | |||
ntp_quit = 1; | |||
} | |||
} | |||
msgbuf_write(&ibuf_main.w); | |||
msgbuf_clear(&ibuf_main.w); | |||
log_info("ntp engine exiting"); | |||
_exit(0); | |||
} | |||
int | |||
setup_listener(struct servent *se) | |||
{ | |||
struct sockaddr_in sa_in; | |||
int fd; | |||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) | |||
fatal("socket"); | |||
bzero(&sa_in, sizeof(sa_in)); | |||
sa_in.sin_family = AF_INET; | |||
sa_in.sin_addr.s_addr = htonl(INADDR_ANY); | |||
sa_in.sin_port = se->s_port; | |||
if (bind(fd, (struct sockaddr *)&sa_in, sizeof(sa_in)) == -1) | |||
fatal("bind"); | |||
return (fd); | |||
} | |||
int | |||
ntp_dispatch_imsg(void) | |||
{ | |||
struct imsg imsg; | |||
int n; | |||
if ((n = imsg_read(&ibuf_main)) == -1) | |||
return (-1); | |||
if (n == 0) { /* connection closed */ | |||
log_warnx("ntp_dispatch_imsg in ntp engine: pipe closed"); | |||
return (-1); | |||
} | |||
for (;;) { | |||
if ((n = imsg_get(&ibuf_main, &imsg)) == -1) | |||
return (-1); | |||
if (n == 0) | |||
break; | |||
switch (imsg.hdr.type) { | |||
default: | |||
break; | |||
} | |||
imsg_free(&imsg); | |||
} | |||
return (0); | |||
} | |||
int | |||
ntp_dispatch(int fd) | |||
{ | |||
struct sockaddr fsa; | |||
socklen_t fsa_len; | |||
char buf[NTP_MSGSIZE]; | |||
ssize_t size; | |||
struct ntp_msg msg; | |||
fsa_len = sizeof(fsa); | |||
if ((size = recvfrom(fd, &buf, sizeof(buf), 0, &fsa, &fsa_len)) == -1) | |||
fatal("recvfrom"); | |||
parse_ntp_msg(buf, size, &msg); | |||
ntp_reply(fd, &fsa, &msg, 0); | |||
return (0); | |||
} | |||
int | |||
parse_ntp_msg(char *p, ssize_t len, struct ntp_msg *msg) | |||
{ | |||
int auth, i; | |||
if (len == NTP_MSGSIZE) | |||
auth = 1; | |||
else if (len == NTP_MSGSIZE_NOAUTH) | |||
auth = 0; | |||
else { | |||
log_warnx("malformed packet received"); | |||
return (-1); | |||
} | |||
memcpy(&msg->status, p, sizeof(msg->status)); | |||
p += sizeof(msg->status); | |||
memcpy(&msg->stratum, p, sizeof(msg->stratum)); | |||
p += sizeof(msg->stratum); | |||
memcpy(&msg->ppoll, p, sizeof(msg->ppoll)); | |||
p += sizeof(msg->ppoll); | |||
memcpy(&msg->precision, p, sizeof(msg->precision)); | |||
p += sizeof(msg->precision); | |||
memcpy(&msg->distance.int_part, p, sizeof(msg->distance.int_part)); | |||
p += sizeof(msg->distance.int_part); | |||
memcpy(&msg->distance.fraction, p, sizeof(msg->distance.fraction)); | |||
p += sizeof(msg->distance.fraction); | |||
memcpy(&msg->dispersion.int_part, p, sizeof(msg->dispersion.int_part)); | |||
p += sizeof(msg->dispersion.int_part); | |||
memcpy(&msg->dispersion.fraction, p, sizeof(msg->dispersion.fraction)); | |||
p += sizeof(msg->dispersion.fraction); | |||
memcpy(&msg->refid, p, sizeof(msg->refid)); | |||
p += sizeof(msg->refid); | |||
memcpy(&msg->reftime.int_part, p, sizeof(msg->reftime.int_part)); | |||
p += sizeof(msg->reftime.int_part); | |||
memcpy(&msg->reftime.fraction, p, sizeof(msg->reftime.fraction)); | |||
p += sizeof(msg->reftime.fraction); | |||
memcpy(&msg->orgtime.int_part, p, sizeof(msg->orgtime.int_part)); | |||
p += sizeof(msg->orgtime.int_part); | |||
memcpy(&msg->orgtime.fraction, p, sizeof(msg->orgtime.fraction)); | |||
p += sizeof(msg->orgtime.fraction); | |||
memcpy(&msg->rectime.int_part, p, sizeof(msg->rectime.int_part)); | |||
p += sizeof(msg->rectime.int_part); | |||
memcpy(&msg->rectime.fraction, p, sizeof(msg->rectime.fraction)); | |||
p += sizeof(msg->rectime.fraction); | |||
memcpy(&msg->xmttime.int_part, p, sizeof(msg->xmttime.int_part)); | |||
p += sizeof(msg->xmttime.int_part); | |||
memcpy(&msg->xmttime.fraction, p, sizeof(msg->xmttime.fraction)); | |||
p += sizeof(msg->xmttime.fraction); | |||
if (auth) { | |||
memcpy(&msg->keyid, p, sizeof(msg->keyid)); | |||
p += sizeof(msg->refid); | |||
for (i = 0; i < NTP_DIGESTSIZE; i++) { | |||
memcpy(&msg->digest[i], p, sizeof(msg->digest[i])); | |||
p += sizeof(msg->digest[i]); | |||
} | |||
/* XXX check auth */ | |||
} | |||
return (0); | |||
} | |||
int | |||
ntp_reply(int fd, struct sockaddr *sa, struct ntp_msg *query, int auth) | |||
{ | |||
ssize_t len; | |||
struct l_fixedpt t; | |||
struct ntp_msg reply; | |||
if (auth) | |||
len = NTP_MSGSIZE; | |||
else | |||
len = NTP_MSGSIZE_NOAUTH; | |||
bzero(&reply, sizeof(reply)); | |||
reply.status = 0 | (query->status & VERSIONMASK); | |||
if ((query->status & MODEMASK) == MODE_CLIENT) | |||
reply.status |= MODE_SERVER; | |||
else | |||
reply.status |= MODE_SYM_PAS; | |||
reply.stratum = 2; | |||
reply.ppoll = query->ppoll; | |||
reply.precision = 0; /* XXX */ | |||
reply.refid = htonl(t.fraction); /* XXX */ | |||
reply.reftime.int_part = htonl(ref_ts.int_part); | |||
reply.reftime.fraction = htonl(ref_ts.fraction); | |||
get_ts(&t); | |||
reply.rectime.int_part = htonl(t.int_part); | |||
reply.rectime.fraction = htonl(t.fraction); | |||
reply.xmttime.int_part = htonl(t.int_part); | |||
reply.xmttime.fraction = htonl(t.fraction); | |||
reply.orgtime.int_part = query->xmttime.int_part; | |||
reply.orgtime.fraction = query->xmttime.fraction; | |||
return (ntp_send(fd, sa, &reply, len, auth)); | |||
} | |||
int | |||
ntp_send(int fd, struct sockaddr *sa, struct ntp_msg *reply, ssize_t len, | |||
int auth) | |||
{ | |||
char buf[NTP_MSGSIZE]; | |||
char *p; | |||
p = buf; | |||
memcpy(p, &reply->status, sizeof(reply->status)); | |||
p += sizeof(reply->status); | |||
memcpy(p, &reply->stratum, sizeof(reply->stratum)); | |||
p += sizeof(reply->stratum); | |||
memcpy(p, &reply->ppoll, sizeof(reply->ppoll)); | |||
p += sizeof(reply->ppoll); | |||
memcpy(p, &reply->precision, sizeof(reply->precision)); | |||
p += sizeof(reply->precision); | |||
memcpy(p, &reply->distance.int_part, sizeof(reply->distance.int_part)); | |||
p += sizeof(reply->distance.int_part); | |||
memcpy(p, &reply->distance.fraction, sizeof(reply->distance.fraction)); | |||
p += sizeof(reply->distance.fraction); | |||
memcpy(p, &reply->dispersion.int_part, | |||
sizeof(reply->dispersion.int_part)); | |||
p += sizeof(reply->dispersion.int_part); | |||
memcpy(p, &reply->dispersion.fraction, | |||
sizeof(reply->dispersion.fraction)); | |||
p += sizeof(reply->dispersion.fraction); | |||
memcpy(p, &reply->refid, sizeof(reply->refid)); | |||
p += sizeof(reply->refid); | |||
memcpy(p, &reply->reftime.int_part, sizeof(reply->reftime.int_part)); | |||
p += sizeof(reply->reftime.int_part); | |||
memcpy(p, &reply->reftime.fraction, sizeof(reply->reftime.fraction)); | |||
p += sizeof(reply->reftime.fraction); | |||
memcpy(p, &reply->orgtime.int_part, sizeof(reply->orgtime.int_part)); | |||
p += sizeof(reply->orgtime.int_part); | |||
memcpy(p, &reply->orgtime.fraction, sizeof(reply->orgtime.fraction)); | |||
p += sizeof(reply->orgtime.fraction); | |||
memcpy(p, &reply->rectime.int_part, sizeof(reply->rectime.int_part)); | |||
p += sizeof(reply->rectime.int_part); | |||
memcpy(p, &reply->rectime.fraction, sizeof(reply->rectime.fraction)); | |||
p += sizeof(reply->rectime.fraction); | |||
memcpy(p, &reply->xmttime.int_part, sizeof(reply->xmttime.int_part)); | |||
p += sizeof(reply->xmttime.int_part); | |||
memcpy(p, &reply->xmttime.fraction, sizeof(reply->xmttime.fraction)); | |||
p += sizeof(reply->xmttime.fraction); | |||
if (auth) { | |||
/* XXX */ | |||
} | |||
if (sendto(fd, &buf, len, 0, sa, sa->sa_len) != len) | |||
fatal("sendto"); | |||
return (0); | |||
} | |||
void | |||
get_ts(struct l_fixedpt *t) | |||
{ | |||
struct timeval tv; | |||
gettimeofday(&tv, NULL); | |||
t->int_part = tv.tv_sec + JAN_1970; | |||
t->fraction = ((float)tv.tv_usec)/1000000 * UINT_MAX; | |||
} |
@ -0,0 +1,134 @@ | |||
/* | |||
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org> | |||
* Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org> | |||
* | |||
* 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. | |||
*/ | |||
/* Style borrowed from NTP ref/tcpdump and updated for SNTPv4 (RFC2030). */ | |||
/* | |||
* RFC Section 3 | |||
* | |||
* 0 1 2 3 | |||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | Integer Part | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | Fraction Part | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | |||
* 0 1 2 3 | |||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | Integer Part | Fraction Part | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
*/ | |||
struct l_fixedpt { | |||
u_int32_t int_part; | |||
u_int32_t fraction; | |||
}; | |||
struct s_fixedpt { | |||
u_int16_t int_part; | |||
u_int16_t fraction; | |||
}; | |||
/* RFC Section 4 | |||
* | |||
* 0 1 2 3 | |||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* |LI | VN | Mode| Stratum | Poll | Precision | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | Synchronizing Distance | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | Synchronizing Dispersion | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | Reference Clock Identifier | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | | | |||
* | Reference Timestamp (64 bits) | | |||
* | | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | | | |||
* | Originate Timestamp (64 bits) | | |||
* | | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | | | |||
* | Receive Timestamp (64 bits) | | |||
* | | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | | | |||
* | Transmit Timestamp (64 bits) | | |||
* | | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | Key Identifier (optional) (32) | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | | | |||
* | | | |||
* | Message Digest (optional) (128) | | |||
* | | | |||
* | | | |||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
* | |||
*/ | |||
#define NTP_DIGESTSIZE 16 | |||
#define NTP_MSGSIZE_NOAUTH 48 | |||
#define NTP_MSGSIZE (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE) | |||
struct ntp_msg { | |||
u_int8_t status; /* status of local clock and leap info */ | |||
u_int8_t stratum; /* Stratum level */ | |||
u_int8_t ppoll; /* poll value */ | |||
int8_t precision; | |||
struct s_fixedpt distance; | |||
struct s_fixedpt dispersion; | |||
u_int32_t refid; | |||
struct l_fixedpt reftime; | |||
struct l_fixedpt orgtime; | |||
struct l_fixedpt rectime; | |||
struct l_fixedpt xmttime; | |||
u_int32_t keyid; | |||
u_int8_t digest[NTP_DIGESTSIZE]; | |||
}; | |||
/* | |||
* Leap Second Codes (high order two bits) | |||
*/ | |||
#define LI_NOWARNING (0 << 6) /* no warning */ | |||
#define LI_PLUSSEC (1 << 6) /* add a second (61 seconds) */ | |||
#define LI_MINUSSEC (2 << 6) /* minus a second (59 seconds) */ | |||
#define LI_ALARM (3 << 6) /* alarm condition */ | |||
/* | |||
* Status Masks | |||
*/ | |||
#define MODEMASK (7 << 0) | |||
#define VERSIONMASK (7 << 3) | |||
#define LIMASK (2 << 6) | |||
/* | |||
* Mode values | |||
*/ | |||
#define MODE_RES0 0 /* reserved */ | |||
#define MODE_SYM_ACT 1 /* symmetric active */ | |||
#define MODE_SYM_PAS 2 /* symmetric passive */ | |||
#define MODE_CLIENT 3 /* client */ | |||
#define MODE_SERVER 4 /* server */ | |||
#define MODE_BROADCAST 5 /* broadcast */ | |||
#define MODE_RES1 6 /* reserved for NTP control message */ | |||
#define MODE_RES2 7 /* reserved for private use */ | |||
#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */ |
@ -0,0 +1,245 @@ | |||
/* $OpenBSD: ntpd.c,v 1.1 2004/05/31 13:46:16 henning Exp $ */ | |||
/* | |||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> | |||
* | |||
* 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. | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/socket.h> | |||
#include <sys/wait.h> | |||
#include <netinet/in.h> | |||
#include <arpa/inet.h> | |||
#include <err.h> | |||
#include <errno.h> | |||
#include <fcntl.h> | |||
#include <poll.h> | |||
#include <pwd.h> | |||
#include <signal.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include "ntpd.h" | |||
void sighdlr(int); | |||
void usage(void); | |||
int main(int, char *[]); | |||
int check_child(pid_t, const char *); | |||
int reconfigure(char *); | |||
int dispatch_imsg(void); | |||
int rfd = -1; | |||
volatile sig_atomic_t quit = 0; | |||
volatile sig_atomic_t reconfig = 0; | |||
volatile sig_atomic_t sigchld = 0; | |||
struct imsgbuf ibuf; | |||
void | |||
sighdlr(int sig) | |||
{ | |||
switch (sig) { | |||
case SIGTERM: | |||
case SIGINT: | |||
quit = 1; | |||
break; | |||
case SIGCHLD: | |||
sigchld = 1; | |||
break; | |||
case SIGHUP: | |||
reconfig = 1; | |||
break; | |||
} | |||
} | |||
void | |||
usage(void) | |||
{ | |||
extern char *__progname; | |||
fprintf(stderr, "usage: %s [-d] [-f file]", __progname); | |||
exit(1); | |||
} | |||
#define POLL_MAX 8 | |||
#define PFD_PIPE 0 | |||
int | |||
main(int argc, char *argv[]) | |||
{ | |||
struct pollfd pfd[POLL_MAX]; | |||
pid_t chld_pid = 0, pid; | |||
char *conffile; | |||
int debug = 0; | |||
int ch, nfds; | |||
int pipe_chld[2]; | |||
conffile = CONFFILE; | |||
log_init(1); /* log to stderr until daemonized */ | |||
while ((ch = getopt(argc, argv, "df:")) != -1) { | |||
switch (ch) { | |||
case 'd': | |||
debug = 1; | |||
break; | |||
case 'f': | |||
conffile = optarg; | |||
break; | |||
default: | |||
usage(); | |||
/* NOTREACHED */ | |||
} | |||
} | |||
if (geteuid()) | |||
errx(1, "need root privileges"); | |||
if (getpwnam(NTPD_USER) == NULL) | |||
errx(1, "unknown user %s", NTPD_USER); | |||
endpwent(); | |||
log_init(debug); | |||
if (!debug) | |||
daemon(1, 0); | |||
log_info("startup"); | |||
if (pipe(pipe_chld) == -1) | |||
fatal("pipe"); | |||
/* fork children */ | |||
chld_pid = ntp_main(pipe_chld); | |||
setproctitle("[priv]"); | |||
signal(SIGTERM, sighdlr); | |||
signal(SIGINT, sighdlr); | |||
signal(SIGCHLD, sighdlr); | |||
signal(SIGHUP, sighdlr); | |||
close(pipe_chld[1]); | |||
imsg_init(&ibuf, pipe_chld[0]); | |||
while (quit == 0) { | |||
pfd[PFD_PIPE].fd = ibuf.fd; | |||
pfd[PFD_PIPE].events = POLLIN; | |||
if (ibuf.w.queued) | |||
pfd[PFD_PIPE].events |= POLLOUT; | |||
if ((nfds = poll(pfd, 1, INFTIM)) == -1) | |||
if (errno != EINTR) { | |||
log_warn("poll error"); | |||
quit = 1; | |||
} | |||
if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT)) | |||
if (msgbuf_write(&ibuf.w) < 0) { | |||
log_warn("pipe write error (to child"); | |||
quit = 1; | |||
} | |||
if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) { | |||
nfds--; | |||
if (dispatch_imsg() == -1) | |||
quit = 1; | |||
} | |||
if (reconfig) { | |||
log_info("rereading config"); | |||
reconfigure(conffile); | |||
reconfig = 0; | |||
} | |||
if (sigchld) { | |||
if (check_child(chld_pid, "child")) | |||
quit = 1; | |||
sigchld = 0; | |||
} | |||
} | |||
signal(SIGCHLD, SIG_IGN); | |||
if (chld_pid) | |||
kill(chld_pid, SIGTERM); | |||
do { | |||
if ((pid = wait(NULL)) == -1 && | |||
errno != EINTR && errno != ECHILD) | |||
fatal("wait"); | |||
} while (pid != -1 || (pid == -1 && errno == EINTR)); | |||
log_info("Terminating"); | |||
return (0); | |||
} | |||
int | |||
check_child(pid_t pid, const char *pname) | |||
{ | |||
int status; | |||
if (waitpid(pid, &status, WNOHANG) > 0) { | |||
if (WIFEXITED(status)) { | |||
log_warnx("Lost child: %s exited", pname); | |||
return (1); | |||
} | |||
if (WIFSIGNALED(status)) { | |||
log_warnx("Lost child: %s terminated; signal %d", | |||
pname, WTERMSIG(status)); | |||
return (1); | |||
} | |||
} | |||
return (0); | |||
} | |||
int | |||
reconfigure(char *conffile) | |||
{ | |||
return (-1); | |||
} | |||
int | |||
dispatch_imsg(void) | |||
{ | |||
struct imsg imsg; | |||
int n; | |||
if ((n = imsg_read(&ibuf)) == -1) | |||
return (-1); | |||
if (n == 0) { /* connection closed */ | |||
log_warnx("dispatch_imsg in main: pipe closed"); | |||
return (-1); | |||
} | |||
for (;;) { | |||
if ((n = imsg_get(&ibuf, &imsg)) == -1) | |||
return (-1); | |||
if (n == 0) | |||
break; | |||
switch (imsg.hdr.type) { | |||
default: | |||
break; | |||
} | |||
imsg_free(&imsg); | |||
} | |||
return (0); | |||
} |
@ -0,0 +1,112 @@ | |||
/* $OpenBSD: ntpd.h,v 1.1 2004/05/31 13:46:16 henning Exp $ */ | |||
/* | |||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> | |||
* | |||
* 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. | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/socket.h> | |||
#include <sys/queue.h> | |||
#include <netinet/in.h> | |||
#include <arpa/inet.h> | |||
#include <stdarg.h> | |||
#define NTPD_USER "_ntp" | |||
#define CONFFILE "/etc/ntpd.conf" | |||
#define READ_BUF_SIZE 65535 | |||
struct buf { | |||
TAILQ_ENTRY(buf) entries; | |||
u_char *buf; | |||
ssize_t size; | |||
ssize_t wpos; | |||
ssize_t rpos; | |||
}; | |||
struct msgbuf { | |||
u_int32_t queued; | |||
int fd; | |||
TAILQ_HEAD(bufs, buf) bufs; | |||
}; | |||
struct buf_read { | |||
u_char buf[READ_BUF_SIZE]; | |||
u_char *rptr; | |||
ssize_t wpos; | |||
}; | |||
/* ipc messages */ | |||
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) | |||
#define MAX_IMSGSIZE 8192 | |||
struct imsgbuf { | |||
int fd; | |||
pid_t pid; | |||
struct buf_read r; | |||
struct msgbuf w; | |||
}; | |||
enum imsg_type { | |||
IMSG_NONE | |||
}; | |||
struct imsg_hdr { | |||
enum imsg_type type; | |||
u_int16_t len; | |||
u_int32_t peerid; | |||
pid_t pid; | |||
}; | |||
struct imsg { | |||
struct imsg_hdr hdr; | |||
void *data; | |||
}; | |||
/* prototypes */ | |||
/* log.c */ | |||
void log_init(int); | |||
void vlog(int, const char *, va_list); | |||
void log_warn(const char *, ...); | |||
void log_warnx(const char *, ...); | |||
void log_info(const char *, ...); | |||
void log_debug(const char *, ...); | |||
void fatal(const char *); | |||
void fatalx(const char *); | |||
/* buffer.c */ | |||
struct buf *buf_open(ssize_t); | |||
int buf_add(struct buf *, void *, ssize_t); | |||
int buf_close(struct msgbuf *, struct buf *); | |||
void buf_free(struct buf *); | |||
void msgbuf_init(struct msgbuf *); | |||
void msgbuf_clear(struct msgbuf *); | |||
int msgbuf_write(struct msgbuf *); | |||
/* imsg.c */ | |||
void imsg_init(struct imsgbuf *, int); | |||
int imsg_read(struct imsgbuf *); | |||
int imsg_get(struct imsgbuf *, struct imsg *); | |||
int imsg_compose(struct imsgbuf *, int, u_int32_t, void *, u_int16_t); | |||
int imsg_compose_pid(struct imsgbuf *, int, pid_t, void *, u_int16_t); | |||
struct buf *imsg_create(struct imsgbuf *, int, u_int32_t, u_int16_t); | |||
struct buf *imsg_create_pid(struct imsgbuf *, int, pid_t, u_int16_t); | |||
int imsg_add(struct buf *, void *, u_int16_t); | |||
int imsg_close(struct imsgbuf *, struct buf *); | |||
void imsg_free(struct imsg *); | |||
/* ntp.c */ | |||
pid_t ntp_main(int[2]); |