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