xref: /openbsd-src/usr.sbin/ntpd/util.c (revision 8745f5cf9c71e9801d335b988c13bd14a57ce14d)
1*8745f5cfSotto /*	$OpenBSD: util.c,v 1.28 2023/12/20 15:36:36 otto Exp $ */
2692d048dSalexander 
3692d048dSalexander /*
4692d048dSalexander  * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
5692d048dSalexander  *
6692d048dSalexander  * Permission to use, copy, modify, and distribute this software for any
7692d048dSalexander  * purpose with or without fee is hereby granted, provided that the above
8692d048dSalexander  * copyright notice and this permission notice appear in all copies.
9692d048dSalexander  *
10692d048dSalexander  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11692d048dSalexander  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12692d048dSalexander  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13692d048dSalexander  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14714ab749Sreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15714ab749Sreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16714ab749Sreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17692d048dSalexander  */
18692d048dSalexander 
19102c98c6Srzalamena #include <fcntl.h>
20c1ed3944Shenning #include <limits.h>
21c11af8cfSclaudio #include <stdint.h>
2202d74365Sphessler #include <stdio.h>
234e840e7aSrzalamena #include <stdlib.h>
247b6bdf51Sbcook #include <time.h>
254e840e7aSrzalamena #include <unistd.h>
26692d048dSalexander 
27692d048dSalexander #include "ntpd.h"
28692d048dSalexander 
29692d048dSalexander double
gettime_corrected(void)304e6294c2Sotto gettime_corrected(void)
314e6294c2Sotto {
324e6294c2Sotto 	return (gettime() + getoffset());
334e6294c2Sotto }
344e6294c2Sotto 
354e6294c2Sotto double
getoffset(void)364e6294c2Sotto getoffset(void)
374e6294c2Sotto {
384e6294c2Sotto 	struct timeval	tv;
394e6294c2Sotto 	if (adjtime(NULL, &tv) == -1)
404e6294c2Sotto 		return (0.0);
414e6294c2Sotto 	return (tv.tv_sec + 1.0e-6 * tv.tv_usec);
424e6294c2Sotto }
434e6294c2Sotto 
444e6294c2Sotto double
gettime(void)45692d048dSalexander gettime(void)
46692d048dSalexander {
47692d048dSalexander 	struct timeval	tv;
48692d048dSalexander 
49692d048dSalexander 	if (gettimeofday(&tv, NULL) == -1)
50692d048dSalexander 		fatal("gettimeofday");
51692d048dSalexander 
52e67a9c06Sbcook 	return (gettime_from_timeval(&tv));
53692d048dSalexander }
54692d048dSalexander 
55bc58a738Sreyk double
gettime_from_timeval(struct timeval * tv)56bc58a738Sreyk gettime_from_timeval(struct timeval *tv)
57bc58a738Sreyk {
58e67a9c06Sbcook 	/*
59e67a9c06Sbcook 	 * Account for overflow on OSes that have a 32-bit time_t.
60e67a9c06Sbcook 	 */
61e67a9c06Sbcook 	return ((uint64_t)tv->tv_sec + JAN_1970 + 1.0e-6 * tv->tv_usec);
62bc58a738Sreyk }
63bc58a738Sreyk 
642fae8c34Shenning time_t
getmonotime(void)652fae8c34Shenning getmonotime(void)
662fae8c34Shenning {
672fae8c34Shenning 	struct timespec	ts;
682fae8c34Shenning 
692fae8c34Shenning 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
702fae8c34Shenning 		fatal("clock_gettime");
712fae8c34Shenning 
722fae8c34Shenning 	return (ts.tv_sec);
732fae8c34Shenning }
742fae8c34Shenning 
75138ae74fShenning 
76138ae74fShenning void
d_to_tv(double d,struct timeval * tv)77138ae74fShenning d_to_tv(double d, struct timeval *tv)
78138ae74fShenning {
794f8f19c5Skrw 	tv->tv_sec = d;
8058ae8097Sotto 	tv->tv_usec = (d - tv->tv_sec) * 1000000;
8183f2415aSotto 	while (tv->tv_usec < 0) {
8283f2415aSotto 		tv->tv_usec += 1000000;
8383f2415aSotto 		tv->tv_sec -= 1;
8483f2415aSotto 	}
85138ae74fShenning }
86138ae74fShenning 
87692d048dSalexander double
lfp_to_d(struct l_fixedpt lfp)88692d048dSalexander lfp_to_d(struct l_fixedpt lfp)
89692d048dSalexander {
90d96a2e9bSotto 	double	base, ret;
91692d048dSalexander 
92af0b62daSmickey 	lfp.int_partl = ntohl(lfp.int_partl);
93af0b62daSmickey 	lfp.fractionl = ntohl(lfp.fractionl);
94692d048dSalexander 
95d96a2e9bSotto 	/* see comment in ntp.h */
96d96a2e9bSotto 	base = NTP_ERA;
97d96a2e9bSotto 	if (lfp.int_partl <= INT32_MAX)
98d96a2e9bSotto 		base++;
99d96a2e9bSotto 	ret = base * SECS_IN_ERA;
100c338e3e2Sotto 	ret += (double)(lfp.int_partl) + ((double)lfp.fractionl / L_DENOMINATOR);
101692d048dSalexander 
102692d048dSalexander 	return (ret);
103692d048dSalexander }
104692d048dSalexander 
105692d048dSalexander struct l_fixedpt
d_to_lfp(double d)106692d048dSalexander d_to_lfp(double d)
107692d048dSalexander {
108692d048dSalexander 	struct l_fixedpt	lfp;
109692d048dSalexander 
110d96a2e9bSotto 	while (d > SECS_IN_ERA)
111d96a2e9bSotto 		d -= SECS_IN_ERA;
112af0b62daSmickey 	lfp.int_partl = htonl((u_int32_t)d);
113c338e3e2Sotto 	lfp.fractionl = htonl((u_int32_t)((d - (u_int32_t)d) * L_DENOMINATOR));
114692d048dSalexander 
115692d048dSalexander 	return (lfp);
116692d048dSalexander }
117247f21e5Salexander 
118247f21e5Salexander double
sfp_to_d(struct s_fixedpt sfp)119247f21e5Salexander sfp_to_d(struct s_fixedpt sfp)
120247f21e5Salexander {
121247f21e5Salexander 	double	ret;
122247f21e5Salexander 
123af0b62daSmickey 	sfp.int_parts = ntohs(sfp.int_parts);
124af0b62daSmickey 	sfp.fractions = ntohs(sfp.fractions);
125247f21e5Salexander 
126c338e3e2Sotto 	ret = (double)(sfp.int_parts) + ((double)sfp.fractions / S_DENOMINATOR);
127247f21e5Salexander 
128247f21e5Salexander 	return (ret);
129247f21e5Salexander }
130247f21e5Salexander 
131247f21e5Salexander struct s_fixedpt
d_to_sfp(double d)132247f21e5Salexander d_to_sfp(double d)
133247f21e5Salexander {
134247f21e5Salexander 	struct s_fixedpt	sfp;
135247f21e5Salexander 
136af0b62daSmickey 	sfp.int_parts = htons((u_int16_t)d);
137c338e3e2Sotto 	sfp.fractions = htons((u_int16_t)((d - (u_int16_t)d) * S_DENOMINATOR));
138247f21e5Salexander 
139247f21e5Salexander 	return (sfp);
140247f21e5Salexander }
14102d74365Sphessler 
14202d74365Sphessler char *
print_rtable(int r)14302d74365Sphessler print_rtable(int r)
14402d74365Sphessler {
14502d74365Sphessler 	static char b[11];
14602d74365Sphessler 
14702d74365Sphessler 	b[0] = 0;
14802d74365Sphessler 	if (r > 0)
14902d74365Sphessler 		snprintf(b, sizeof(b), "rtable %d", r);
15002d74365Sphessler 
15102d74365Sphessler 	return (b);
15202d74365Sphessler }
15341ab25d4Sreyk 
15441ab25d4Sreyk const char *
log_sockaddr(struct sockaddr * sa)15541ab25d4Sreyk log_sockaddr(struct sockaddr *sa)
15641ab25d4Sreyk {
15741ab25d4Sreyk 	static char	buf[NI_MAXHOST];
15841ab25d4Sreyk 
15941ab25d4Sreyk 	if (getnameinfo(sa, SA_LEN(sa), buf, sizeof(buf), NULL, 0,
16041ab25d4Sreyk 	    NI_NUMERICHOST))
16141ab25d4Sreyk 		return ("(unknown)");
16241ab25d4Sreyk 	else
16341ab25d4Sreyk 		return (buf);
16441ab25d4Sreyk }
1654e840e7aSrzalamena 
166*8745f5cfSotto const char *
log_ntp_addr(struct ntp_addr * addr)167*8745f5cfSotto log_ntp_addr(struct ntp_addr *addr)
168*8745f5cfSotto {
169*8745f5cfSotto 	if (addr == NULL)
170*8745f5cfSotto 		return ("(unknown)");
171*8745f5cfSotto 	return log_sockaddr((struct sockaddr *)&addr->ss);
172*8745f5cfSotto }
173*8745f5cfSotto 
1744e840e7aSrzalamena pid_t
start_child(char * pname,int cfd,int argc,char ** argv)1754e840e7aSrzalamena start_child(char *pname, int cfd, int argc, char **argv)
1764e840e7aSrzalamena {
1774e840e7aSrzalamena 	char		**nargv;
1784e840e7aSrzalamena 	int		  nargc, i;
1794e840e7aSrzalamena 	pid_t		  pid;
1804e840e7aSrzalamena 
1814e840e7aSrzalamena 	/* Prepare the child process new argv. */
1824e840e7aSrzalamena 	nargv = calloc(argc + 3, sizeof(char *));
1834e840e7aSrzalamena 	if (nargv == NULL)
1844e840e7aSrzalamena 		fatal("%s: calloc", __func__);
1854e840e7aSrzalamena 
1864e840e7aSrzalamena 	/* Copy the program name first. */
1874e840e7aSrzalamena 	nargc = 0;
1884e840e7aSrzalamena 	nargv[nargc++] = argv[0];
1894e840e7aSrzalamena 
1904e840e7aSrzalamena 	/* Set the process name and copy the original args. */
1914e840e7aSrzalamena 	nargv[nargc++] = "-P";
1924e840e7aSrzalamena 	nargv[nargc++] = pname;
1934e840e7aSrzalamena 	for (i = 1; i < argc; i++)
1944e840e7aSrzalamena 		nargv[nargc++] = argv[i];
1954e840e7aSrzalamena 
196326f547bSgsoares 	nargv[nargc] = NULL;
1974e840e7aSrzalamena 
1984e840e7aSrzalamena 	switch (pid = fork()) {
1994e840e7aSrzalamena 	case -1:
2004e840e7aSrzalamena 		fatal("%s: fork", __func__);
2014e840e7aSrzalamena 		break;
2024e840e7aSrzalamena 	case 0:
2034e840e7aSrzalamena 		/* Prepare the parent socket and execute. */
204102c98c6Srzalamena 		if (cfd != PARENT_SOCK_FILENO) {
205102c98c6Srzalamena 			if (dup2(cfd, PARENT_SOCK_FILENO) == -1)
206102c98c6Srzalamena 				fatal("dup2");
207102c98c6Srzalamena 		} else if (fcntl(cfd, F_SETFD, 0) == -1)
208102c98c6Srzalamena 			fatal("fcntl");
2094e840e7aSrzalamena 
2104e840e7aSrzalamena 		execvp(argv[0], nargv);
2114e840e7aSrzalamena 		fatal("%s: execvp", __func__);
2124e840e7aSrzalamena 		break;
2134e840e7aSrzalamena 
2144e840e7aSrzalamena 	default:
2154e840e7aSrzalamena 		/* Close child's socket end. */
2164e840e7aSrzalamena 		close(cfd);
2174e840e7aSrzalamena 		break;
2184e840e7aSrzalamena 	}
2194e840e7aSrzalamena 
2204e840e7aSrzalamena 	free(nargv);
2214e840e7aSrzalamena 	return (pid);
2224e840e7aSrzalamena }
2234e840e7aSrzalamena 
2244e840e7aSrzalamena int
sanitize_argv(int * argc,char *** argv)2254e840e7aSrzalamena sanitize_argv(int *argc, char ***argv)
2264e840e7aSrzalamena {
2274e840e7aSrzalamena 	char		**nargv;
2284e840e7aSrzalamena 	int		  nargc;
2294e840e7aSrzalamena 	int		  i;
2304e840e7aSrzalamena 
2314e840e7aSrzalamena 	/*
2324e840e7aSrzalamena 	 * We need at least three arguments:
2334e840e7aSrzalamena 	 * Example: '/usr/sbin/ntpd' '-P' 'foobar'.
2344e840e7aSrzalamena 	 */
2354e840e7aSrzalamena 	if (*argc < 3)
2364e840e7aSrzalamena 		return (-1);
2374e840e7aSrzalamena 
2384e840e7aSrzalamena 	*argc -= 2;
2394e840e7aSrzalamena 
2404e840e7aSrzalamena 	/* Allocate new arguments vector and copy pointers. */
2414e840e7aSrzalamena 	nargv = calloc((*argc) + 1, sizeof(char *));
2424e840e7aSrzalamena 	if (nargv == NULL)
2434e840e7aSrzalamena 		return (-1);
2444e840e7aSrzalamena 
2454e840e7aSrzalamena 	nargc = 0;
2464e840e7aSrzalamena 	nargv[nargc++] = (*argv)[0];
2474e840e7aSrzalamena 	for (i = 1; i < *argc; i++)
2484e840e7aSrzalamena 		nargv[nargc++] = (*argv)[i + 2];
2494e840e7aSrzalamena 
2504e840e7aSrzalamena 	nargv[nargc] = NULL;
2514e840e7aSrzalamena 	*argv = nargv;
2524e840e7aSrzalamena 	return (0);
2534e840e7aSrzalamena }
254