2 * OS specific functions for UNIX/POSIX systems
3 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
15 #include <sys/capability.h>
16 #include <sys/prctl.h>
17 #include <private/android_filesystem_config.h>
21 #include <CoreServices/CoreServices.h>
22 #include <mach/mach.h>
23 #include <mach/mach_time.h>
31 #include "wpa_debug.h"
35 static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
37 #define ALLOC_MAGIC 0xa84ef1b2
38 #define FREED_MAGIC 0x67fd487a
40 struct os_alloc_trace {
45 } __attribute__((aligned(16)));
47 #endif /* WPA_TRACE */
50 void os_sleep(os_time_t sec, os_time_t usec)
59 int os_get_time(struct os_time *t)
63 res = gettimeofday(&tv, NULL);
70 int os_get_reltime(struct os_reltime *t)
73 #if defined(CLOCK_BOOTTIME)
74 static clockid_t clock_id = CLOCK_BOOTTIME;
75 #elif defined(CLOCK_MONOTONIC)
76 static clockid_t clock_id = CLOCK_MONOTONIC;
78 static clockid_t clock_id = CLOCK_REALTIME;
84 res = clock_gettime(clock_id, &ts);
87 t->usec = ts.tv_nsec / 1000;
93 clock_id = CLOCK_MONOTONIC;
96 #ifdef CLOCK_MONOTONIC
98 clock_id = CLOCK_REALTIME;
106 uint64_t abstime, nano;
107 static mach_timebase_info_data_t info = { 0, 0 };
110 if (mach_timebase_info(&info) != KERN_SUCCESS)
114 abstime = mach_absolute_time();
115 nano = (abstime * info.numer) / info.denom;
117 t->sec = nano / NSEC_PER_SEC;
118 t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
121 #endif /* __MACH__ */
125 int os_mktime(int year, int month, int day, int hour, int min, int sec,
129 time_t t_local, t1, t2;
132 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
133 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
137 memset(&tm, 0, sizeof(tm));
138 tm.tm_year = year - 1900;
139 tm.tm_mon = month - 1;
145 t_local = mktime(&tm);
147 /* figure out offset to UTC */
148 tm1 = localtime(&t_local);
151 tm1 = gmtime(&t_local);
160 *t = (os_time_t) t_local - tz_offset;
165 int os_gmtime(os_time_t t, struct os_tm *tm)
173 tm->sec = tm2->tm_sec;
174 tm->min = tm2->tm_min;
175 tm->hour = tm2->tm_hour;
176 tm->day = tm2->tm_mday;
177 tm->month = tm2->tm_mon + 1;
178 tm->year = tm2->tm_year + 1900;
185 static int os_daemon(int nochdir, int noclose)
192 devnull = open("/dev/null", O_RDWR);
196 if (dup2(devnull, STDIN_FILENO) < 0) {
201 if (dup2(devnull, STDOUT_FILENO) < 0) {
206 if (dup2(devnull, STDERR_FILENO) < 0) {
213 #else /* __APPLE__ */
214 #define os_daemon daemon
215 #endif /* __APPLE__ */
222 #endif /* __FreeBSD__ */
224 int os_daemonize(const char *pid_file)
226 #if defined(__uClinux__) || defined(__sun__)
228 #else /* defined(__uClinux__) || defined(__sun__) */
233 pfh = pidfile_open(pid_file, 0600, &otherpid);
235 if (errno == EEXIST) {
236 errx(1, "Daemon already running, pid: %jd.",
239 warn("Cannot open or create pidfile.");
241 #endif /* __FreeBSD__ */
243 if (os_daemon(0, 0)) {
247 #endif /* __FreeBSD__ */
253 FILE *f = fopen(pid_file, "w");
255 fprintf(f, "%u\n", getpid());
259 #else /* __FreeBSD__ */
261 #endif /* __FreeBSD__ */
264 #endif /* defined(__uClinux__) || defined(__sun__) */
268 void os_daemonize_terminate(const char *pid_file)
275 int os_get_random(unsigned char *buf, size_t len)
283 f = fopen("/dev/urandom", "rb");
285 printf("Could not open /dev/urandom.\n");
289 rc = fread(buf, 1, len, f);
292 return rc != len ? -1 : 0;
296 unsigned long os_random(void)
302 char * os_rel2abs_path(const char *rel_path)
304 char *buf = NULL, *cwd, *ret;
305 size_t len = 128, cwd_len, rel_len, ret_len;
311 if (rel_path[0] == '/')
312 return os_strdup(rel_path);
315 buf = os_malloc(len);
318 cwd = getcwd(buf, len);
322 if (last_errno != ERANGE)
333 cwd_len = os_strlen(cwd);
334 rel_len = os_strlen(rel_path);
335 ret_len = cwd_len + 1 + rel_len + 1;
336 ret = os_malloc(ret_len);
338 os_memcpy(ret, cwd, cwd_len);
340 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
341 ret[ret_len - 1] = '\0';
348 int os_program_init(void)
352 * We ignore errors here since errors are normal if we
353 * are already running as non-root.
355 #ifdef ANDROID_SETGROUPS_OVERRIDE
356 gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
357 #else /* ANDROID_SETGROUPS_OVERRIDE */
358 gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
359 #endif /* ANDROID_SETGROUPS_OVERRIDE */
360 struct __user_cap_header_struct header;
361 struct __user_cap_data_struct cap;
363 setgroups(ARRAY_SIZE(groups), groups);
365 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
370 header.version = _LINUX_CAPABILITY_VERSION;
372 cap.effective = cap.permitted =
373 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
375 capset(&header, &cap);
382 void os_program_deinit(void)
385 struct os_alloc_trace *a;
386 unsigned long total = 0;
387 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
389 if (a->magic != ALLOC_MAGIC) {
390 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
392 a, a->magic, (unsigned long) a->len);
395 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
396 a, (unsigned long) a->len);
397 wpa_trace_dump("memleak", a);
400 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
401 (unsigned long) total);
402 #endif /* WPA_TRACE */
406 int os_setenv(const char *name, const char *value, int overwrite)
408 return setenv(name, value, overwrite);
412 int os_unsetenv(const char *name)
414 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
419 return unsetenv(name);
424 char * os_readfile(const char *name, size_t *len)
430 f = fopen(name, "rb");
434 if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
439 if (fseek(f, 0, SEEK_SET) < 0) {
444 buf = os_malloc(*len);
450 if (fread(buf, 1, *len, f) != *len) {
462 int os_file_exists(const char *fname)
464 FILE *f = fopen(fname, "rb");
472 int os_fdatasync(FILE *stream)
474 if (!fflush(stream)) {
476 return fdatasync(fileno(stream));
477 #else /* !__linux__ */
479 /* OS X does not implement fdatasync(). */
480 return fcntl(fileno(stream), F_FULLFSYNC);
481 #else /* F_FULLFSYNC */
482 return fsync(fileno(stream));
483 #endif /* F_FULLFSYNC */
484 #endif /* __linux__ */
492 void * os_zalloc(size_t size)
494 return calloc(1, size);
496 #endif /* WPA_TRACE */
499 size_t os_strlcpy(char *dest, const char *src, size_t siz)
505 /* Copy string up to the maximum size of the dest buffer */
506 while (--left != 0) {
507 if ((*dest++ = *s++) == '\0')
513 /* Not enough room for the string; force NUL-termination */
517 ; /* determine total src string length */
524 int os_memcmp_const(const void *a, const void *b, size_t len)
531 for (res = 0, i = 0; i < len; i++)
532 res |= aa[i] ^ bb[i];
540 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
541 char wpa_trace_fail_func[256] = { 0 };
542 unsigned int wpa_trace_fail_after;
544 static int testing_fail_alloc(void)
546 const char *func[WPA_TRACE_LEN];
551 if (!wpa_trace_fail_after)
554 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
556 if (i < res && os_strcmp(func[i], __func__) == 0)
558 if (i < res && os_strcmp(func[i], "os_malloc") == 0)
560 if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
562 if (i < res && os_strcmp(func[i], "os_calloc") == 0)
564 if (i < res && os_strcmp(func[i], "os_realloc") == 0)
566 if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
568 if (i < res && os_strcmp(func[i], "os_strdup") == 0)
571 pos = wpa_trace_fail_func;
581 } else if (*pos == '?') {
585 next = os_strchr(pos, ';');
589 len = os_strlen(pos);
590 if (os_memcmp(pos, func[i], len) != 0) {
611 wpa_trace_fail_after--;
612 if (wpa_trace_fail_after == 0) {
613 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
614 wpa_trace_fail_func);
615 for (i = 0; i < res; i++)
616 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
625 char wpa_trace_test_fail_func[256] = { 0 };
626 unsigned int wpa_trace_test_fail_after;
628 int testing_test_fail(void)
630 const char *func[WPA_TRACE_LEN];
635 if (!wpa_trace_test_fail_after)
638 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
640 if (i < res && os_strcmp(func[i], __func__) == 0)
643 pos = wpa_trace_test_fail_func;
653 } else if (*pos == '?') {
657 next = os_strchr(pos, ';');
661 len = os_strlen(pos);
662 if (os_memcmp(pos, func[i], len) != 0) {
683 wpa_trace_test_fail_after--;
684 if (wpa_trace_test_fail_after == 0) {
685 wpa_printf(MSG_INFO, "TESTING: fail at %s",
686 wpa_trace_test_fail_func);
687 for (i = 0; i < res; i++)
688 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
698 static inline int testing_fail_alloc(void)
704 void * os_malloc(size_t size)
706 struct os_alloc_trace *a;
708 if (testing_fail_alloc())
711 a = malloc(sizeof(*a) + size);
714 a->magic = ALLOC_MAGIC;
715 dl_list_add(&alloc_list, &a->list);
722 void * os_realloc(void *ptr, size_t size)
724 struct os_alloc_trace *a;
729 return os_malloc(size);
731 a = (struct os_alloc_trace *) ptr - 1;
732 if (a->magic != ALLOC_MAGIC) {
733 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
735 a->magic == FREED_MAGIC ? " (already freed)" : "");
736 wpa_trace_show("Invalid os_realloc() call");
745 os_memcpy(n, a + 1, copy_len);
751 void os_free(void *ptr)
753 struct os_alloc_trace *a;
757 a = (struct os_alloc_trace *) ptr - 1;
758 if (a->magic != ALLOC_MAGIC) {
759 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
761 a->magic == FREED_MAGIC ? " (already freed)" : "");
762 wpa_trace_show("Invalid os_free() call");
765 dl_list_del(&a->list);
766 a->magic = FREED_MAGIC;
768 wpa_trace_check_ref(ptr);
773 void * os_zalloc(size_t size)
775 void *ptr = os_malloc(size);
777 os_memset(ptr, 0, size);
782 char * os_strdup(const char *s)
787 d = os_malloc(len + 1);
790 os_memcpy(d, s, len);
795 #endif /* WPA_TRACE */
798 int os_exec(const char *program, const char *arg, int wait_completion)
810 /* run the external command in the child process */
811 const int MAX_ARG = 30;
812 char *_program, *_arg, *pos;
813 char *argv[MAX_ARG + 1];
816 _program = os_strdup(program);
817 _arg = os_strdup(arg);
823 while (i < MAX_ARG && pos && *pos) {
829 pos = os_strchr(pos, ' ');
835 execv(program, argv);
843 if (wait_completion) {
844 /* wait for the child process to complete in the parent */
845 waitpid(pid, &pid_status, 0);