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>
25 #include "wpa_debug.h"
29 static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
31 #define ALLOC_MAGIC 0xa84ef1b2
32 #define FREED_MAGIC 0x67fd487a
34 struct os_alloc_trace {
41 #endif /* WPA_TRACE */
44 void os_sleep(os_time_t sec, os_time_t usec)
53 int os_get_time(struct os_time *t)
57 res = gettimeofday(&tv, NULL);
64 int os_get_reltime(struct os_reltime *t)
66 #if defined(CLOCK_BOOTTIME)
67 static clockid_t clock_id = CLOCK_BOOTTIME;
68 #elif defined(CLOCK_MONOTONIC)
69 static clockid_t clock_id = CLOCK_MONOTONIC;
71 static clockid_t clock_id = CLOCK_REALTIME;
77 res = clock_gettime(clock_id, &ts);
80 t->usec = ts.tv_nsec / 1000;
86 clock_id = CLOCK_MONOTONIC;
89 #ifdef CLOCK_MONOTONIC
91 clock_id = CLOCK_REALTIME;
101 int os_mktime(int year, int month, int day, int hour, int min, int sec,
105 time_t t_local, t1, t2;
108 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
109 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
113 memset(&tm, 0, sizeof(tm));
114 tm.tm_year = year - 1900;
115 tm.tm_mon = month - 1;
121 t_local = mktime(&tm);
123 /* figure out offset to UTC */
124 tm1 = localtime(&t_local);
127 tm1 = gmtime(&t_local);
136 *t = (os_time_t) t_local - tz_offset;
141 int os_gmtime(os_time_t t, struct os_tm *tm)
149 tm->sec = tm2->tm_sec;
150 tm->min = tm2->tm_min;
151 tm->hour = tm2->tm_hour;
152 tm->day = tm2->tm_mday;
153 tm->month = tm2->tm_mon + 1;
154 tm->year = tm2->tm_year + 1900;
161 static int os_daemon(int nochdir, int noclose)
168 devnull = open("/dev/null", O_RDWR);
172 if (dup2(devnull, STDIN_FILENO) < 0) {
177 if (dup2(devnull, STDOUT_FILENO) < 0) {
182 if (dup2(devnull, STDERR_FILENO) < 0) {
189 #else /* __APPLE__ */
190 #define os_daemon daemon
191 #endif /* __APPLE__ */
198 #endif /* __FreeBSD__ */
200 int os_daemonize(const char *pid_file)
202 #if defined(__uClinux__) || defined(__sun__)
204 #else /* defined(__uClinux__) || defined(__sun__) */
209 pfh = pidfile_open(pid_file, 0600, &otherpid);
211 if (errno == EEXIST) {
212 errx(1, "Daemon already running, pid: %jd.",
215 warn("Cannot open or create pidfile.");
217 #endif /* __FreeBSD__ */
219 if (os_daemon(0, 0)) {
223 #endif /* __FreeBSD__ */
229 FILE *f = fopen(pid_file, "w");
231 fprintf(f, "%u\n", getpid());
235 #else /* __FreeBSD__ */
237 #endif /* __FreeBSD__ */
240 #endif /* defined(__uClinux__) || defined(__sun__) */
244 void os_daemonize_terminate(const char *pid_file)
251 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");
446 void * os_zalloc(size_t size)
448 return calloc(1, size);
450 #endif /* WPA_TRACE */
453 size_t os_strlcpy(char *dest, const char *src, size_t siz)
459 /* Copy string up to the maximum size of the dest buffer */
460 while (--left != 0) {
461 if ((*dest++ = *s++) == '\0')
467 /* Not enough room for the string; force NUL-termination */
471 ; /* determine total src string length */
478 int os_memcmp_const(const void *a, const void *b, size_t len)
485 for (res = 0, i = 0; i < len; i++)
486 res |= aa[i] ^ bb[i];
494 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
495 char wpa_trace_fail_func[256] = { 0 };
496 unsigned int wpa_trace_fail_after;
498 static int testing_fail_alloc(void)
500 const char *func[WPA_TRACE_LEN];
505 if (!wpa_trace_fail_after)
508 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
510 if (i < res && os_strcmp(func[i], __func__) == 0)
512 if (i < res && os_strcmp(func[i], "os_malloc") == 0)
514 if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
516 if (i < res && os_strcmp(func[i], "os_calloc") == 0)
518 if (i < res && os_strcmp(func[i], "os_realloc") == 0)
520 if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
522 if (i < res && os_strcmp(func[i], "os_strdup") == 0)
525 pos = wpa_trace_fail_func;
535 } else if (*pos == '?') {
539 next = os_strchr(pos, ';');
543 len = os_strlen(pos);
544 if (os_memcmp(pos, func[i], len) != 0) {
565 wpa_trace_fail_after--;
566 if (wpa_trace_fail_after == 0) {
567 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
568 wpa_trace_fail_func);
569 for (i = 0; i < res; i++)
570 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
580 static inline int testing_fail_alloc(void)
586 void * os_malloc(size_t size)
588 struct os_alloc_trace *a;
590 if (testing_fail_alloc())
593 a = malloc(sizeof(*a) + size);
596 a->magic = ALLOC_MAGIC;
597 dl_list_add(&alloc_list, &a->list);
604 void * os_realloc(void *ptr, size_t size)
606 struct os_alloc_trace *a;
611 return os_malloc(size);
613 a = (struct os_alloc_trace *) ptr - 1;
614 if (a->magic != ALLOC_MAGIC) {
615 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
617 a->magic == FREED_MAGIC ? " (already freed)" : "");
618 wpa_trace_show("Invalid os_realloc() call");
627 os_memcpy(n, a + 1, copy_len);
633 void os_free(void *ptr)
635 struct os_alloc_trace *a;
639 a = (struct os_alloc_trace *) ptr - 1;
640 if (a->magic != ALLOC_MAGIC) {
641 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
643 a->magic == FREED_MAGIC ? " (already freed)" : "");
644 wpa_trace_show("Invalid os_free() call");
647 dl_list_del(&a->list);
648 a->magic = FREED_MAGIC;
650 wpa_trace_check_ref(ptr);
655 void * os_zalloc(size_t size)
657 void *ptr = os_malloc(size);
659 os_memset(ptr, 0, size);
664 char * os_strdup(const char *s)
669 d = os_malloc(len + 1);
672 os_memcpy(d, s, len);
677 #endif /* WPA_TRACE */
680 int os_exec(const char *program, const char *arg, int wait_completion)
692 /* run the external command in the child process */
693 const int MAX_ARG = 30;
694 char *_program, *_arg, *pos;
695 char *argv[MAX_ARG + 1];
698 _program = os_strdup(program);
699 _arg = os_strdup(arg);
705 while (i < MAX_ARG && pos && *pos) {
711 pos = os_strchr(pos, ' ');
717 execv(program, argv);
725 if (wait_completion) {
726 /* wait for the child process to complete in the parent */
727 waitpid(pid, &pid_status, 0);