diff options
author | Jakob Schlyter <jakob@cvs.openbsd.org> | 2002-07-27 08:46:52 +0000 |
---|---|---|
committer | Jakob Schlyter <jakob@cvs.openbsd.org> | 2002-07-27 08:46:52 +0000 |
commit | bd99e93bdd1c214922290f933fe7814b62149ed0 (patch) | |
tree | da9cb077d01e75ad7b0be9f2f746eb173bf5a7a5 | |
parent | 08fde9efdb250c1a8ff95f6019301ba4643e1fa3 (diff) |
leapsecond support; written by thorsten glaser; ok millert@
-rw-r--r-- | usr.sbin/rdate/ntpleaps.c | 163 | ||||
-rw-r--r-- | usr.sbin/rdate/ntpleaps.h | 59 |
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 |