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