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 @@ [EMAIL PROTECTED]@
 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 <[EMAIL PROTECTED]>
+ *
+ * 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);
 }

Reply via email to