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