16d49e1aeSJan Lentfer /* 2*3ff40c12SJohn Marino * OS specific functions for UNIX/POSIX systems 3*3ff40c12SJohn Marino * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> 46d49e1aeSJan Lentfer * 5*3ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license. 6*3ff40c12SJohn Marino * See README for more details. 76d49e1aeSJan Lentfer */ 86d49e1aeSJan Lentfer 96d49e1aeSJan Lentfer #include "includes.h" 106d49e1aeSJan Lentfer 11*3ff40c12SJohn Marino #include <time.h> 12*3ff40c12SJohn Marino 13*3ff40c12SJohn Marino #ifdef ANDROID 14*3ff40c12SJohn Marino #include <sys/capability.h> 15*3ff40c12SJohn Marino #include <linux/prctl.h> 16*3ff40c12SJohn Marino #include <private/android_filesystem_config.h> 17*3ff40c12SJohn Marino #endif /* ANDROID */ 18*3ff40c12SJohn Marino 196d49e1aeSJan Lentfer #include "os.h" 20*3ff40c12SJohn Marino #include "common.h" 21*3ff40c12SJohn Marino 22*3ff40c12SJohn Marino #ifdef WPA_TRACE 23*3ff40c12SJohn Marino 24*3ff40c12SJohn Marino #include "wpa_debug.h" 25*3ff40c12SJohn Marino #include "trace.h" 26*3ff40c12SJohn Marino #include "list.h" 27*3ff40c12SJohn Marino 28*3ff40c12SJohn Marino static struct dl_list alloc_list; 29*3ff40c12SJohn Marino 30*3ff40c12SJohn Marino #define ALLOC_MAGIC 0xa84ef1b2 31*3ff40c12SJohn Marino #define FREED_MAGIC 0x67fd487a 32*3ff40c12SJohn Marino 33*3ff40c12SJohn Marino struct os_alloc_trace { 34*3ff40c12SJohn Marino unsigned int magic; 35*3ff40c12SJohn Marino struct dl_list list; 36*3ff40c12SJohn Marino size_t len; 37*3ff40c12SJohn Marino WPA_TRACE_INFO 38*3ff40c12SJohn Marino }; 39*3ff40c12SJohn Marino 40*3ff40c12SJohn Marino #endif /* WPA_TRACE */ 41*3ff40c12SJohn Marino 426d49e1aeSJan Lentfer 436d49e1aeSJan Lentfer void os_sleep(os_time_t sec, os_time_t usec) 446d49e1aeSJan Lentfer { 456d49e1aeSJan Lentfer if (sec) 466d49e1aeSJan Lentfer sleep(sec); 476d49e1aeSJan Lentfer if (usec) 486d49e1aeSJan Lentfer usleep(usec); 496d49e1aeSJan Lentfer } 506d49e1aeSJan Lentfer 516d49e1aeSJan Lentfer 526d49e1aeSJan Lentfer int os_get_time(struct os_time *t) 536d49e1aeSJan Lentfer { 546d49e1aeSJan Lentfer int res; 556d49e1aeSJan Lentfer struct timeval tv; 566d49e1aeSJan Lentfer res = gettimeofday(&tv, NULL); 576d49e1aeSJan Lentfer t->sec = tv.tv_sec; 586d49e1aeSJan Lentfer t->usec = tv.tv_usec; 596d49e1aeSJan Lentfer return res; 606d49e1aeSJan Lentfer } 616d49e1aeSJan Lentfer 626d49e1aeSJan Lentfer 63*3ff40c12SJohn Marino int os_get_reltime(struct os_reltime *t) 64*3ff40c12SJohn Marino { 65*3ff40c12SJohn Marino #if defined(CLOCK_BOOTTIME) 66*3ff40c12SJohn Marino static clockid_t clock_id = CLOCK_BOOTTIME; 67*3ff40c12SJohn Marino #elif defined(CLOCK_MONOTONIC) 68*3ff40c12SJohn Marino static clockid_t clock_id = CLOCK_MONOTONIC; 69*3ff40c12SJohn Marino #else 70*3ff40c12SJohn Marino static clockid_t clock_id = CLOCK_REALTIME; 71*3ff40c12SJohn Marino #endif 72*3ff40c12SJohn Marino struct timespec ts; 73*3ff40c12SJohn Marino int res; 74*3ff40c12SJohn Marino 75*3ff40c12SJohn Marino while (1) { 76*3ff40c12SJohn Marino res = clock_gettime(clock_id, &ts); 77*3ff40c12SJohn Marino if (res == 0) { 78*3ff40c12SJohn Marino t->sec = ts.tv_sec; 79*3ff40c12SJohn Marino t->usec = ts.tv_nsec / 1000; 80*3ff40c12SJohn Marino return 0; 81*3ff40c12SJohn Marino } 82*3ff40c12SJohn Marino switch (clock_id) { 83*3ff40c12SJohn Marino #ifdef CLOCK_BOOTTIME 84*3ff40c12SJohn Marino case CLOCK_BOOTTIME: 85*3ff40c12SJohn Marino clock_id = CLOCK_MONOTONIC; 86*3ff40c12SJohn Marino break; 87*3ff40c12SJohn Marino #endif 88*3ff40c12SJohn Marino #ifdef CLOCK_MONOTONIC 89*3ff40c12SJohn Marino case CLOCK_MONOTONIC: 90*3ff40c12SJohn Marino clock_id = CLOCK_REALTIME; 91*3ff40c12SJohn Marino break; 92*3ff40c12SJohn Marino #endif 93*3ff40c12SJohn Marino case CLOCK_REALTIME: 94*3ff40c12SJohn Marino return -1; 95*3ff40c12SJohn Marino } 96*3ff40c12SJohn Marino } 97*3ff40c12SJohn Marino } 98*3ff40c12SJohn Marino 99*3ff40c12SJohn Marino 1006d49e1aeSJan Lentfer int os_mktime(int year, int month, int day, int hour, int min, int sec, 1016d49e1aeSJan Lentfer os_time_t *t) 1026d49e1aeSJan Lentfer { 1036d49e1aeSJan Lentfer struct tm tm, *tm1; 1046d49e1aeSJan Lentfer time_t t_local, t1, t2; 1056d49e1aeSJan Lentfer os_time_t tz_offset; 1066d49e1aeSJan Lentfer 1076d49e1aeSJan Lentfer if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 1086d49e1aeSJan Lentfer hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 1096d49e1aeSJan Lentfer sec > 60) 1106d49e1aeSJan Lentfer return -1; 1116d49e1aeSJan Lentfer 1126d49e1aeSJan Lentfer memset(&tm, 0, sizeof(tm)); 1136d49e1aeSJan Lentfer tm.tm_year = year - 1900; 1146d49e1aeSJan Lentfer tm.tm_mon = month - 1; 1156d49e1aeSJan Lentfer tm.tm_mday = day; 1166d49e1aeSJan Lentfer tm.tm_hour = hour; 1176d49e1aeSJan Lentfer tm.tm_min = min; 1186d49e1aeSJan Lentfer tm.tm_sec = sec; 1196d49e1aeSJan Lentfer 1206d49e1aeSJan Lentfer t_local = mktime(&tm); 1216d49e1aeSJan Lentfer 1226d49e1aeSJan Lentfer /* figure out offset to UTC */ 1236d49e1aeSJan Lentfer tm1 = localtime(&t_local); 1246d49e1aeSJan Lentfer if (tm1) { 1256d49e1aeSJan Lentfer t1 = mktime(tm1); 1266d49e1aeSJan Lentfer tm1 = gmtime(&t_local); 1276d49e1aeSJan Lentfer if (tm1) { 1286d49e1aeSJan Lentfer t2 = mktime(tm1); 1296d49e1aeSJan Lentfer tz_offset = t2 - t1; 1306d49e1aeSJan Lentfer } else 1316d49e1aeSJan Lentfer tz_offset = 0; 1326d49e1aeSJan Lentfer } else 1336d49e1aeSJan Lentfer tz_offset = 0; 1346d49e1aeSJan Lentfer 1356d49e1aeSJan Lentfer *t = (os_time_t) t_local - tz_offset; 1366d49e1aeSJan Lentfer return 0; 1376d49e1aeSJan Lentfer } 1386d49e1aeSJan Lentfer 1396d49e1aeSJan Lentfer 140*3ff40c12SJohn Marino int os_gmtime(os_time_t t, struct os_tm *tm) 141*3ff40c12SJohn Marino { 142*3ff40c12SJohn Marino struct tm *tm2; 143*3ff40c12SJohn Marino time_t t2 = t; 144*3ff40c12SJohn Marino 145*3ff40c12SJohn Marino tm2 = gmtime(&t2); 146*3ff40c12SJohn Marino if (tm2 == NULL) 147*3ff40c12SJohn Marino return -1; 148*3ff40c12SJohn Marino tm->sec = tm2->tm_sec; 149*3ff40c12SJohn Marino tm->min = tm2->tm_min; 150*3ff40c12SJohn Marino tm->hour = tm2->tm_hour; 151*3ff40c12SJohn Marino tm->day = tm2->tm_mday; 152*3ff40c12SJohn Marino tm->month = tm2->tm_mon + 1; 153*3ff40c12SJohn Marino tm->year = tm2->tm_year + 1900; 154*3ff40c12SJohn Marino return 0; 155*3ff40c12SJohn Marino } 156*3ff40c12SJohn Marino 157*3ff40c12SJohn Marino 1586d49e1aeSJan Lentfer #ifdef __APPLE__ 1596d49e1aeSJan Lentfer #include <fcntl.h> 1606d49e1aeSJan Lentfer static int os_daemon(int nochdir, int noclose) 1616d49e1aeSJan Lentfer { 1626d49e1aeSJan Lentfer int devnull; 1636d49e1aeSJan Lentfer 1646d49e1aeSJan Lentfer if (chdir("/") < 0) 1656d49e1aeSJan Lentfer return -1; 1666d49e1aeSJan Lentfer 1676d49e1aeSJan Lentfer devnull = open("/dev/null", O_RDWR); 1686d49e1aeSJan Lentfer if (devnull < 0) 1696d49e1aeSJan Lentfer return -1; 1706d49e1aeSJan Lentfer 1716d49e1aeSJan Lentfer if (dup2(devnull, STDIN_FILENO) < 0) { 1726d49e1aeSJan Lentfer close(devnull); 1736d49e1aeSJan Lentfer return -1; 1746d49e1aeSJan Lentfer } 1756d49e1aeSJan Lentfer 1766d49e1aeSJan Lentfer if (dup2(devnull, STDOUT_FILENO) < 0) { 1776d49e1aeSJan Lentfer close(devnull); 1786d49e1aeSJan Lentfer return -1; 1796d49e1aeSJan Lentfer } 1806d49e1aeSJan Lentfer 1816d49e1aeSJan Lentfer if (dup2(devnull, STDERR_FILENO) < 0) { 1826d49e1aeSJan Lentfer close(devnull); 1836d49e1aeSJan Lentfer return -1; 1846d49e1aeSJan Lentfer } 1856d49e1aeSJan Lentfer 1866d49e1aeSJan Lentfer return 0; 1876d49e1aeSJan Lentfer } 1886d49e1aeSJan Lentfer #else /* __APPLE__ */ 1896d49e1aeSJan Lentfer #define os_daemon daemon 1906d49e1aeSJan Lentfer #endif /* __APPLE__ */ 1916d49e1aeSJan Lentfer 1926d49e1aeSJan Lentfer 1936d49e1aeSJan Lentfer int os_daemonize(const char *pid_file) 1946d49e1aeSJan Lentfer { 195*3ff40c12SJohn Marino #if defined(__uClinux__) || defined(__sun__) 1966d49e1aeSJan Lentfer return -1; 197*3ff40c12SJohn Marino #else /* defined(__uClinux__) || defined(__sun__) */ 1986d49e1aeSJan Lentfer if (os_daemon(0, 0)) { 1996d49e1aeSJan Lentfer perror("daemon"); 2006d49e1aeSJan Lentfer return -1; 2016d49e1aeSJan Lentfer } 2026d49e1aeSJan Lentfer 2036d49e1aeSJan Lentfer if (pid_file) { 2046d49e1aeSJan Lentfer FILE *f = fopen(pid_file, "w"); 2056d49e1aeSJan Lentfer if (f) { 2066d49e1aeSJan Lentfer fprintf(f, "%u\n", getpid()); 2076d49e1aeSJan Lentfer fclose(f); 2086d49e1aeSJan Lentfer } 2096d49e1aeSJan Lentfer } 2106d49e1aeSJan Lentfer 2116d49e1aeSJan Lentfer return -0; 212*3ff40c12SJohn Marino #endif /* defined(__uClinux__) || defined(__sun__) */ 2136d49e1aeSJan Lentfer } 2146d49e1aeSJan Lentfer 2156d49e1aeSJan Lentfer 2166d49e1aeSJan Lentfer void os_daemonize_terminate(const char *pid_file) 2176d49e1aeSJan Lentfer { 2186d49e1aeSJan Lentfer if (pid_file) 2196d49e1aeSJan Lentfer unlink(pid_file); 2206d49e1aeSJan Lentfer } 2216d49e1aeSJan Lentfer 2226d49e1aeSJan Lentfer 2236d49e1aeSJan Lentfer int os_get_random(unsigned char *buf, size_t len) 2246d49e1aeSJan Lentfer { 2256d49e1aeSJan Lentfer FILE *f; 2266d49e1aeSJan Lentfer size_t rc; 2276d49e1aeSJan Lentfer 2286d49e1aeSJan Lentfer f = fopen("/dev/urandom", "rb"); 2296d49e1aeSJan Lentfer if (f == NULL) { 2306d49e1aeSJan Lentfer printf("Could not open /dev/urandom.\n"); 2316d49e1aeSJan Lentfer return -1; 2326d49e1aeSJan Lentfer } 2336d49e1aeSJan Lentfer 2346d49e1aeSJan Lentfer rc = fread(buf, 1, len, f); 2356d49e1aeSJan Lentfer fclose(f); 2366d49e1aeSJan Lentfer 2376d49e1aeSJan Lentfer return rc != len ? -1 : 0; 2386d49e1aeSJan Lentfer } 2396d49e1aeSJan Lentfer 2406d49e1aeSJan Lentfer 2416d49e1aeSJan Lentfer unsigned long os_random(void) 2426d49e1aeSJan Lentfer { 2436d49e1aeSJan Lentfer return random(); 2446d49e1aeSJan Lentfer } 2456d49e1aeSJan Lentfer 2466d49e1aeSJan Lentfer 2476d49e1aeSJan Lentfer char * os_rel2abs_path(const char *rel_path) 2486d49e1aeSJan Lentfer { 2496d49e1aeSJan Lentfer char *buf = NULL, *cwd, *ret; 2506d49e1aeSJan Lentfer size_t len = 128, cwd_len, rel_len, ret_len; 2516d49e1aeSJan Lentfer int last_errno; 2526d49e1aeSJan Lentfer 253*3ff40c12SJohn Marino if (!rel_path) 254*3ff40c12SJohn Marino return NULL; 255*3ff40c12SJohn Marino 2566d49e1aeSJan Lentfer if (rel_path[0] == '/') 257*3ff40c12SJohn Marino return os_strdup(rel_path); 2586d49e1aeSJan Lentfer 2596d49e1aeSJan Lentfer for (;;) { 260*3ff40c12SJohn Marino buf = os_malloc(len); 2616d49e1aeSJan Lentfer if (buf == NULL) 2626d49e1aeSJan Lentfer return NULL; 2636d49e1aeSJan Lentfer cwd = getcwd(buf, len); 2646d49e1aeSJan Lentfer if (cwd == NULL) { 2656d49e1aeSJan Lentfer last_errno = errno; 266*3ff40c12SJohn Marino os_free(buf); 2676d49e1aeSJan Lentfer if (last_errno != ERANGE) 2686d49e1aeSJan Lentfer return NULL; 2696d49e1aeSJan Lentfer len *= 2; 2706d49e1aeSJan Lentfer if (len > 2000) 2716d49e1aeSJan Lentfer return NULL; 2726d49e1aeSJan Lentfer } else { 2736d49e1aeSJan Lentfer buf[len - 1] = '\0'; 2746d49e1aeSJan Lentfer break; 2756d49e1aeSJan Lentfer } 2766d49e1aeSJan Lentfer } 2776d49e1aeSJan Lentfer 278*3ff40c12SJohn Marino cwd_len = os_strlen(cwd); 279*3ff40c12SJohn Marino rel_len = os_strlen(rel_path); 2806d49e1aeSJan Lentfer ret_len = cwd_len + 1 + rel_len + 1; 281*3ff40c12SJohn Marino ret = os_malloc(ret_len); 2826d49e1aeSJan Lentfer if (ret) { 283*3ff40c12SJohn Marino os_memcpy(ret, cwd, cwd_len); 2846d49e1aeSJan Lentfer ret[cwd_len] = '/'; 285*3ff40c12SJohn Marino os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 2866d49e1aeSJan Lentfer ret[ret_len - 1] = '\0'; 2876d49e1aeSJan Lentfer } 288*3ff40c12SJohn Marino os_free(buf); 2896d49e1aeSJan Lentfer return ret; 2906d49e1aeSJan Lentfer } 2916d49e1aeSJan Lentfer 2926d49e1aeSJan Lentfer 2936d49e1aeSJan Lentfer int os_program_init(void) 2946d49e1aeSJan Lentfer { 295*3ff40c12SJohn Marino #ifdef ANDROID 296*3ff40c12SJohn Marino /* 297*3ff40c12SJohn Marino * We ignore errors here since errors are normal if we 298*3ff40c12SJohn Marino * are already running as non-root. 299*3ff40c12SJohn Marino */ 300*3ff40c12SJohn Marino #ifdef ANDROID_SETGROUPS_OVERRIDE 301*3ff40c12SJohn Marino gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE }; 302*3ff40c12SJohn Marino #else /* ANDROID_SETGROUPS_OVERRIDE */ 303*3ff40c12SJohn Marino gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE }; 304*3ff40c12SJohn Marino #endif /* ANDROID_SETGROUPS_OVERRIDE */ 305*3ff40c12SJohn Marino struct __user_cap_header_struct header; 306*3ff40c12SJohn Marino struct __user_cap_data_struct cap; 307*3ff40c12SJohn Marino 308*3ff40c12SJohn Marino setgroups(ARRAY_SIZE(groups), groups); 309*3ff40c12SJohn Marino 310*3ff40c12SJohn Marino prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 311*3ff40c12SJohn Marino 312*3ff40c12SJohn Marino setgid(AID_WIFI); 313*3ff40c12SJohn Marino setuid(AID_WIFI); 314*3ff40c12SJohn Marino 315*3ff40c12SJohn Marino header.version = _LINUX_CAPABILITY_VERSION; 316*3ff40c12SJohn Marino header.pid = 0; 317*3ff40c12SJohn Marino cap.effective = cap.permitted = 318*3ff40c12SJohn Marino (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW); 319*3ff40c12SJohn Marino cap.inheritable = 0; 320*3ff40c12SJohn Marino capset(&header, &cap); 321*3ff40c12SJohn Marino #endif /* ANDROID */ 322*3ff40c12SJohn Marino 323*3ff40c12SJohn Marino #ifdef WPA_TRACE 324*3ff40c12SJohn Marino dl_list_init(&alloc_list); 325*3ff40c12SJohn Marino #endif /* WPA_TRACE */ 3266d49e1aeSJan Lentfer return 0; 3276d49e1aeSJan Lentfer } 3286d49e1aeSJan Lentfer 3296d49e1aeSJan Lentfer 3306d49e1aeSJan Lentfer void os_program_deinit(void) 3316d49e1aeSJan Lentfer { 332*3ff40c12SJohn Marino #ifdef WPA_TRACE 333*3ff40c12SJohn Marino struct os_alloc_trace *a; 334*3ff40c12SJohn Marino unsigned long total = 0; 335*3ff40c12SJohn Marino dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) { 336*3ff40c12SJohn Marino total += a->len; 337*3ff40c12SJohn Marino if (a->magic != ALLOC_MAGIC) { 338*3ff40c12SJohn Marino wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x " 339*3ff40c12SJohn Marino "len %lu", 340*3ff40c12SJohn Marino a, a->magic, (unsigned long) a->len); 341*3ff40c12SJohn Marino continue; 342*3ff40c12SJohn Marino } 343*3ff40c12SJohn Marino wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu", 344*3ff40c12SJohn Marino a, (unsigned long) a->len); 345*3ff40c12SJohn Marino wpa_trace_dump("memleak", a); 346*3ff40c12SJohn Marino } 347*3ff40c12SJohn Marino if (total) 348*3ff40c12SJohn Marino wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes", 349*3ff40c12SJohn Marino (unsigned long) total); 350*3ff40c12SJohn Marino #endif /* WPA_TRACE */ 3516d49e1aeSJan Lentfer } 3526d49e1aeSJan Lentfer 3536d49e1aeSJan Lentfer 3546d49e1aeSJan Lentfer int os_setenv(const char *name, const char *value, int overwrite) 3556d49e1aeSJan Lentfer { 3566d49e1aeSJan Lentfer return setenv(name, value, overwrite); 3576d49e1aeSJan Lentfer } 3586d49e1aeSJan Lentfer 3596d49e1aeSJan Lentfer 3606d49e1aeSJan Lentfer int os_unsetenv(const char *name) 3616d49e1aeSJan Lentfer { 3626d49e1aeSJan Lentfer #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ 3636d49e1aeSJan Lentfer defined(__OpenBSD__) 3646d49e1aeSJan Lentfer unsetenv(name); 3656d49e1aeSJan Lentfer return 0; 3666d49e1aeSJan Lentfer #else 3676d49e1aeSJan Lentfer return unsetenv(name); 3686d49e1aeSJan Lentfer #endif 3696d49e1aeSJan Lentfer } 3706d49e1aeSJan Lentfer 3716d49e1aeSJan Lentfer 3726d49e1aeSJan Lentfer char * os_readfile(const char *name, size_t *len) 3736d49e1aeSJan Lentfer { 3746d49e1aeSJan Lentfer FILE *f; 3756d49e1aeSJan Lentfer char *buf; 376*3ff40c12SJohn Marino long pos; 3776d49e1aeSJan Lentfer 3786d49e1aeSJan Lentfer f = fopen(name, "rb"); 3796d49e1aeSJan Lentfer if (f == NULL) 3806d49e1aeSJan Lentfer return NULL; 3816d49e1aeSJan Lentfer 382*3ff40c12SJohn Marino if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) { 383*3ff40c12SJohn Marino fclose(f); 384*3ff40c12SJohn Marino return NULL; 385*3ff40c12SJohn Marino } 386*3ff40c12SJohn Marino *len = pos; 387*3ff40c12SJohn Marino if (fseek(f, 0, SEEK_SET) < 0) { 388*3ff40c12SJohn Marino fclose(f); 389*3ff40c12SJohn Marino return NULL; 390*3ff40c12SJohn Marino } 3916d49e1aeSJan Lentfer 392*3ff40c12SJohn Marino buf = os_malloc(*len); 3936d49e1aeSJan Lentfer if (buf == NULL) { 3946d49e1aeSJan Lentfer fclose(f); 3956d49e1aeSJan Lentfer return NULL; 3966d49e1aeSJan Lentfer } 3976d49e1aeSJan Lentfer 3986d49e1aeSJan Lentfer if (fread(buf, 1, *len, f) != *len) { 3996d49e1aeSJan Lentfer fclose(f); 400*3ff40c12SJohn Marino os_free(buf); 4016d49e1aeSJan Lentfer return NULL; 4026d49e1aeSJan Lentfer } 4036d49e1aeSJan Lentfer 4046d49e1aeSJan Lentfer fclose(f); 4056d49e1aeSJan Lentfer 4066d49e1aeSJan Lentfer return buf; 4076d49e1aeSJan Lentfer } 4086d49e1aeSJan Lentfer 4096d49e1aeSJan Lentfer 410*3ff40c12SJohn Marino #ifndef WPA_TRACE 4116d49e1aeSJan Lentfer void * os_zalloc(size_t size) 4126d49e1aeSJan Lentfer { 4136d49e1aeSJan Lentfer return calloc(1, size); 4146d49e1aeSJan Lentfer } 415*3ff40c12SJohn Marino #endif /* WPA_TRACE */ 4166d49e1aeSJan Lentfer 4176d49e1aeSJan Lentfer 4186d49e1aeSJan Lentfer size_t os_strlcpy(char *dest, const char *src, size_t siz) 4196d49e1aeSJan Lentfer { 4206d49e1aeSJan Lentfer const char *s = src; 4216d49e1aeSJan Lentfer size_t left = siz; 4226d49e1aeSJan Lentfer 4236d49e1aeSJan Lentfer if (left) { 4246d49e1aeSJan Lentfer /* Copy string up to the maximum size of the dest buffer */ 4256d49e1aeSJan Lentfer while (--left != 0) { 4266d49e1aeSJan Lentfer if ((*dest++ = *s++) == '\0') 4276d49e1aeSJan Lentfer break; 4286d49e1aeSJan Lentfer } 4296d49e1aeSJan Lentfer } 4306d49e1aeSJan Lentfer 4316d49e1aeSJan Lentfer if (left == 0) { 4326d49e1aeSJan Lentfer /* Not enough room for the string; force NUL-termination */ 4336d49e1aeSJan Lentfer if (siz != 0) 4346d49e1aeSJan Lentfer *dest = '\0'; 4356d49e1aeSJan Lentfer while (*s++) 4366d49e1aeSJan Lentfer ; /* determine total src string length */ 4376d49e1aeSJan Lentfer } 4386d49e1aeSJan Lentfer 4396d49e1aeSJan Lentfer return s - src - 1; 4406d49e1aeSJan Lentfer } 441*3ff40c12SJohn Marino 442*3ff40c12SJohn Marino 443*3ff40c12SJohn Marino #ifdef WPA_TRACE 444*3ff40c12SJohn Marino 445*3ff40c12SJohn Marino void * os_malloc(size_t size) 446*3ff40c12SJohn Marino { 447*3ff40c12SJohn Marino struct os_alloc_trace *a; 448*3ff40c12SJohn Marino a = malloc(sizeof(*a) + size); 449*3ff40c12SJohn Marino if (a == NULL) 450*3ff40c12SJohn Marino return NULL; 451*3ff40c12SJohn Marino a->magic = ALLOC_MAGIC; 452*3ff40c12SJohn Marino dl_list_add(&alloc_list, &a->list); 453*3ff40c12SJohn Marino a->len = size; 454*3ff40c12SJohn Marino wpa_trace_record(a); 455*3ff40c12SJohn Marino return a + 1; 456*3ff40c12SJohn Marino } 457*3ff40c12SJohn Marino 458*3ff40c12SJohn Marino 459*3ff40c12SJohn Marino void * os_realloc(void *ptr, size_t size) 460*3ff40c12SJohn Marino { 461*3ff40c12SJohn Marino struct os_alloc_trace *a; 462*3ff40c12SJohn Marino size_t copy_len; 463*3ff40c12SJohn Marino void *n; 464*3ff40c12SJohn Marino 465*3ff40c12SJohn Marino if (ptr == NULL) 466*3ff40c12SJohn Marino return os_malloc(size); 467*3ff40c12SJohn Marino 468*3ff40c12SJohn Marino a = (struct os_alloc_trace *) ptr - 1; 469*3ff40c12SJohn Marino if (a->magic != ALLOC_MAGIC) { 470*3ff40c12SJohn Marino wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s", 471*3ff40c12SJohn Marino a, a->magic, 472*3ff40c12SJohn Marino a->magic == FREED_MAGIC ? " (already freed)" : ""); 473*3ff40c12SJohn Marino wpa_trace_show("Invalid os_realloc() call"); 474*3ff40c12SJohn Marino abort(); 475*3ff40c12SJohn Marino } 476*3ff40c12SJohn Marino n = os_malloc(size); 477*3ff40c12SJohn Marino if (n == NULL) 478*3ff40c12SJohn Marino return NULL; 479*3ff40c12SJohn Marino copy_len = a->len; 480*3ff40c12SJohn Marino if (copy_len > size) 481*3ff40c12SJohn Marino copy_len = size; 482*3ff40c12SJohn Marino os_memcpy(n, a + 1, copy_len); 483*3ff40c12SJohn Marino os_free(ptr); 484*3ff40c12SJohn Marino return n; 485*3ff40c12SJohn Marino } 486*3ff40c12SJohn Marino 487*3ff40c12SJohn Marino 488*3ff40c12SJohn Marino void os_free(void *ptr) 489*3ff40c12SJohn Marino { 490*3ff40c12SJohn Marino struct os_alloc_trace *a; 491*3ff40c12SJohn Marino 492*3ff40c12SJohn Marino if (ptr == NULL) 493*3ff40c12SJohn Marino return; 494*3ff40c12SJohn Marino a = (struct os_alloc_trace *) ptr - 1; 495*3ff40c12SJohn Marino if (a->magic != ALLOC_MAGIC) { 496*3ff40c12SJohn Marino wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s", 497*3ff40c12SJohn Marino a, a->magic, 498*3ff40c12SJohn Marino a->magic == FREED_MAGIC ? " (already freed)" : ""); 499*3ff40c12SJohn Marino wpa_trace_show("Invalid os_free() call"); 500*3ff40c12SJohn Marino abort(); 501*3ff40c12SJohn Marino } 502*3ff40c12SJohn Marino dl_list_del(&a->list); 503*3ff40c12SJohn Marino a->magic = FREED_MAGIC; 504*3ff40c12SJohn Marino 505*3ff40c12SJohn Marino wpa_trace_check_ref(ptr); 506*3ff40c12SJohn Marino free(a); 507*3ff40c12SJohn Marino } 508*3ff40c12SJohn Marino 509*3ff40c12SJohn Marino 510*3ff40c12SJohn Marino void * os_zalloc(size_t size) 511*3ff40c12SJohn Marino { 512*3ff40c12SJohn Marino void *ptr = os_malloc(size); 513*3ff40c12SJohn Marino if (ptr) 514*3ff40c12SJohn Marino os_memset(ptr, 0, size); 515*3ff40c12SJohn Marino return ptr; 516*3ff40c12SJohn Marino } 517*3ff40c12SJohn Marino 518*3ff40c12SJohn Marino 519*3ff40c12SJohn Marino char * os_strdup(const char *s) 520*3ff40c12SJohn Marino { 521*3ff40c12SJohn Marino size_t len; 522*3ff40c12SJohn Marino char *d; 523*3ff40c12SJohn Marino len = os_strlen(s); 524*3ff40c12SJohn Marino d = os_malloc(len + 1); 525*3ff40c12SJohn Marino if (d == NULL) 526*3ff40c12SJohn Marino return NULL; 527*3ff40c12SJohn Marino os_memcpy(d, s, len); 528*3ff40c12SJohn Marino d[len] = '\0'; 529*3ff40c12SJohn Marino return d; 530*3ff40c12SJohn Marino } 531*3ff40c12SJohn Marino 532*3ff40c12SJohn Marino #endif /* WPA_TRACE */ 533