GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/rdate/ntpleaps.c Lines: 0 63 0.0 %
Date: 2017-11-07 Branches: 0 28 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ntpleaps.c,v 1.14 2015/12/12 20:04:23 mmcc Exp $	*/
2
3
/*
4
 * Copyright (c) 2002 Thorsten Glaser. All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 *    - Redistributions of source code must retain the above copyright
11
 *      notice, this list of conditions and the following disclaimer.
12
 *    - Redistributions in binary form must reproduce the above
13
 *      copyright notice, this list of conditions and the following
14
 *      disclaimer in the documentation and/or other materials provided
15
 *      with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 */
31
32
/* Leap second support for NTP clients (generic) */
33
34
/*
35
 * I could include tzfile.h, but this would make the code unportable
36
 * at no real benefit. Read tzfile.h for why.
37
 */
38
39
#include <sys/types.h>
40
#include <netinet/in.h>
41
42
#include <fcntl.h>
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <unistd.h>
47
48
#include "ntpleaps.h"
49
50
static u_int64_t *leapsecs;
51
static unsigned int leapsecs_num;
52
53
u_int32_t	read_be_dword(u_int8_t *ptr);
54
55
56
int
57
ntpleaps_init(void)
58
{
59
	static int doneinit;
60
	static int donewarn;
61
62
	if (doneinit)
63
		return (0);
64
65
	if (ntpleaps_read() == 0) {
66
		doneinit = 1;
67
		return (0);
68
	}
69
70
	/* This does not really hurt, but users will complain about
71
	 * off-by-22-seconds (at time of coding) errors if we don't warn.
72
	 */
73
	if (!donewarn) {
74
		fputs("Warning: error reading tzfile. You will NOT be\n"
75
		    "able to get legal time or posix compliance!\n", stderr);
76
		donewarn = 1;	/* put it only once */
77
	}
78
79
	return (-1);
80
}
81
82
int
83
ntpleaps_sub(u_int64_t *t)
84
{
85
	unsigned int i = 0;
86
	u_int64_t u;
87
	int r = 1;
88
89
	if (ntpleaps_init() == -1)
90
		return (-1);
91
92
	u = *t;
93
94
	while (i < leapsecs_num) {
95
		if (u < leapsecs[i]) {
96
			r--;
97
			break;
98
		}
99
		if (u == leapsecs[i++])
100
			break;
101
	}
102
103
	*t = u - i;
104
	return (r);
105
}
106
107
u_int32_t
108
read_be_dword(u_int8_t *ptr)
109
{
110
	u_int32_t res;
111
112
	memcpy(&res, ptr, 4);
113
	return (ntohl(res));
114
}
115
116
117
int
118
ntpleaps_read(void)
119
{
120
	int fd;
121
	unsigned int r;
122
	u_int8_t buf[32];
123
	u_int32_t m1, m2, m3;
124
	u_int64_t s;
125
	u_int64_t *l;
126
127
	fd = open("/usr/share/zoneinfo/right/UTC", O_RDONLY | O_NDELAY);
128
	if (fd == -1)
129
		return (-1);
130
131
	/* Check signature */
132
	read(fd, buf, 4);
133
	buf[4] = 0;
134
	if (strcmp((const char *)buf, "TZif")) {
135
		close(fd);
136
		return (-1);
137
	}
138
139
	/* Pre-initialize buf[24..27] so we need not check read(2) result */
140
	buf[24] = 0;
141
	buf[25] = 0;
142
	buf[26] = 0;
143
	buf[27] = 0;
144
145
	/* Skip uninteresting parts of header */
146
	read(fd, buf, 28);
147
148
	/* Read number of leap second entries */
149
	r = read_be_dword(&buf[24]);
150
	/* Check for plausibility - arbitrary values */
151
	if ((r < 20) || (r > 60000)) {
152
		close(fd);
153
		return (-1);
154
	}
155
	if ((l = reallocarray(NULL, r, sizeof(u_int64_t))) == NULL) {
156
		close(fd);
157
		return (-1);
158
	}
159
160
	/* Skip further uninteresting stuff */
161
	read(fd, buf, 12);
162
	m1 = read_be_dword(buf);
163
	m2 = read_be_dword(&buf[4]);
164
	m3 = read_be_dword(&buf[8]);
165
	m3 += (m1 << 2)+m1+(m2 << 2)+(m2 << 1);
166
	lseek(fd, (off_t)m3, SEEK_CUR);
167
168
	/* Now go parse the tzfile leap second info */
169
	for (m1 = 0; m1 < r; m1++) {
170
		if (read(fd, buf, 8) != 8) {
171
			free(l);
172
			close(fd);
173
			return (-1);
174
		}
175
		s = SEC_TO_TAI64(read_be_dword(buf));
176
		/*
177
		 * Assume just _one_ leap second on each entry, and compensate
178
		 * the lacking error checking by validating the first entry
179
		 * against the known value
180
		 */
181
		if (!m1 && s != 0x4000000004B2580AULL) {
182
			free(l);
183
			close(fd);
184
			return (-1);
185
		}
186
		l[m1] = s;
187
	}
188
189
	/* Clean up and activate the table */
190
	close(fd);
191
	free(leapsecs);
192
	leapsecs = l;
193
	leapsecs_num = r;
194
	return (0);
195
}