[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
leap second support for (portable) OpenNTPD
- To: misc_(_at_)_openbsd_(_dot_)_org
- Subject: leap second support for (portable) OpenNTPD
- From: Thorsten Glaser <tg_(_at_)_mirbsd_(_dot_)_de>
- Date: Tue, 9 May 2006 09:44:06 +0000 (UTC)
Hello people,
I have adapted my leap second patch (which has been part of
OpenBSD's base system's rdate(8) for years) to (portable)
OpenNTPD and attached it below.
A patch against OpenBSD ntpd(8) has been sent to henning@
some time ago already.
The patch does not modify default behaviour - instead, like
with rdate, you have to specify the -c option if you are
running a "right" timezone (as in contrast to a "posix" one).
bye,
//mirabile
PS: Please direct replies to me too, I don't read misc@ any more.
--
> emacs als auch vi zum Kotzen finde (joe rules) und pine f|r den einzig
> bedienbaren textmode-mailclient halte (und ich hab sie alle ausprobiert). ;)
Hallooooo, ich bin der Holger ("Hallo Holger!"), und ich bin ebenfalls
... pine-User, und das auch noch gewohnheitsmd_ig ("Oooooooohhh"). [aus dasr]
===== cutting here may damage your screen surface =====
$MirBSD: Web/pub/openntpd-3.7p1-leapsecs.diff,v 1.1 2006/05/09 09:18:06 tg Exp $
diff -pruN openntpd-3.7p1.orig/LICENCE openntpd-3.7p1/LICENCE
--- openntpd-3.7p1.orig/LICENCE Sun Mar 13 13:02:56 2005
+++ openntpd-3.7p1/LICENCE Tue May 9 09:10:26 2006
@@ -111,4 +111,8 @@ daemon.c, sys-queue.h: The Regents of th
* SUCH DAMAGE.
*/
+The leap second support is an extension by Thorsten Glaser and
+is covered by the MirOS licence, but available under the ISC
+licence for use by the OpenBSD project in rdate(8) as well.
+
$Id: openntpd-3.7p1-leapsecs.diff,v 1.1 2006/05/09 09:18:06 tg Exp $
diff -pruN openntpd-3.7p1.orig/Makefile.in openntpd-3.7p1/Makefile.in
--- openntpd-3.7p1.orig/Makefile.in Wed Dec 15 01:59:53 2004
+++ openntpd-3.7p1/Makefile.in Tue May 9 09:09:19 2006
@@ -30,9 +30,9 @@ STRIP_OPT=_(_at_)_STRIP_OPT@
PROG= ntpd
LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
SRCS= ntpd.c buffer.c log.c imsg.c ntp.c ntp_msg.c config.c \
- server.c client.c util.c y.tab.c
+ server.c client.c util.c y.tab.c ntpleaps.c
OBJS= ntpd.o buffer.o log.o imsg.o ntp.o ntp_msg.o config.o \
- server.o client.o util.o y.tab.o
+ server.o client.o util.o y.tab.o ntpleaps.o
YFLAGS=
MAN= ntpd.8 ntpd.conf.5
@@ -45,7 +45,7 @@ $(LIBCOMPAT): config.h $(top_srcdir)/op
$(OBJS): config.h
ntpd: ntpd.o buffer.o log.o imsg.o ntp.o ntp_msg.o config.o \
- server.o client.o util.o y.tab.o $(LIBCOMPAT)
+ server.o client.o util.o y.tab.o ntpleaps.o $(LIBCOMPAT)
$(CC) $(CFLAGS) $(LDFLAGS) -o ntpd $(OBJS) $(LIBCOMPAT) $(LIBS)
.c.o:
diff -pruN openntpd-3.7p1.orig/contrib/redhat/openntpd.spec openntpd-3.7p1/contrib/redhat/openntpd.spec
--- openntpd-3.7p1.orig/contrib/redhat/openntpd.spec Mon May 23 00:22:17 2005
+++ openntpd-3.7p1/contrib/redhat/openntpd.spec Tue May 9 09:15:21 2006
@@ -13,7 +13,8 @@ Requires: /sbin/chkconfig
#Patch1: openntpd-3.6p1-linux-adjtimex3.patch
%description
-NTP Time Synchronization Client - http://www.openntpd.org
+NTP Time Synchronisation Client - http://www.openntpd.org
+Enhanced by correct leap second support facility by MirOS
%prep
%setup -q -n %{name}-%{version}
diff -pruN openntpd-3.7p1.orig/ntpd.8 openntpd-3.7p1/ntpd.8
--- openntpd-3.7p1.orig/ntpd.8 Tue Dec 14 01:20:13 2004
+++ openntpd-3.7p1/ntpd.8 Tue May 9 09:08:29 2006
@@ -23,7 +23,7 @@
.Sh SYNOPSIS
.Nm ntpd
.Bk -words
-.Op Fl dSs
+.Op Fl cdSs
.Op Fl f Ar file
.Ek
.Sh DESCRIPTION
@@ -61,6 +61,12 @@ typically
.Pp
The options are as follows:
.Bl -tag -width "-f fileXXX"
+.It Fl c
+Correct leap seconds.
+Use this option if you are using one of the time zones from
+.Pa /usr/share/zoneinfo/right/
+(i\.e\. you are counting leap seconds in the kernel time,
+instead of following POSIX closely which denies their existence).
.It Fl d
Do not daemonize.
If this option is specified,
diff -pruN openntpd-3.7p1.orig/ntpd.c openntpd-3.7p1/ntpd.c
--- openntpd-3.7p1.orig/ntpd.c Sun Mar 13 12:41:24 2005
+++ openntpd-3.7p1/ntpd.c Tue May 9 09:08:29 2006
@@ -39,6 +39,7 @@ RCSID("$Release: OpenNTPD "OPENNTPD_VERS
#include <unistd.h>
#include "ntpd.h"
+#include "ntpleaps.h"
void sighdlr(int);
__dead void usage(void);
@@ -52,6 +53,7 @@ volatile sig_atomic_t quit = 0;
volatile sig_atomic_t reconfig = 0;
volatile sig_atomic_t sigchld = 0;
struct imsgbuf *ibuf;
+int corrleaps = 0;
void
sighdlr(int sig)
@@ -102,8 +104,11 @@ main(int argc, char *argv[])
log_init(1); /* log to stderr until daemonized */
res_init(); /* XXX */
- while ((ch = getopt(argc, argv, "df:sS")) != -1) {
+ while ((ch = getopt(argc, argv, "cdf:sS")) != -1) {
switch (ch) {
+ case 'c':
+ corrleaps = 1;
+ break;
case 'd':
conf.debug = 1;
break;
@@ -121,6 +126,9 @@ main(int argc, char *argv[])
/* NOTREACHED */
}
}
+
+ if (corrleaps)
+ ntpleaps_init();
if (parse_config(conffile, &conf))
exit(1);
diff -pruN openntpd-3.7p1.orig/ntpleaps.c openntpd-3.7p1/ntpleaps.c
--- openntpd-3.7p1.orig/ntpleaps.c Thu Jan 1 00:00:00 1970
+++ openntpd-3.7p1/ntpleaps.c Tue May 9 09:08:29 2006
@@ -0,0 +1,200 @@
+/* $OpenBSD: ntpleaps.c,v 1.7 2004/05/05 20:29:54 jakob Exp $ */
+
+/*
+ * Copyright (c) 2002, 2005, 2006 Thorsten Glaser. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Leap second support for NTP clients (generic) */
+
+/*
+ * I could include tzfile.h, but this would make the code unportable
+ * at no real benefit. Read tzfile.h for why.
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ntpleaps.h"
+
+#ifndef __RCSID
+#define __RCSID(x) static const char __rcsid[] __attribute__((used)) = (x)
+#endif
+
+__RCSID("$MirOS: src/usr.sbin/rdate/ntpleaps.c,v 1.4 2006/05/09 09:00:00 tg Exp $");
+
+#ifndef O_NDELAY
+#define O_NDELAY 0
+#endif
+
+u_int64_t *leapsecs = NULL;
+unsigned int leapsecs_num = 0;
+static int flaginit = -1;
+static int flagwarn = 0;
+
+static u_int32_t read_be_dword(u_int8_t *);
+
+int
+ntpleaps_init(void)
+{
+ if (!flaginit)
+ return (0);
+
+ if (!ntpleaps_read()) {
+ flaginit = 0;
+ return (0);
+ }
+
+ /* This does not really hurt, but users will complain about
+ * off-by-23-seconds (at time of coding) errors if we don't warn.
+ */
+ if (!flagwarn) {
+ fputs("Warning: error reading tzfile. You will NOT be\n"
+ "able to get legal time or posix compliance! To fix this,\n"
+ "install the 240 byte /usr/share/zoneinfo/right/UTC file.\n",
+ stderr);
+ flagwarn = 1; /* put it only once */
+ }
+
+ return (-1);
+}
+
+int
+ntpleaps_sub(u_int64_t *t)
+{
+ u_int64_t u;
+ unsigned i = 0, r = 0;
+
+ if ((flaginit ? ntpleaps_init() : 0) == -1)
+ return (-1);
+
+ u = *t;
+ if (u > 0)
+ while ((i < leapsecs_num) && (*t >= leapsecs[i])) {
+ --u;
+ ++i;
+ if (*t == leapsecs[i])
+ r = 1;
+ }
+ *t = u;
+ return (r);
+}
+
+static u_int32_t
+read_be_dword(u_int8_t *ptr)
+{
+ u_int32_t res;
+
+ memcpy(&res, ptr, 4);
+ return (ntohl(res));
+}
+
+int
+ntpleaps_read(void)
+{
+ int fd;
+ unsigned int r;
+ u_int8_t buf[32];
+ u_int32_t m1, m2, m3;
+ u_int64_t s;
+ u_int64_t *l;
+
+ fd = open("/usr/share/zoneinfo/right/UTC", O_RDONLY | O_NDELAY);
+ if (fd == -1)
+ fd = open("/usr/share/zoneinfo/UTC", O_RDONLY | O_NDELAY);
+ if (fd == -1)
+ return (-1);
+
+ /* Check signature */
+ read(fd, buf, 4);
+ buf[4] = 0;
+ if (strcmp((const char *)buf, "TZif")) {
+ close(fd);
+ return (-1);
+ }
+
+ /* Pre-initalise buf[24..27] so we need not check read(2) result */
+ buf[24] = 0;
+ buf[25] = 0;
+ buf[26] = 0;
+ buf[27] = 0;
+
+ /* Skip uninteresting parts of header */
+ read(fd, buf, 28);
+
+ /* Read number of leap second entries */
+ r = read_be_dword(&buf[24]);
+ /* Check for plausibility - arbitrary values */
+ if ((r < 20) || (r > 60000)) {
+ close(fd);
+ return (-1);
+ }
+ if ((l = (u_int64_t *)malloc(r << 3)) == NULL) {
+ close(fd);
+ return (-1);
+ }
+
+ /* Skip further uninteresting stuff */
+ read(fd, buf, 12);
+ m1 = read_be_dword(buf);
+ m2 = read_be_dword(&buf[4]);
+ m3 = read_be_dword(&buf[8]);
+ m3 += (m1 << 2)+m1+(m2 << 2)+(m2 << 1);
+ lseek(fd, (off_t)m3, SEEK_CUR);
+
+ /* Now go parse the tzfile leap second info */
+ for (m1 = 0; m1 < r; m1++) {
+ if (read(fd, buf, 8) != 8) {
+ free(l);
+ close(fd);
+ return (-1);
+ }
+ s = SEC_TO_TAI64(read_be_dword(buf));
+ /*
+ * Assume just _one_ leap second on each entry, and compensate
+ * the lacking error checking by validating the first entry
+ * against the known value
+ */
+ if (!m1 && s != 0x4000000004B2580AULL)
+ return (-1);
+ l[m1] = s;
+ }
+
+ /* Clean up and activate the table */
+ close(fd);
+ if (leapsecs != NULL)
+ free(leapsecs);
+ leapsecs = l;
+ leapsecs_num = r;
+ return (0);
+}
diff -pruN openntpd-3.7p1.orig/ntpleaps.h openntpd-3.7p1/ntpleaps.h
--- openntpd-3.7p1.orig/ntpleaps.h Thu Jan 1 00:00:00 1970
+++ openntpd-3.7p1/ntpleaps.h Tue May 9 09:08:29 2006
@@ -0,0 +1,75 @@
+/** $MirOS: src/usr.sbin/rdate/ntpleaps.h,v 1.3 2006/05/09 09:00:00 tg Exp $ */
+/* $OpenBSD: ntpleaps.h,v 1.3 2004/05/05 20:29:54 jakob Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2006
+ * Thorsten Glaser <tg_(_at_)_mirbsd_(_dot_)_de>
+ *
+ * Licensee is hereby permitted to deal in this work without restric-
+ * tion, including unlimited rights to use, publicly perform, modify,
+ * merge, distribute, sell, give away or sublicence, provided all co-
+ * pyright notices above, these terms and the disclaimer are retained
+ * in all redistributions or reproduced in accompanying documentation
+ * or other materials provided with binary redistributions.
+ *
+ * Licensor offers the work "AS IS" and WITHOUT WARRANTY of any kind,
+ * express, or implied, to the maximum extent permitted by applicable
+ * law, without malicious intent or gross negligence; in no event may
+ * licensor, an author or contributor be held liable for any indirect
+ * or other damage, or direct damage except proven a consequence of a
+ * direct error of said person and intended use of this work, loss or
+ * other issues arising in any way out of its use, even if advised of
+ * the possibility of such damage or existence of a nontrivial bug.
+ */
+
+/* Leap second support for SNTP clients
+ * This header file and its corresponding C file provide generic
+ * ability for NTP or SNTP clients to correctly handle leap seconds
+ * by reading them from an always existing file and subtracting the
+ * leap seconds from the NTP return value before setting the posix
+ * clock. This is fairly portable between operating systems and may
+ * be used for patching other ntp clients, too. The tzfile used is:
+ * /usr/share/zoneinfo/right/UTC which is available on any unix-like
+ * platform with the Olson tz library, which is necessary to get real
+ * leap second zoneinfo files and userland support anyways.
+ */
+
+#ifndef _NTPLEAPS_H
+#define _NTPLEAPS_H
+
+/* Offset between struct timeval.tv_sec and a tai64_t */
+#define NTPLEAPS_OFFSET (4611686018427387914ULL)
+
+/* Hide this ugly value from programmes */
+#define SEC_TO_TAI64(s) (NTPLEAPS_OFFSET + (u_int64_t)(s))
+#define TAI64_TO_SEC(t) ((t) - NTPLEAPS_OFFSET)
+
+/* Initialises the leap second table. Does not need to be called
+ * before usage of the subtract funtion, but calls ntpleaps_read.
+ * Returns 0 on success, -1 on error (displays a warning on stderr)
+ */
+int ntpleaps_init(void);
+
+/* Re-reads the leap second table, thus consuming quite much time.
+ * Ought to be called from within daemons at least once a month to
+ * ensure the in-memory table is always up-to-date.
+ * Returns 0 on success, -1 on error (leap seconds will not be available)
+ */
+int ntpleaps_read(void);
+
+/* Subtracts leap seconds from the given value (converts NTP time
+ * to posix clock tick time.
+ * Returns 0 on success, -1 on error (time is unchanged), 1 on leap second
+ */
+int ntpleaps_sub(u_int64_t *);
+
+/* This macro is not implemented on all operating systems */
+#ifndef SA_LEN
+#define SA_LEN(x) (((x)->sa_family == AF_INET6) ? \
+ sizeof(struct sockaddr_in6) : \
+ (((x)->sa_family == AF_INET) ? \
+ sizeof(struct sockaddr_in) : \
+ sizeof(struct sockaddr)))
+#endif
+
+#endif
diff -pruN openntpd-3.7p1.orig/util.c openntpd-3.7p1/util.c
--- openntpd-3.7p1.orig/util.c Tue Dec 14 01:18:13 2004
+++ openntpd-3.7p1/util.c Tue May 9 09:08:29 2006
@@ -20,16 +20,25 @@
#include <limits.h>
#include "ntpd.h"
+#include "ntpleaps.h"
+extern int corrleaps;
+
double
gettime(void)
{
struct timeval tv;
+ uint64_t t;
if (gettimeofday(&tv, NULL) == -1)
fatal("gettimeofday");
- return (tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec);
+ /* subtract leap seconds to set the posix tick */
+ t = SEC_TO_TAI64(tv.tv_sec);
+ if (corrleaps)
+ ntpleaps_sub(&t);
+
+ return (TAI64_TO_SEC(t) + JAN_1970 + 1.0e-6 * tv.tv_usec);
}
Visit your host, monkey.org