summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Schlyter <jakob@cvs.openbsd.org>2002-07-27 08:46:52 +0000
committerJakob Schlyter <jakob@cvs.openbsd.org>2002-07-27 08:46:52 +0000
commitbd99e93bdd1c214922290f933fe7814b62149ed0 (patch)
treeda9cb077d01e75ad7b0be9f2f746eb173bf5a7a5
parent08fde9efdb250c1a8ff95f6019301ba4643e1fa3 (diff)
leapsecond support; written by thorsten glaser; ok millert@
-rw-r--r--usr.sbin/rdate/ntpleaps.c163
-rw-r--r--usr.sbin/rdate/ntpleaps.h59
2 files changed, 222 insertions, 0 deletions
diff --git a/usr.sbin/rdate/ntpleaps.c b/usr.sbin/rdate/ntpleaps.c
new file mode 100644
index 00000000000..4dd8a81ea6c
--- /dev/null
+++ b/usr.sbin/rdate/ntpleaps.c
@@ -0,0 +1,163 @@
+/* $Id: ntpleaps.c,v 1.1 2002/07/27 08:46:51 jakob Exp $ */
+
+/*
+ * Copyright (c) 2002 by Thorsten "mirabile" Glaser <x86@ePOST.de>
+ *
+ * Permission is hereby granted to any person obtaining a copy of this work
+ * to deal in the work, without restrictions, including unlimited rights to
+ * use, copy, modify, merge, publish, distribute, sublicense or sell copies
+ * of the work, and to permit persons to whom the work is furnished to also
+ * do so, as long as due credit is given to the original author and contri-
+ * butors, and the following disclaimer is kept in all substantial portions
+ * of the work or accompanying documentation:
+ *
+ * This work is provided "AS IS", without warranty of any kind, neither ex-
+ * press nor implied, including, but not limited to, the warranties of mer-
+ * chantability, fitness for particular purposes and noninfringement. In NO
+ * event shall the author and contributors be liable for any claim, damages
+ * and such, whether in contract, strict liability or otherwise, arising in
+ * any way out of this work, even if advised of the possibility of such.
+ */
+
+/* Leap second support for NTP clients (generic) */
+
+static const char RCSId[] = "$OpenBSD: ntpleaps.c,v 1.1 2002/07/27 08:46:51 jakob Exp $";
+
+
+/* I could include tzfile.h, but this would make the code unportable
+ * at no real benefit. Read tzfile.h for why.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "ntpleaps.h"
+
+u_int64_t *leapsecs = NULL;
+unsigned int leapsecs_num = 0;
+static int flaginit = 0;
+static int flagwarn = 0;
+
+
+int
+ntpleaps_init(void)
+{
+ if (flaginit)
+ return 0;
+
+ if (!ntpleaps_read()) {
+ flaginit = 1;
+ return(0);
+ }
+
+ /* This does not really hurt, but users will complain about
+ * off-by-22-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!\n", stderr);
+ flagwarn = 1; /* put it only once */
+ }
+
+ return (-1);
+}
+
+int
+ntpleaps_sub(u_int64_t *t)
+{
+ unsigned int i = 0;
+ u_int64_t u;
+ int r=1;
+
+ if (ntpleaps_init() == -1)
+ return(-1);
+
+ u = *t;
+
+ while (i<leapsecs_num) {
+ if (u < leapsecs[i])
+ break;
+ if (u == leapsecs[i++])
+ goto do_sub;
+ }
+ --r;
+
+do_sub:
+ *t=u-i;
+ return (r);
+}
+
+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)
+ return (-1);
+
+ /* Check signature */
+ read(fd, buf, 4); buf[4]=0;
+ if(strcmp((const char *)buf, "TZif")) {
+ close(fd);
+ return (-1);
+ }
+
+ /* Pre-initalize 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=ntohl( *((u_int32_t *) (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 = ntohl( *((u_int32_t *)(buf)) );
+ m2 = ntohl( *((u_int32_t *)(buf+4)) );
+ m3 = ntohl( *((u_int32_t *)(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++) {
+ read(fd, buf, 8);
+ m2 = ntohl( *((u_int32_t *)buf) );
+ s = NTPLEAPS_OFFSET + (u_int64_t) m2;
+ /* 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 --git a/usr.sbin/rdate/ntpleaps.h b/usr.sbin/rdate/ntpleaps.h
new file mode 100644
index 00000000000..eb5fef167ed
--- /dev/null
+++ b/usr.sbin/rdate/ntpleaps.h
@@ -0,0 +1,59 @@
+/* $Id: ntpleaps.h,v 1.1 2002/07/27 08:46:51 jakob Exp $ */
+
+/*
+ * Copyright (c) 2002 by Thorsten "mirabile" Glaser <x86@ePOST.de>
+ *
+ * Permission is hereby granted to any person obtaining a copy of this work
+ * to deal in the work, without restrictions, including unlimited rights to
+ * use, copy, modify, merge, publish, distribute, sublicense or sell copies
+ * of the work, and to permit persons to whom the work is furnished to also
+ * do so, as long as due credit is given to the original author and contri-
+ * butors, and the following disclaimer is kept in all substantial portions
+ * of the work or accompanying documentation:
+ *
+ * This work is provided "AS IS", without warranty of any kind, neither ex-
+ * press nor implied, including, but not limited to, the warranties of mer-
+ * chantability, fitness for particular purposes and noninfringement. In NO
+ * event shall the author and contributors be liable for any claim, damages
+ * and such, whether in contract, strict liability or otherwise, arising in
+ * any way out of this work, even if advised of the possibility of such.
+ */
+
+/* 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)
+
+/* Initializes 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 *);
+
+#endif