xref: /openbsd/usr.sbin/ntpd/util.c (revision 3cab2bb3)
1 /*	$OpenBSD: util.c,v 1.25 2020/01/30 15:55:41 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 <stdio.h>
22 #include <stdlib.h>
23 #include <time.h>
24 #include <unistd.h>
25 
26 #include "ntpd.h"
27 
28 double
29 gettime_corrected(void)
30 {
31 	return (gettime() + getoffset());
32 }
33 
34 double
35 getoffset(void)
36 {
37 	struct timeval	tv;
38 	if (adjtime(NULL, &tv) == -1)
39 		return (0.0);
40 	return (tv.tv_sec + 1.0e-6 * tv.tv_usec);
41 }
42 
43 double
44 gettime(void)
45 {
46 	struct timeval	tv;
47 
48 	if (gettimeofday(&tv, NULL) == -1)
49 		fatal("gettimeofday");
50 
51 	return (gettime_from_timeval(&tv));
52 }
53 
54 double
55 gettime_from_timeval(struct timeval *tv)
56 {
57 	/*
58 	 * Account for overflow on OSes that have a 32-bit time_t.
59 	 */
60 	return ((uint64_t)tv->tv_sec + JAN_1970 + 1.0e-6 * tv->tv_usec);
61 }
62 
63 time_t
64 getmonotime(void)
65 {
66 	struct timespec	ts;
67 
68 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
69 		fatal("clock_gettime");
70 
71 	return (ts.tv_sec);
72 }
73 
74 
75 void
76 d_to_tv(double d, struct timeval *tv)
77 {
78 	tv->tv_sec = d;
79 	tv->tv_usec = (d - tv->tv_sec) * 1000000;
80 	while (tv->tv_usec < 0) {
81 		tv->tv_usec += 1000000;
82 		tv->tv_sec -= 1;
83 	}
84 }
85 
86 double
87 lfp_to_d(struct l_fixedpt lfp)
88 {
89 	double	base, ret;
90 
91 	lfp.int_partl = ntohl(lfp.int_partl);
92 	lfp.fractionl = ntohl(lfp.fractionl);
93 
94 	/* see comment in ntp.h */
95 	base = NTP_ERA;
96 	if (lfp.int_partl <= INT32_MAX)
97 		base++;
98 	ret = base * SECS_IN_ERA;
99 	ret += (double)(lfp.int_partl) + ((double)lfp.fractionl / UINT_MAX);
100 
101 	return (ret);
102 }
103 
104 struct l_fixedpt
105 d_to_lfp(double d)
106 {
107 	struct l_fixedpt	lfp;
108 
109 	while (d > SECS_IN_ERA)
110 		d -= SECS_IN_ERA;
111 	lfp.int_partl = htonl((u_int32_t)d);
112 	lfp.fractionl = htonl((u_int32_t)((d - (u_int32_t)d) * UINT_MAX));
113 
114 	return (lfp);
115 }
116 
117 double
118 sfp_to_d(struct s_fixedpt sfp)
119 {
120 	double	ret;
121 
122 	sfp.int_parts = ntohs(sfp.int_parts);
123 	sfp.fractions = ntohs(sfp.fractions);
124 
125 	ret = (double)(sfp.int_parts) + ((double)sfp.fractions / USHRT_MAX);
126 
127 	return (ret);
128 }
129 
130 struct s_fixedpt
131 d_to_sfp(double d)
132 {
133 	struct s_fixedpt	sfp;
134 
135 	sfp.int_parts = htons((u_int16_t)d);
136 	sfp.fractions = htons((u_int16_t)((d - (u_int16_t)d) * USHRT_MAX));
137 
138 	return (sfp);
139 }
140 
141 char *
142 print_rtable(int r)
143 {
144 	static char b[11];
145 
146 	b[0] = 0;
147 	if (r > 0)
148 		snprintf(b, sizeof(b), "rtable %d", r);
149 
150 	return (b);
151 }
152 
153 const char *
154 log_sockaddr(struct sockaddr *sa)
155 {
156 	static char	buf[NI_MAXHOST];
157 
158 	if (getnameinfo(sa, SA_LEN(sa), buf, sizeof(buf), NULL, 0,
159 	    NI_NUMERICHOST))
160 		return ("(unknown)");
161 	else
162 		return (buf);
163 }
164 
165 pid_t
166 start_child(char *pname, int cfd, int argc, char **argv)
167 {
168 	char		**nargv;
169 	int		  nargc, i;
170 	pid_t		  pid;
171 
172 	/* Prepare the child process new argv. */
173 	nargv = calloc(argc + 3, sizeof(char *));
174 	if (nargv == NULL)
175 		fatal("%s: calloc", __func__);
176 
177 	/* Copy the program name first. */
178 	nargc = 0;
179 	nargv[nargc++] = argv[0];
180 
181 	/* Set the process name and copy the original args. */
182 	nargv[nargc++] = "-P";
183 	nargv[nargc++] = pname;
184 	for (i = 1; i < argc; i++)
185 		nargv[nargc++] = argv[i];
186 
187 	nargv[nargc] = NULL;
188 
189 	switch (pid = fork()) {
190 	case -1:
191 		fatal("%s: fork", __func__);
192 		break;
193 	case 0:
194 		/* Prepare the parent socket and execute. */
195 		if (cfd != PARENT_SOCK_FILENO) {
196 			if (dup2(cfd, PARENT_SOCK_FILENO) == -1)
197 				fatal("dup2");
198 		} else if (fcntl(cfd, F_SETFD, 0) == -1)
199 			fatal("fcntl");
200 
201 		execvp(argv[0], nargv);
202 		fatal("%s: execvp", __func__);
203 		break;
204 
205 	default:
206 		/* Close child's socket end. */
207 		close(cfd);
208 		break;
209 	}
210 
211 	free(nargv);
212 	return (pid);
213 }
214 
215 int
216 sanitize_argv(int *argc, char ***argv)
217 {
218 	char		**nargv;
219 	int		  nargc;
220 	int		  i;
221 
222 	/*
223 	 * We need at least three arguments:
224 	 * Example: '/usr/sbin/ntpd' '-P' 'foobar'.
225 	 */
226 	if (*argc < 3)
227 		return (-1);
228 
229 	*argc -= 2;
230 
231 	/* Allocate new arguments vector and copy pointers. */
232 	nargv = calloc((*argc) + 1, sizeof(char *));
233 	if (nargv == NULL)
234 		return (-1);
235 
236 	nargc = 0;
237 	nargv[nargc++] = (*argv)[0];
238 	for (i = 1; i < *argc; i++)
239 		nargv[nargc++] = (*argv)[i + 2];
240 
241 	nargv[nargc] = NULL;
242 	*argv = nargv;
243 	return (0);
244 }
245