diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-06-17 19:17:49 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-06-17 19:17:49 +0000 |
commit | b4ad8c9613e23bfa3e8ee4bae1b99b115fd63661 (patch) | |
tree | e13c30549b43adad7446b7ccd3677e945b6cce7f | |
parent | f9e4cdc6e99bc859ee7e13773d3407643fe12f04 (diff) |
provide most of the client functionality.
hook the descriptors into the main poll and such.
we're not doing anything with the reply we recive yet, tho.
mostly hacked on the Frankfurt->Montreal flight, as batteries and those
horrible air canada seats permitted...
-rw-r--r-- | usr.sbin/ntpd/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/ntpd/client.c | 129 | ||||
-rw-r--r-- | usr.sbin/ntpd/ntp.c | 50 | ||||
-rw-r--r-- | usr.sbin/ntpd/ntp.h | 14 | ||||
-rw-r--r-- | usr.sbin/ntpd/ntpd.c | 3 | ||||
-rw-r--r-- | usr.sbin/ntpd/ntpd.h | 24 | ||||
-rw-r--r-- | usr.sbin/ntpd/parse.y | 32 |
7 files changed, 243 insertions, 13 deletions
diff --git a/usr.sbin/ntpd/Makefile b/usr.sbin/ntpd/Makefile index 96664576ced..0fedc671017 100644 --- a/usr.sbin/ntpd/Makefile +++ b/usr.sbin/ntpd/Makefile @@ -1,10 +1,10 @@ -# $OpenBSD: Makefile,v 1.4 2004/06/02 10:08:59 henning Exp $ +# $OpenBSD: Makefile,v 1.5 2004/06/17 19:17:48 henning Exp $ .PATH: ${.CURDIR}/.. PROG= ntpd SRCS= ntpd.c buffer.c log.c imsg.c ntp.c ntp_msg.c parse.y config.c \ - server.c + server.c client.c CFLAGS+= -Wall -I${.CURDIR} CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CFLAGS+= -Wmissing-declarations diff --git a/usr.sbin/ntpd/client.c b/usr.sbin/ntpd/client.c new file mode 100644 index 00000000000..c742d1d11fb --- /dev/null +++ b/usr.sbin/ntpd/client.c @@ -0,0 +1,129 @@ +/* $OpenBSD: client.c,v 1.1 2004/06/17 19:17:48 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 <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "ntpd.h" + +int +client_peer_init(struct ntp_peer *p) +{ + struct sockaddr_in *sa_in; + struct sockaddr_in6 *sa_in6; + + if ((p->query = calloc(1, sizeof(struct ntp_msg))) == NULL) + fatal("client_query calloc"); + + switch (p->ss.ss_family) { + case AF_INET: + sa_in = (struct sockaddr_in *)&p->ss; + if (ntohs(sa_in->sin_port) == 0) + sa_in->sin_port = htons(123); + break; + case AF_INET6: + sa_in6 = (struct sockaddr_in6 *)&p->ss; + if (ntohs(sa_in6->sin6_port) == 0) + sa_in6->sin6_port = htons(123); + break; + default: + fatal("king bula sez: wrong AF in client_peer_init"); + /* not reached */ + } + + if ((p->query->fd = socket(p->ss.ss_family, SOCK_DGRAM, 0)) == -1) + fatal("client_query socket"); + + p->query->msg.status = MODE_CLIENT | (NTP_VERSION << 3); + p->state = STATE_NONE; + p->next = time(NULL); + + return (0); +} + +int +client_query(struct ntp_peer *p) +{ + /* + * Send out a random 64-bit number as our transmit time. The NTP + * server will copy said number into the originate field on the + * response that it sends us. This is totally legal per the SNTP spec. + * + * The impact of this is two fold: we no longer send out the current + * system time for the world to see (which may aid an attacker), and + * it gives us a (not very secure) way of knowing that we're not + * getting spoofed by an attacker that can't capture our traffic + * but can spoof packets from the NTP server we're communicating with. + * + * Save the real transmit timestamp locally. + */ + + p->query->msg.xmttime.int_part = arc4random(); + p->query->msg.xmttime.fraction = arc4random(); + get_ts(&p->query->xmttime); + + ntp_sendmsg(p->query->fd, (struct sockaddr *)&p->ss, &p->query->msg, + NTP_MSGSIZE_NOAUTH, 0); + p->state = STATE_QUERY_SENT; + p->next = 0; + p->deadline = time(NULL) + MAX_QUERYTIME; + + return (0); +} + +int +client_dispatch(struct ntp_peer *p) +{ + struct sockaddr_storage fsa; + socklen_t fsa_len; + char buf[NTP_MSGSIZE]; + ssize_t size; + struct ntp_msg msg; + struct l_fixedpt rtt, t; + + fsa_len = sizeof(fsa); + if ((size = recvfrom(p->query->fd, &buf, sizeof(buf), 0, + (struct sockaddr *)&fsa, &fsa_len)) == -1) + fatal("recvfrom"); + + ntp_getmsg(buf, size, &msg); + + if (msg.orgtime.int_part != p->query->msg.xmttime.int_part || + msg.orgtime.fraction != p->query->msg.xmttime.fraction) { + log_warn("received packet without correct cookie, discarding"); + return (0); + } + +log_debug("reply received"); + + /* XXX parse */ + get_ts(&t); + rtt.int_part = (t.int_part - p->query->xmttime.int_part) - + (msg.rectime.int_part - msg.xmttime.int_part); + + p->state = STATE_REPLY_RECEIVED; + p->next = time(NULL) + QUERY_INTERVAL; + p->deadline = 0; + + return (0); +} diff --git a/usr.sbin/ntpd/ntp.c b/usr.sbin/ntpd/ntp.c index 55538d58efa..792337423d1 100644 --- a/usr.sbin/ntpd/ntp.c +++ b/usr.sbin/ntpd/ntp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.c,v 1.6 2004/06/02 10:08:59 henning Exp $ */ +/* $OpenBSD: ntp.c,v 1.7 2004/06/17 19:17:48 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -52,12 +52,15 @@ ntp_sighdlr(int sig) pid_t ntp_main(int pipe_prnt[2], struct ntpd_conf *conf) { - int nfds, i, j; + int nfds, i, j, idx_peers, timeout; pid_t pid; struct pollfd pfd[OPEN_MAX]; struct passwd *pw; struct servent *se; struct listen_addr *la; + struct ntp_peer *p; + struct ntp_peer *idx2peer[OPEN_MAX]; + time_t nextaction; switch (pid = fork()) { case -1: @@ -98,10 +101,15 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *conf) close(pipe_prnt[0]); imsg_init(&ibuf_main, pipe_prnt[1]); + TAILQ_FOREACH(p, &conf->ntp_peers, entry) + client_peer_init(p); + log_info("ntp engine ready"); while (ntp_quit == 0) { bzero(&pfd, sizeof(pfd)); + bzero(idx2peer, sizeof(idx2peer)); + nextaction = time(NULL) + 240; pfd[PFD_PIPE_MAIN].fd = ibuf_main.fd; pfd[PFD_PIPE_MAIN].events = POLLIN; if (ibuf_main.w.queued > 0) @@ -112,14 +120,38 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *conf) pfd[i].fd = la->fd; pfd[i].events = POLLIN; i++; + if (i > OPEN_MAX) + fatal("i > OPEN_MAX"); + } + + + idx_peers = i; + TAILQ_FOREACH(p, &conf->ntp_peers, entry) { + if (p->next > 0 && p->next < nextaction) + nextaction = p->next; + if ((p->next > 0 && p->next <= time(NULL)) || + (p->deadline > 0 && p->deadline <= time(NULL))) + client_query(p); + + if (p->state == STATE_QUERY_SENT) { + pfd[i].fd = p->query->fd; + pfd[i].events = POLLIN; + idx2peer[i - idx_peers] = p; + i++; + if (i > OPEN_MAX) + fatal("i > OPEN_MAX"); + } } - if ((nfds = poll(pfd, i, INFTIM)) == -1) + timeout = nextaction - time(NULL); + if (timeout < 0) + timeout = 0; + + if ((nfds = poll(pfd, i, timeout * 1000)) == -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)"); @@ -132,12 +164,20 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *conf) ntp_quit = 1; } - for (j = 1; nfds > 0 && j < i; j++) + for (j = 1; nfds > 0 && j < idx_peers; j++) if (pfd[j].revents & POLLIN) { nfds--; if (ntp_dispatch(pfd[j].fd) == -1) ntp_quit = 1; } + + for (; nfds > 0 && j < i; j++) + if (pfd[j].revents & POLLIN) { + nfds--; + if (client_dispatch(idx2peer[j - idx_peers]) == + -1) + ntp_quit = 1; + } } msgbuf_write(&ibuf_main.w); diff --git a/usr.sbin/ntpd/ntp.h b/usr.sbin/ntpd/ntp.h index 461de9d8ead..8a63c006904 100644 --- a/usr.sbin/ntpd/ntp.h +++ b/usr.sbin/ntpd/ntp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.h,v 1.4 2004/06/05 12:29:15 alexander Exp $ */ +/* $OpenBSD: ntp.h,v 1.5 2004/06/17 19:17:48 henning Exp $ */ /* * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> @@ -109,6 +109,12 @@ struct ntp_msg { u_int8_t digest[NTP_DIGESTSIZE]; }; +struct ntp_query { + int fd; + struct ntp_msg msg; + struct l_fixedpt xmttime; +}; + /* * Leap Second Codes (high order two bits) */ @@ -138,4 +144,8 @@ struct ntp_msg { #define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */ -#endif /* _NTP_H_ */ +#define NTP_VERSION 4 +#define MAX_QUERYTIME 30 /* max seconds a single query might take */ +#define QUERY_INTERVAL 60 /* sync with peers every n seconds */ + +#endif /* _NTP_H_ */ diff --git a/usr.sbin/ntpd/ntpd.c b/usr.sbin/ntpd/ntpd.c index a60cb153adc..7d6eadac1d9 100644 --- a/usr.sbin/ntpd/ntpd.c +++ b/usr.sbin/ntpd/ntpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.c,v 1.4 2004/06/01 21:58:08 henning Exp $ */ +/* $OpenBSD: ntpd.c,v 1.5 2004/06/17 19:17:48 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -91,6 +91,7 @@ main(int argc, char *argv[]) bzero(&conf, sizeof(conf)); TAILQ_INIT(&conf.listen_addrs); + TAILQ_INIT(&conf.ntp_peers); log_init(1); /* log to stderr until daemonized */ diff --git a/usr.sbin/ntpd/ntpd.h b/usr.sbin/ntpd/ntpd.h index 44e75c1f25f..71d309cb8b8 100644 --- a/usr.sbin/ntpd/ntpd.h +++ b/usr.sbin/ntpd/ntpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.h,v 1.5 2004/06/05 12:29:15 alexander Exp $ */ +/* $OpenBSD: ntpd.h,v 1.6 2004/06/17 19:17:48 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -34,14 +34,30 @@ #define NTPD_OPT_VERBOSE 0x0001 #define NTPD_OPT_VERBOSE2 0x0002 +enum client_state { + STATE_NONE, + STATE_QUERY_SENT, + STATE_REPLY_RECEIVED +}; + struct listen_addr { TAILQ_ENTRY(listen_addr) entry; struct sockaddr_storage sa; int fd; }; +struct ntp_peer { + TAILQ_ENTRY(ntp_peer) entry; + struct sockaddr_storage ss; + struct ntp_query *query; + enum client_state state; + time_t next; + time_t deadline; +}; + struct ntpd_conf { TAILQ_HEAD(listen_addrs, listen_addr) listen_addrs; + TAILQ_HEAD(ntp_peers, ntp_peer) ntp_peers; u_int8_t opts; }; @@ -103,6 +119,7 @@ void log_info(const char *, ...); void log_debug(const char *, ...); void fatal(const char *); void fatalx(const char *); +const char * log_sockaddr(struct sockaddr *); /* buffer.c */ struct buf *buf_open(ssize_t); @@ -144,3 +161,8 @@ int ntp_sendmsg(int, struct sockaddr *, struct ntp_msg *, ssize_t, int); /* server.c */ int setup_listeners(struct servent *, struct ntpd_conf *); int ntp_reply(int, struct sockaddr *, struct ntp_msg *, int); + +/* client.c */ +int client_peer_init(struct ntp_peer *); +int client_query(struct ntp_peer *); +int client_dispatch(struct ntp_peer *); diff --git a/usr.sbin/ntpd/parse.y b/usr.sbin/ntpd/parse.y index 18e3ab37ab9..da13af04bab 100644 --- a/usr.sbin/ntpd/parse.y +++ b/usr.sbin/ntpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.1 2004/06/01 21:58:09 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.2 2004/06/17 19:17:48 henning Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -77,6 +77,7 @@ typedef struct { %} %token LISTEN ON +%token SERVER %token ERROR %token <v.string> STRING %type <v.number> number @@ -130,9 +131,23 @@ conf_main : LISTEN ON address { NULL) fatal("parse conf_main listen on calloc"); + la->fd = -1; memcpy(&la->sa, &$3, sizeof(struct sockaddr_storage)); TAILQ_INSERT_TAIL(&conf->listen_addrs, la, entry); } + | SERVER address { + struct ntp_peer *p; + + if (!TAILQ_EMPTY(&conf->ntp_peers)) { + yyerror("king bula sez: only on remote server " + "supported for now"); + YYERROR; + } + if ((p = calloc(1, sizeof(struct listen_addr))) == NULL) + fatal("parse conf_mail server on calloc"); + memcpy(&p->ss, &$2, sizeof(struct sockaddr_storage)); + TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry); + } ; address : STRING { @@ -192,7 +207,8 @@ lookup(char *s) /* this has to be sorted always */ static const struct keywords keywords[] = { { "listen", LISTEN}, - { "on", ON} + { "on", ON}, + { "server", SERVER} }; const struct keywords *p; @@ -402,12 +418,14 @@ parse_config(char *filename, struct ntpd_conf *xconf) { struct sym *sym, *next; struct listen_addr *la; + struct ntp_peer *p; if ((conf = calloc(1, sizeof(struct ntpd_conf))) == NULL) fatal(NULL); lineno = 1; errors = 0; TAILQ_INIT(&conf->listen_addrs); + TAILQ_INIT(&conf->ntp_peers); if ((fin = fopen(filename, "r")) == NULL) { log_warn("%s", filename); @@ -444,6 +462,16 @@ parse_config(char *filename, struct ntpd_conf *xconf) TAILQ_INSERT_TAIL(&xconf->listen_addrs, la, entry); } + while ((p = TAILQ_FIRST(&xconf->ntp_peers)) != NULL) { + TAILQ_REMOVE(&xconf->ntp_peers, p, entry); + free(p); + } + + while ((p = TAILQ_FIRST(&conf->ntp_peers)) != NULL) { + TAILQ_REMOVE(&conf->ntp_peers, p, entry); + TAILQ_INSERT_TAIL(&xconf->ntp_peers, p, entry); + } + free(conf); return (errors ? -1 : 0); |