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