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