xref: /openbsd-src/usr.sbin/ntpd/util.c (revision 897fc685943471cf985a0fe38ba076ea6fe74fa5)
1 /*	$OpenBSD: util.c,v 1.24 2017/03/01 00:56:30 gsoares 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	ret;
90 
91 	lfp.int_partl = ntohl(lfp.int_partl);
92 	lfp.fractionl = ntohl(lfp.fractionl);
93 
94 	ret = (double)(lfp.int_partl) + ((double)lfp.fractionl / UINT_MAX);
95 
96 	return (ret);
97 }
98 
99 struct l_fixedpt
100 d_to_lfp(double d)
101 {
102 	struct l_fixedpt	lfp;
103 
104 	lfp.int_partl = htonl((u_int32_t)d);
105 	lfp.fractionl = htonl((u_int32_t)((d - (u_int32_t)d) * UINT_MAX));
106 
107 	return (lfp);
108 }
109 
110 double
111 sfp_to_d(struct s_fixedpt sfp)
112 {
113 	double	ret;
114 
115 	sfp.int_parts = ntohs(sfp.int_parts);
116 	sfp.fractions = ntohs(sfp.fractions);
117 
118 	ret = (double)(sfp.int_parts) + ((double)sfp.fractions / USHRT_MAX);
119 
120 	return (ret);
121 }
122 
123 struct s_fixedpt
124 d_to_sfp(double d)
125 {
126 	struct s_fixedpt	sfp;
127 
128 	sfp.int_parts = htons((u_int16_t)d);
129 	sfp.fractions = htons((u_int16_t)((d - (u_int16_t)d) * USHRT_MAX));
130 
131 	return (sfp);
132 }
133 
134 char *
135 print_rtable(int r)
136 {
137 	static char b[11];
138 
139 	b[0] = 0;
140 	if (r > 0)
141 		snprintf(b, sizeof(b), "rtable %d", r);
142 
143 	return (b);
144 }
145 
146 const char *
147 log_sockaddr(struct sockaddr *sa)
148 {
149 	static char	buf[NI_MAXHOST];
150 
151 	if (getnameinfo(sa, SA_LEN(sa), buf, sizeof(buf), NULL, 0,
152 	    NI_NUMERICHOST))
153 		return ("(unknown)");
154 	else
155 		return (buf);
156 }
157 
158 pid_t
159 start_child(char *pname, int cfd, int argc, char **argv)
160 {
161 	char		**nargv;
162 	int		  nargc, i;
163 	pid_t		  pid;
164 
165 	/* Prepare the child process new argv. */
166 	nargv = calloc(argc + 3, sizeof(char *));
167 	if (nargv == NULL)
168 		fatal("%s: calloc", __func__);
169 
170 	/* Copy the program name first. */
171 	nargc = 0;
172 	nargv[nargc++] = argv[0];
173 
174 	/* Set the process name and copy the original args. */
175 	nargv[nargc++] = "-P";
176 	nargv[nargc++] = pname;
177 	for (i = 1; i < argc; i++)
178 		nargv[nargc++] = argv[i];
179 
180 	nargv[nargc] = NULL;
181 
182 	switch (pid = fork()) {
183 	case -1:
184 		fatal("%s: fork", __func__);
185 		break;
186 	case 0:
187 		/* Prepare the parent socket and execute. */
188 		if (cfd != PARENT_SOCK_FILENO) {
189 			if (dup2(cfd, PARENT_SOCK_FILENO) == -1)
190 				fatal("dup2");
191 		} else if (fcntl(cfd, F_SETFD, 0) == -1)
192 			fatal("fcntl");
193 
194 		execvp(argv[0], nargv);
195 		fatal("%s: execvp", __func__);
196 		break;
197 
198 	default:
199 		/* Close child's socket end. */
200 		close(cfd);
201 		break;
202 	}
203 
204 	free(nargv);
205 	return (pid);
206 }
207 
208 int
209 sanitize_argv(int *argc, char ***argv)
210 {
211 	char		**nargv;
212 	int		  nargc;
213 	int		  i;
214 
215 	/*
216 	 * We need at least three arguments:
217 	 * Example: '/usr/sbin/ntpd' '-P' 'foobar'.
218 	 */
219 	if (*argc < 3)
220 		return (-1);
221 
222 	*argc -= 2;
223 
224 	/* Allocate new arguments vector and copy pointers. */
225 	nargv = calloc((*argc) + 1, sizeof(char *));
226 	if (nargv == NULL)
227 		return (-1);
228 
229 	nargc = 0;
230 	nargv[nargc++] = (*argv)[0];
231 	for (i = 1; i < *argc; i++)
232 		nargv[nargc++] = (*argv)[i + 2];
233 
234 	nargv[nargc] = NULL;
235 	*argv = nargv;
236 	return (0);
237 }
238