xref: /openbsd/usr.sbin/ntpd/util.c (revision 8745f5cf)
1 /*	$OpenBSD: util.c,v 1.28 2023/12/20 15:36:36 otto Exp $ */
2 
3 /*
4  * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <fcntl.h>
20 #include <limits.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <time.h>
25 #include <unistd.h>
26 
27 #include "ntpd.h"
28 
29 double
gettime_corrected(void)30 gettime_corrected(void)
31 {
32 	return (gettime() + getoffset());
33 }
34 
35 double
getoffset(void)36 getoffset(void)
37 {
38 	struct timeval	tv;
39 	if (adjtime(NULL, &tv) == -1)
40 		return (0.0);
41 	return (tv.tv_sec + 1.0e-6 * tv.tv_usec);
42 }
43 
44 double
gettime(void)45 gettime(void)
46 {
47 	struct timeval	tv;
48 
49 	if (gettimeofday(&tv, NULL) == -1)
50 		fatal("gettimeofday");
51 
52 	return (gettime_from_timeval(&tv));
53 }
54 
55 double
gettime_from_timeval(struct timeval * tv)56 gettime_from_timeval(struct timeval *tv)
57 {
58 	/*
59 	 * Account for overflow on OSes that have a 32-bit time_t.
60 	 */
61 	return ((uint64_t)tv->tv_sec + JAN_1970 + 1.0e-6 * tv->tv_usec);
62 }
63 
64 time_t
getmonotime(void)65 getmonotime(void)
66 {
67 	struct timespec	ts;
68 
69 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
70 		fatal("clock_gettime");
71 
72 	return (ts.tv_sec);
73 }
74 
75 
76 void
d_to_tv(double d,struct timeval * tv)77 d_to_tv(double d, struct timeval *tv)
78 {
79 	tv->tv_sec = d;
80 	tv->tv_usec = (d - tv->tv_sec) * 1000000;
81 	while (tv->tv_usec < 0) {
82 		tv->tv_usec += 1000000;
83 		tv->tv_sec -= 1;
84 	}
85 }
86 
87 double
lfp_to_d(struct l_fixedpt lfp)88 lfp_to_d(struct l_fixedpt lfp)
89 {
90 	double	base, ret;
91 
92 	lfp.int_partl = ntohl(lfp.int_partl);
93 	lfp.fractionl = ntohl(lfp.fractionl);
94 
95 	/* see comment in ntp.h */
96 	base = NTP_ERA;
97 	if (lfp.int_partl <= INT32_MAX)
98 		base++;
99 	ret = base * SECS_IN_ERA;
100 	ret += (double)(lfp.int_partl) + ((double)lfp.fractionl / L_DENOMINATOR);
101 
102 	return (ret);
103 }
104 
105 struct l_fixedpt
d_to_lfp(double d)106 d_to_lfp(double d)
107 {
108 	struct l_fixedpt	lfp;
109 
110 	while (d > SECS_IN_ERA)
111 		d -= SECS_IN_ERA;
112 	lfp.int_partl = htonl((u_int32_t)d);
113 	lfp.fractionl = htonl((u_int32_t)((d - (u_int32_t)d) * L_DENOMINATOR));
114 
115 	return (lfp);
116 }
117 
118 double
sfp_to_d(struct s_fixedpt sfp)119 sfp_to_d(struct s_fixedpt sfp)
120 {
121 	double	ret;
122 
123 	sfp.int_parts = ntohs(sfp.int_parts);
124 	sfp.fractions = ntohs(sfp.fractions);
125 
126 	ret = (double)(sfp.int_parts) + ((double)sfp.fractions / S_DENOMINATOR);
127 
128 	return (ret);
129 }
130 
131 struct s_fixedpt
d_to_sfp(double d)132 d_to_sfp(double d)
133 {
134 	struct s_fixedpt	sfp;
135 
136 	sfp.int_parts = htons((u_int16_t)d);
137 	sfp.fractions = htons((u_int16_t)((d - (u_int16_t)d) * S_DENOMINATOR));
138 
139 	return (sfp);
140 }
141 
142 char *
print_rtable(int r)143 print_rtable(int r)
144 {
145 	static char b[11];
146 
147 	b[0] = 0;
148 	if (r > 0)
149 		snprintf(b, sizeof(b), "rtable %d", r);
150 
151 	return (b);
152 }
153 
154 const char *
log_sockaddr(struct sockaddr * sa)155 log_sockaddr(struct sockaddr *sa)
156 {
157 	static char	buf[NI_MAXHOST];
158 
159 	if (getnameinfo(sa, SA_LEN(sa), buf, sizeof(buf), NULL, 0,
160 	    NI_NUMERICHOST))
161 		return ("(unknown)");
162 	else
163 		return (buf);
164 }
165 
166 const char *
log_ntp_addr(struct ntp_addr * addr)167 log_ntp_addr(struct ntp_addr *addr)
168 {
169 	if (addr == NULL)
170 		return ("(unknown)");
171 	return log_sockaddr((struct sockaddr *)&addr->ss);
172 }
173 
174 pid_t
start_child(char * pname,int cfd,int argc,char ** argv)175 start_child(char *pname, int cfd, int argc, char **argv)
176 {
177 	char		**nargv;
178 	int		  nargc, i;
179 	pid_t		  pid;
180 
181 	/* Prepare the child process new argv. */
182 	nargv = calloc(argc + 3, sizeof(char *));
183 	if (nargv == NULL)
184 		fatal("%s: calloc", __func__);
185 
186 	/* Copy the program name first. */
187 	nargc = 0;
188 	nargv[nargc++] = argv[0];
189 
190 	/* Set the process name and copy the original args. */
191 	nargv[nargc++] = "-P";
192 	nargv[nargc++] = pname;
193 	for (i = 1; i < argc; i++)
194 		nargv[nargc++] = argv[i];
195 
196 	nargv[nargc] = NULL;
197 
198 	switch (pid = fork()) {
199 	case -1:
200 		fatal("%s: fork", __func__);
201 		break;
202 	case 0:
203 		/* Prepare the parent socket and execute. */
204 		if (cfd != PARENT_SOCK_FILENO) {
205 			if (dup2(cfd, PARENT_SOCK_FILENO) == -1)
206 				fatal("dup2");
207 		} else if (fcntl(cfd, F_SETFD, 0) == -1)
208 			fatal("fcntl");
209 
210 		execvp(argv[0], nargv);
211 		fatal("%s: execvp", __func__);
212 		break;
213 
214 	default:
215 		/* Close child's socket end. */
216 		close(cfd);
217 		break;
218 	}
219 
220 	free(nargv);
221 	return (pid);
222 }
223 
224 int
sanitize_argv(int * argc,char *** argv)225 sanitize_argv(int *argc, char ***argv)
226 {
227 	char		**nargv;
228 	int		  nargc;
229 	int		  i;
230 
231 	/*
232 	 * We need at least three arguments:
233 	 * Example: '/usr/sbin/ntpd' '-P' 'foobar'.
234 	 */
235 	if (*argc < 3)
236 		return (-1);
237 
238 	*argc -= 2;
239 
240 	/* Allocate new arguments vector and copy pointers. */
241 	nargv = calloc((*argc) + 1, sizeof(char *));
242 	if (nargv == NULL)
243 		return (-1);
244 
245 	nargc = 0;
246 	nargv[nargc++] = (*argv)[0];
247 	for (i = 1; i < *argc; i++)
248 		nargv[nargc++] = (*argv)[i + 2];
249 
250 	nargv[nargc] = NULL;
251 	*argv = nargv;
252 	return (0);
253 }
254