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