xref: /netbsd-src/usr.bin/rump_dhcpclient/common.c (revision e963960681e924e34192f4aace9206aa70d13d8d)
1*e9639606Spooka /*
2*e9639606Spooka  * dhcpcd - DHCP client daemon
3*e9639606Spooka  * Copyright (c) 2006-2009 Roy Marples <roy@marples.name>
4*e9639606Spooka  * All rights reserved
5*e9639606Spooka 
6*e9639606Spooka  * Redistribution and use in source and binary forms, with or without
7*e9639606Spooka  * modification, are permitted provided that the following conditions
8*e9639606Spooka  * are met:
9*e9639606Spooka  * 1. Redistributions of source code must retain the above copyright
10*e9639606Spooka  *    notice, this list of conditions and the following disclaimer.
11*e9639606Spooka  * 2. Redistributions in binary form must reproduce the above copyright
12*e9639606Spooka  *    notice, this list of conditions and the following disclaimer in the
13*e9639606Spooka  *    documentation and/or other materials provided with the distribution.
14*e9639606Spooka  *
15*e9639606Spooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*e9639606Spooka  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*e9639606Spooka  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*e9639606Spooka  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*e9639606Spooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*e9639606Spooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*e9639606Spooka  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*e9639606Spooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*e9639606Spooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*e9639606Spooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*e9639606Spooka  * SUCH DAMAGE.
26*e9639606Spooka  */
27*e9639606Spooka 
28*e9639606Spooka /* Needed define to get at getline for glibc and FreeBSD */
29*e9639606Spooka #ifndef _GNU_SOURCE
30*e9639606Spooka #  define _GNU_SOURCE
31*e9639606Spooka #endif
32*e9639606Spooka 
33*e9639606Spooka #include <sys/cdefs.h>
34*e9639606Spooka 
35*e9639606Spooka #ifdef __APPLE__
36*e9639606Spooka #  include <mach/mach_time.h>
37*e9639606Spooka #  include <mach/kern_return.h>
38*e9639606Spooka #endif
39*e9639606Spooka 
40*e9639606Spooka #include <sys/param.h>
41*e9639606Spooka #include <sys/time.h>
42*e9639606Spooka 
43*e9639606Spooka #include <errno.h>
44*e9639606Spooka #include <fcntl.h>
45*e9639606Spooka #include <limits.h>
46*e9639606Spooka #ifdef BSD
47*e9639606Spooka #  include <paths.h>
48*e9639606Spooka #endif
49*e9639606Spooka #include <stdint.h>
50*e9639606Spooka #include <stdio.h>
51*e9639606Spooka #include <stdlib.h>
52*e9639606Spooka #include <string.h>
53*e9639606Spooka #include <time.h>
54*e9639606Spooka #include <unistd.h>
55*e9639606Spooka 
56*e9639606Spooka #include "common.h"
57*e9639606Spooka 
58*e9639606Spooka #ifndef _PATH_DEVNULL
59*e9639606Spooka #  define _PATH_DEVNULL "/dev/null"
60*e9639606Spooka #endif
61*e9639606Spooka 
62*e9639606Spooka int clock_monotonic;
63*e9639606Spooka #ifdef DEBUG_MEMORY
64*e9639606Spooka static char lbuf_set;
65*e9639606Spooka #endif
66*e9639606Spooka 
67*e9639606Spooka #ifdef DEBUG_MEMORY
68*e9639606Spooka static void
free_lbuf(void)69*e9639606Spooka free_lbuf(void)
70*e9639606Spooka {
71*e9639606Spooka 	free(lbuf);
72*e9639606Spooka 	lbuf = NULL;
73*e9639606Spooka }
74*e9639606Spooka #endif
75*e9639606Spooka 
76*e9639606Spooka /* Handy function to get the time.
77*e9639606Spooka  * We only care about time advancements, not the actual time itself
78*e9639606Spooka  * Which is why we use CLOCK_MONOTONIC, but it is not available on all
79*e9639606Spooka  * platforms.
80*e9639606Spooka  */
81*e9639606Spooka #define NO_MONOTONIC "host does not support a monotonic clock - timing can skew"
82*e9639606Spooka int
get_monotonic(struct timeval * tp)83*e9639606Spooka get_monotonic(struct timeval *tp)
84*e9639606Spooka {
85*e9639606Spooka 	static int posix_clock_set = 0;
86*e9639606Spooka #if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
87*e9639606Spooka 	struct timespec ts;
88*e9639606Spooka 	static clockid_t posix_clock;
89*e9639606Spooka 
90*e9639606Spooka 	if (!posix_clock_set) {
91*e9639606Spooka 		if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
92*e9639606Spooka 			posix_clock = CLOCK_MONOTONIC;
93*e9639606Spooka 			clock_monotonic = posix_clock_set = 1;
94*e9639606Spooka 		}
95*e9639606Spooka 	}
96*e9639606Spooka 
97*e9639606Spooka 	if (clock_monotonic) {
98*e9639606Spooka 		if (clock_gettime(posix_clock, &ts) == 0) {
99*e9639606Spooka 			tp->tv_sec = ts.tv_sec;
100*e9639606Spooka 			tp->tv_usec = ts.tv_nsec / 1000;
101*e9639606Spooka 			return 0;
102*e9639606Spooka 		}
103*e9639606Spooka 	}
104*e9639606Spooka #elif defined(__APPLE__)
105*e9639606Spooka #define NSEC_PER_SEC 1000000000
106*e9639606Spooka 	/* We can use mach kernel functions here.
107*e9639606Spooka 	 * This is crap though - why can't they implement clock_gettime?*/
108*e9639606Spooka 	static struct mach_timebase_info info = { 0, 0 };
109*e9639606Spooka 	static double factor = 0.0;
110*e9639606Spooka 	uint64_t nano;
111*e9639606Spooka 	long rem;
112*e9639606Spooka 
113*e9639606Spooka 	if (!posix_clock_set) {
114*e9639606Spooka 		if (mach_timebase_info(&info) == KERN_SUCCESS) {
115*e9639606Spooka 			factor = (double)info.numer / (double)info.denom;
116*e9639606Spooka 			clock_monotonic = posix_clock_set = 1;
117*e9639606Spooka 		}
118*e9639606Spooka 	}
119*e9639606Spooka 	if (clock_monotonic) {
120*e9639606Spooka 		nano = mach_absolute_time();
121*e9639606Spooka 		if ((info.denom != 1 || info.numer != 1) && factor != 0.0)
122*e9639606Spooka 			nano *= factor;
123*e9639606Spooka 		tp->tv_sec = nano / NSEC_PER_SEC;
124*e9639606Spooka 		rem = nano % NSEC_PER_SEC;
125*e9639606Spooka 		if (rem < 0) {
126*e9639606Spooka 			tp->tv_sec--;
127*e9639606Spooka 			rem += NSEC_PER_SEC;
128*e9639606Spooka 		}
129*e9639606Spooka 		tp->tv_usec = rem / 1000;
130*e9639606Spooka 		return 0;
131*e9639606Spooka 	}
132*e9639606Spooka #endif
133*e9639606Spooka 
134*e9639606Spooka 	/* Something above failed, so fall back to gettimeofday */
135*e9639606Spooka 	if (!posix_clock_set) {
136*e9639606Spooka 		posix_clock_set = 1;
137*e9639606Spooka 	}
138*e9639606Spooka 	return gettimeofday(tp, NULL);
139*e9639606Spooka }
140*e9639606Spooka 
141*e9639606Spooka time_t
uptime(void)142*e9639606Spooka uptime(void)
143*e9639606Spooka {
144*e9639606Spooka 	struct timeval tv;
145*e9639606Spooka 
146*e9639606Spooka 	if (get_monotonic(&tv) == -1)
147*e9639606Spooka 		return -1;
148*e9639606Spooka 	return tv.tv_sec;
149*e9639606Spooka }
150*e9639606Spooka 
151*e9639606Spooka void *
xmalloc(size_t s)152*e9639606Spooka xmalloc(size_t s)
153*e9639606Spooka {
154*e9639606Spooka 	void *value = malloc(s);
155*e9639606Spooka 
156*e9639606Spooka 	if (value != NULL)
157*e9639606Spooka 		return value;
158*e9639606Spooka 	abort();
159*e9639606Spooka 	/* NOTREACHED */
160*e9639606Spooka }
161*e9639606Spooka 
162*e9639606Spooka void *
xzalloc(size_t s)163*e9639606Spooka xzalloc(size_t s)
164*e9639606Spooka {
165*e9639606Spooka 	void *value = xmalloc(s);
166*e9639606Spooka 
167*e9639606Spooka 	memset(value, 0, s);
168*e9639606Spooka 	return value;
169*e9639606Spooka }
170*e9639606Spooka 
171*e9639606Spooka void *
xrealloc(void * ptr,size_t s)172*e9639606Spooka xrealloc(void *ptr, size_t s)
173*e9639606Spooka {
174*e9639606Spooka 	void *value = realloc(ptr, s);
175*e9639606Spooka 
176*e9639606Spooka 	if (value != NULL)
177*e9639606Spooka 		return value;
178*e9639606Spooka 	abort();
179*e9639606Spooka 	/* NOTREACHED */
180*e9639606Spooka }
181*e9639606Spooka 
182*e9639606Spooka char *
xstrdup(const char * str)183*e9639606Spooka xstrdup(const char *str)
184*e9639606Spooka {
185*e9639606Spooka 	char *value;
186*e9639606Spooka 
187*e9639606Spooka 	if (str == NULL)
188*e9639606Spooka 		return NULL;
189*e9639606Spooka 
190*e9639606Spooka 	if ((value = strdup(str)) != NULL)
191*e9639606Spooka 		return value;
192*e9639606Spooka 
193*e9639606Spooka 	abort();
194*e9639606Spooka 	/* NOTREACHED */
195*e9639606Spooka }
196