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