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__ */
218 int os_daemonize(const char *pid_file)
220 #if defined(__uClinux__) || defined(__sun__)
222 #else /* defined(__uClinux__) || defined(__sun__) */
223 if (os_daemon(0, 0)) {
229 FILE *f = fopen(pid_file, "w");
231 fprintf(f, "%u\n", getpid());
237 #endif /* defined(__uClinux__) || defined(__sun__) */
241 void os_daemonize_terminate(const char *pid_file)
248 int os_get_random(unsigned char *buf, size_t len)
256 f = fopen("/dev/urandom", "rb");
258 printf("Could not open /dev/urandom.\n");
262 rc = fread(buf, 1, len, f);
265 return rc != len ? -1 : 0;
269 unsigned long os_random(void)
275 char * os_rel2abs_path(const char *rel_path)
277 char *buf = NULL, *cwd, *ret;
278 size_t len = 128, cwd_len, rel_len, ret_len;
284 if (rel_path[0] == '/')
285 return os_strdup(rel_path);
288 buf = os_malloc(len);
291 cwd = getcwd(buf, len);
295 if (last_errno != ERANGE)
306 cwd_len = os_strlen(cwd);
307 rel_len = os_strlen(rel_path);
308 ret_len = cwd_len + 1 + rel_len + 1;
309 ret = os_malloc(ret_len);
311 os_memcpy(ret, cwd, cwd_len);
313 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
314 ret[ret_len - 1] = '\0';
321 int os_program_init(void)
325 * We ignore errors here since errors are normal if we
326 * are already running as non-root.
328 #ifdef ANDROID_SETGROUPS_OVERRIDE
329 gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
330 #else /* ANDROID_SETGROUPS_OVERRIDE */
331 gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
332 #endif /* ANDROID_SETGROUPS_OVERRIDE */
333 struct __user_cap_header_struct header;
334 struct __user_cap_data_struct cap;
336 setgroups(ARRAY_SIZE(groups), groups);
338 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
343 header.version = _LINUX_CAPABILITY_VERSION;
345 cap.effective = cap.permitted =
346 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
348 capset(&header, &cap);
355 void os_program_deinit(void)
358 struct os_alloc_trace *a;
359 unsigned long total = 0;
360 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
362 if (a->magic != ALLOC_MAGIC) {
363 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
365 a, a->magic, (unsigned long) a->len);
368 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
369 a, (unsigned long) a->len);
370 wpa_trace_dump("memleak", a);
373 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
374 (unsigned long) total);
375 #endif /* WPA_TRACE */
379 int os_setenv(const char *name, const char *value, int overwrite)
381 return setenv(name, value, overwrite);
385 int os_unsetenv(const char *name)
387 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
392 return unsetenv(name);
397 char * os_readfile(const char *name, size_t *len)
403 f = fopen(name, "rb");
407 if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
412 if (fseek(f, 0, SEEK_SET) < 0) {
417 buf = os_malloc(*len);
423 if (fread(buf, 1, *len, f) != *len) {
435 int os_file_exists(const char *fname)
437 FILE *f = fopen(fname, "rb");
445 int os_fdatasync(FILE *stream)
447 if (!fflush(stream)) {
449 return fdatasync(fileno(stream));
452 /* OS X does not implement fdatasync(). */
453 return fcntl(fileno(stream), F_FULLFSYNC);
454 #else /* F_FULLFSYNC */
455 #error Neither fdatasync nor F_FULLSYNC are defined
456 #endif /* F_FULLFSYNC */
457 #endif /* __MACH__ */
465 void * os_zalloc(size_t size)
467 return calloc(1, size);
469 #endif /* WPA_TRACE */
472 size_t os_strlcpy(char *dest, const char *src, size_t siz)
478 /* Copy string up to the maximum size of the dest buffer */
479 while (--left != 0) {
480 if ((*dest++ = *s++) == '\0')
486 /* Not enough room for the string; force NUL-termination */
490 ; /* determine total src string length */
497 int os_memcmp_const(const void *a, const void *b, size_t len)
504 for (res = 0, i = 0; i < len; i++)
505 res |= aa[i] ^ bb[i];
513 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
514 char wpa_trace_fail_func[256] = { 0 };
515 unsigned int wpa_trace_fail_after;
517 static int testing_fail_alloc(void)
519 const char *func[WPA_TRACE_LEN];
524 if (!wpa_trace_fail_after)
527 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
529 if (i < res && os_strcmp(func[i], __func__) == 0)
531 if (i < res && os_strcmp(func[i], "os_malloc") == 0)
533 if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
535 if (i < res && os_strcmp(func[i], "os_calloc") == 0)
537 if (i < res && os_strcmp(func[i], "os_realloc") == 0)
539 if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
541 if (i < res && os_strcmp(func[i], "os_strdup") == 0)
544 pos = wpa_trace_fail_func;
554 } else if (*pos == '?') {
558 next = os_strchr(pos, ';');
562 len = os_strlen(pos);
563 if (os_memcmp(pos, func[i], len) != 0) {
584 wpa_trace_fail_after--;
585 if (wpa_trace_fail_after == 0) {
586 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
587 wpa_trace_fail_func);
588 for (i = 0; i < res; i++)
589 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
598 char wpa_trace_test_fail_func[256] = { 0 };
599 unsigned int wpa_trace_test_fail_after;
601 int testing_test_fail(void)
603 const char *func[WPA_TRACE_LEN];
608 if (!wpa_trace_test_fail_after)
611 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
613 if (i < res && os_strcmp(func[i], __func__) == 0)
616 pos = wpa_trace_test_fail_func;
626 } else if (*pos == '?') {
630 next = os_strchr(pos, ';');
634 len = os_strlen(pos);
635 if (os_memcmp(pos, func[i], len) != 0) {
656 wpa_trace_test_fail_after--;
657 if (wpa_trace_test_fail_after == 0) {
658 wpa_printf(MSG_INFO, "TESTING: fail at %s",
659 wpa_trace_test_fail_func);
660 for (i = 0; i < res; i++)
661 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
671 static inline int testing_fail_alloc(void)
677 void * os_malloc(size_t size)
679 struct os_alloc_trace *a;
681 if (testing_fail_alloc())
684 a = malloc(sizeof(*a) + size);
687 a->magic = ALLOC_MAGIC;
688 dl_list_add(&alloc_list, &a->list);
695 void * os_realloc(void *ptr, size_t size)
697 struct os_alloc_trace *a;
702 return os_malloc(size);
704 a = (struct os_alloc_trace *) ptr - 1;
705 if (a->magic != ALLOC_MAGIC) {
706 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
708 a->magic == FREED_MAGIC ? " (already freed)" : "");
709 wpa_trace_show("Invalid os_realloc() call");
718 os_memcpy(n, a + 1, copy_len);
724 void os_free(void *ptr)
726 struct os_alloc_trace *a;
730 a = (struct os_alloc_trace *) ptr - 1;
731 if (a->magic != ALLOC_MAGIC) {
732 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
734 a->magic == FREED_MAGIC ? " (already freed)" : "");
735 wpa_trace_show("Invalid os_free() call");
738 dl_list_del(&a->list);
739 a->magic = FREED_MAGIC;
741 wpa_trace_check_ref(ptr);
746 void * os_zalloc(size_t size)
748 void *ptr = os_malloc(size);
750 os_memset(ptr, 0, size);
755 char * os_strdup(const char *s)
760 d = os_malloc(len + 1);
763 os_memcpy(d, s, len);
768 #endif /* WPA_TRACE */
771 int os_exec(const char *program, const char *arg, int wait_completion)
783 /* run the external command in the child process */
784 const int MAX_ARG = 30;
785 char *_program, *_arg, *pos;
786 char *argv[MAX_ARG + 1];
789 _program = os_strdup(program);
790 _arg = os_strdup(arg);
796 while (i < MAX_ARG && pos && *pos) {
802 pos = os_strchr(pos, ' ');
808 execv(program, argv);
816 if (wait_completion) {
817 /* wait for the child process to complete in the parent */
818 waitpid(pid, &pid_status, 0);